Loading...
1/*
2 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
3 *
4 * Main part
5 *
6 * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
7 *
8 * If distributed as part of the Linux kernel, this code is licensed under the
9 * terms of the GPL v2.
10 *
11 * Otherwise, the following license terms apply:
12 *
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.
34 *
35 * Author: Thomas Winischhofer <thomas@winischhofer.net>
36 *
37 */
38
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>
51
52#include "sisusb.h"
53#include "sisusb_init.h"
54
55#ifdef INCL_SISUSB_CON
56#include <linux/font.h>
57#endif
58
59#define SISUSB_DONTSYNC
60
61/* Forward declarations / clean-up routines */
62
63#ifdef INCL_SISUSB_CON
64static int sisusb_first_vc;
65static int sisusb_last_vc;
66module_param_named(first, sisusb_first_vc, int, 0);
67module_param_named(last, sisusb_last_vc, int, 0);
68MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
69MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
70#endif
71
72static struct usb_driver sisusb_driver;
73
74static void sisusb_free_buffers(struct sisusb_usb_data *sisusb)
75{
76 int i;
77
78 for (i = 0; i < NUMOBUFS; i++) {
79 kfree(sisusb->obuf[i]);
80 sisusb->obuf[i] = NULL;
81 }
82 kfree(sisusb->ibuf);
83 sisusb->ibuf = NULL;
84}
85
86static void sisusb_free_urbs(struct sisusb_usb_data *sisusb)
87{
88 int i;
89
90 for (i = 0; i < NUMOBUFS; i++) {
91 usb_free_urb(sisusb->sisurbout[i]);
92 sisusb->sisurbout[i] = NULL;
93 }
94 usb_free_urb(sisusb->sisurbin);
95 sisusb->sisurbin = NULL;
96}
97
98/* Level 0: USB transport layer */
99
100/* 1. out-bulks */
101
102/* out-urb management */
103
104/* Return 1 if all free, 0 otherwise */
105static int sisusb_all_free(struct sisusb_usb_data *sisusb)
106{
107 int i;
108
109 for (i = 0; i < sisusb->numobufs; i++) {
110
111 if (sisusb->urbstatus[i] & SU_URB_BUSY)
112 return 0;
113
114 }
115
116 return 1;
117}
118
119/* Kill all busy URBs */
120static void sisusb_kill_all_busy(struct sisusb_usb_data *sisusb)
121{
122 int i;
123
124 if (sisusb_all_free(sisusb))
125 return;
126
127 for (i = 0; i < sisusb->numobufs; i++) {
128
129 if (sisusb->urbstatus[i] & SU_URB_BUSY)
130 usb_kill_urb(sisusb->sisurbout[i]);
131
132 }
133}
134
135/* Return 1 if ok, 0 if error (not all complete within timeout) */
136static int sisusb_wait_all_out_complete(struct sisusb_usb_data *sisusb)
137{
138 int timeout = 5 * HZ, i = 1;
139
140 wait_event_timeout(sisusb->wait_q, (i = sisusb_all_free(sisusb)),
141 timeout);
142
143 return i;
144}
145
146static int sisusb_outurb_available(struct sisusb_usb_data *sisusb)
147{
148 int i;
149
150 for (i = 0; i < sisusb->numobufs; i++) {
151
152 if ((sisusb->urbstatus[i] & (SU_URB_BUSY|SU_URB_ALLOC)) == 0)
153 return i;
154
155 }
156
157 return -1;
158}
159
160static int sisusb_get_free_outbuf(struct sisusb_usb_data *sisusb)
161{
162 int i, timeout = 5 * HZ;
163
164 wait_event_timeout(sisusb->wait_q,
165 ((i = sisusb_outurb_available(sisusb)) >= 0), timeout);
166
167 return i;
168}
169
170static int sisusb_alloc_outbuf(struct sisusb_usb_data *sisusb)
171{
172 int i;
173
174 i = sisusb_outurb_available(sisusb);
175
176 if (i >= 0)
177 sisusb->urbstatus[i] |= SU_URB_ALLOC;
178
179 return i;
180}
181
182static void sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index)
183{
184 if ((index >= 0) && (index < sisusb->numobufs))
185 sisusb->urbstatus[index] &= ~SU_URB_ALLOC;
186}
187
188/* completion callback */
189
190static void sisusb_bulk_completeout(struct urb *urb)
191{
192 struct sisusb_urb_context *context = urb->context;
193 struct sisusb_usb_data *sisusb;
194
195 if (!context)
196 return;
197
198 sisusb = context->sisusb;
199
200 if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
201 return;
202
203#ifndef SISUSB_DONTSYNC
204 if (context->actual_length)
205 *(context->actual_length) += urb->actual_length;
206#endif
207
208 sisusb->urbstatus[context->urbindex] &= ~SU_URB_BUSY;
209 wake_up(&sisusb->wait_q);
210}
211
212static 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)
215{
216 struct urb *urb = sisusb->sisurbout[index];
217 int retval, byteswritten = 0;
218
219 /* Set up URB */
220 urb->transfer_flags = 0;
221
222 usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
223 sisusb_bulk_completeout,
224 &sisusb->urbout_context[index]);
225
226 urb->transfer_flags |= tflags;
227 urb->actual_length = 0;
228
229 /* Set up context */
230 sisusb->urbout_context[index].actual_length = (timeout) ?
231 NULL : actual_length;
232
233 /* Declare this urb/buffer in use */
234 sisusb->urbstatus[index] |= SU_URB_BUSY;
235
236 /* Submit URB */
237 retval = usb_submit_urb(urb, GFP_KERNEL);
238
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;
252 }
253 }
254
255 if (actual_length)
256 *actual_length = byteswritten;
257
258 return retval;
259}
260
261/* 2. in-bulks */
262
263/* completion callback */
264
265static void sisusb_bulk_completein(struct urb *urb)
266{
267 struct sisusb_usb_data *sisusb = urb->context;
268
269 if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
270 return;
271
272 sisusb->completein = 1;
273 wake_up(&sisusb->wait_q);
274}
275
276static 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)
279{
280 struct urb *urb = sisusb->sisurbin;
281 int retval, readbytes = 0;
282
283 urb->transfer_flags = 0;
284
285 usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
286 sisusb_bulk_completein, sisusb);
287
288 urb->transfer_flags |= tflags;
289 urb->actual_length = 0;
290
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;
303 }
304 }
305
306 if (actual_length)
307 *actual_length = readbytes;
308
309 return retval;
310}
311
312
313/* Level 1: */
314
315/* Send a bulk message of variable size
316 *
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.
324 *
325 * (return 0 on success)
326 */
327
328static 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)
331{
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;
338
339 (*bytes_written) = 0;
340
341 /* Sanity check */
342 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
343 return -ENODEV;
344
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.)
352 */
353 if (fromuser || fromkern)
354 index = -1;
355 else if (len > sisusb->obufsize)
356 async = 0;
357
358 pipe = usb_sndbulkpipe(sisusb->sisusb_dev, ep);
359
360 do {
361 passsize = thispass = (sisusb->obufsize < count) ?
362 sisusb->obufsize : count;
363
364 if (index < 0)
365 index = sisusb_get_free_outbuf(sisusb);
366
367 if (index < 0)
368 return -EIO;
369
370 buffer = sisusb->obuf[index];
371
372 if (fromuser) {
373
374 if (copy_from_user(buffer, userbuffer, passsize))
375 return -EFAULT;
376
377 userbuffer += passsize;
378
379 } else if (fromkern) {
380
381 memcpy(buffer, kernbuffer, passsize);
382 kernbuffer += passsize;
383
384 }
385
386 retry = 5;
387 while (thispass) {
388
389 if (!sisusb->sisusb_dev)
390 return -ENODEV;
391
392 result = sisusb_bulkout_msg(sisusb, index, pipe,
393 buffer, thispass, &transferred_len,
394 async ? 0 : 5 * HZ, tflags);
395
396 if (result == -ETIMEDOUT) {
397
398 /* Will not happen if async */
399 if (!retry--)
400 return -ETIME;
401
402 continue;
403 }
404
405 if ((result == 0) && !async && transferred_len) {
406
407 thispass -= transferred_len;
408 buffer += transferred_len;
409
410 } else
411 break;
412 }
413
414 if (result)
415 return result;
416
417 (*bytes_written) += passsize;
418 count -= passsize;
419
420 /* Force new allocation in next iteration */
421 if (fromuser || fromkern)
422 index = -1;
423
424 } while (count > 0);
425
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
435 }
436
437 return ((*bytes_written) == len) ? 0 : -EIO;
438}
439
440/* Receive a bulk message of variable size
441 *
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.)
446 *
447 */
448
449static 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)
452{
453 int result = 0, retry, count = len;
454 int bufsize, thispass, transferred_len;
455 unsigned int pipe;
456 char *buffer;
457
458 (*bytes_read) = 0;
459
460 /* Sanity check */
461 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
462 return -ENODEV;
463
464 pipe = usb_rcvbulkpipe(sisusb->sisusb_dev, ep);
465 buffer = sisusb->ibuf;
466 bufsize = sisusb->ibufsize;
467
468 retry = 5;
469
470#ifdef SISUSB_DONTSYNC
471 if (!(sisusb_wait_all_out_complete(sisusb)))
472 return -EIO;
473#endif
474
475 while (count > 0) {
476
477 if (!sisusb->sisusb_dev)
478 return -ENODEV;
479
480 thispass = (bufsize < count) ? bufsize : count;
481
482 result = sisusb_bulkin_msg(sisusb, pipe, buffer, thispass,
483 &transferred_len, 5 * HZ, tflags);
484
485 if (transferred_len)
486 thispass = transferred_len;
487
488 else if (result == -ETIMEDOUT) {
489
490 if (!retry--)
491 return -ETIME;
492
493 continue;
494
495 } else
496 return -EIO;
497
498
499 if (thispass) {
500
501 (*bytes_read) += thispass;
502 count -= thispass;
503
504 if (userbuffer) {
505
506 if (copy_to_user(userbuffer, buffer, thispass))
507 return -EFAULT;
508
509 userbuffer += thispass;
510
511 } else {
512
513 memcpy(kernbuffer, buffer, thispass);
514 kernbuffer += thispass;
515
516 }
517
518 }
519
520 }
521
522 return ((*bytes_read) == len) ? 0 : -EIO;
523}
524
525static int sisusb_send_packet(struct sisusb_usb_data *sisusb, int len,
526 struct sisusb_packet *packet)
527{
528 int ret;
529 ssize_t bytes_transferred = 0;
530 __le32 tmp;
531
532 if (len == 6)
533 packet->data = 0;
534
535#ifdef SISUSB_DONTSYNC
536 if (!(sisusb_wait_all_out_complete(sisusb)))
537 return 1;
538#endif
539
540 /* Eventually correct endianness */
541 SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
542
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);
546
547 if ((ret == 0) && (len == 6)) {
548
549 /* 2. if packet len == 6, it means we read, so wait for 32bit
550 * return value and write it to packet->data
551 */
552 ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_GFX_IN, 4,
553 (char *)&tmp, NULL, &bytes_transferred, 0);
554
555 packet->data = le32_to_cpu(tmp);
556 }
557
558 return ret;
559}
560
561static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
562 struct sisusb_packet *packet, unsigned int tflags)
563{
564 int ret;
565 ssize_t bytes_transferred = 0;
566 __le32 tmp;
567
568 if (len == 6)
569 packet->data = 0;
570
571#ifdef SISUSB_DONTSYNC
572 if (!(sisusb_wait_all_out_complete(sisusb)))
573 return 1;
574#endif
575
576 /* Eventually correct endianness */
577 SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
578
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);
582
583 if ((ret == 0) && (len == 6)) {
584
585 /* 2. if packet len == 6, it means we read, so wait for 32bit
586 * return value and write it to packet->data
587 */
588 ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_BRIDGE_IN, 4,
589 (char *)&tmp, NULL, &bytes_transferred, 0);
590
591 packet->data = le32_to_cpu(tmp);
592 }
593
594 return ret;
595}
596
597/* access video memory and mmio (return 0 on success) */
598
599/* Low level */
600
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.
607 */
608
609static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,
610 u32 addr, u8 data)
611{
612 struct sisusb_packet packet;
613 int ret;
614
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;
620}
621
622static int sisusb_write_memio_word(struct sisusb_usb_data *sisusb, int type,
623 u32 addr, u16 data)
624{
625 struct sisusb_packet packet;
626 int ret = 0;
627
628 packet.address = addr & ~3;
629
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);
654 }
655
656 return ret;
657}
658
659static int sisusb_write_memio_24bit(struct sisusb_usb_data *sisusb, int type,
660 u32 addr, u32 data)
661{
662 struct sisusb_packet packet;
663 int ret = 0;
664
665 packet.address = addr & ~3;
666
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);
695 }
696
697 return ret;
698}
699
700static int sisusb_write_memio_long(struct sisusb_usb_data *sisusb, int type,
701 u32 addr, u32 data)
702{
703 struct sisusb_packet packet;
704 int ret = 0;
705
706 packet.address = addr & ~3;
707
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);
740 }
741
742 return ret;
743}
744
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
748 *
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]".
753 */
754
755static 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)
758{
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];
766
767 /* if neither kernbuffer not userbuffer are given, assume
768 * data in obuf
769 */
770 if (!fromkern && !userbuffer)
771 kernbuffer = sisusb->obuf[index];
772
773 (*bytes_written = 0);
774
775 length &= 0x00ffffff;
776
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];
785
786 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM,
787 addr, swap8);
788
789 if (!ret)
790 (*bytes_written)++;
791
792 return ret;
793
794 case 2:
795 if (userbuffer) {
796 if (get_user(swap16, (u16 __user *)userbuffer))
797 return -EFAULT;
798 } else
799 swap16 = *((u16 *)kernbuffer);
800
801 ret = sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
802 addr, swap16);
803
804 if (!ret)
805 (*bytes_written) += 2;
806
807 return ret;
808
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
832
833 ret = sisusb_write_memio_24bit(sisusb, SISUSB_TYPE_MEM,
834 addr, swap32);
835
836 if (!ret)
837 (*bytes_written) += 3;
838
839 return ret;
840
841 case 4:
842 if (userbuffer) {
843 if (get_user(swap32, (u32 __user *)userbuffer))
844 return -EFAULT;
845 } else
846 swap32 = *((u32 *)kernbuffer);
847
848 ret = sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM,
849 addr, swap32);
850 if (!ret)
851 (*bytes_written) += 4;
852
853 return ret;
854
855 default:
856 if ((length & ~3) > 0x10000) {
857
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));
895 }
896
897 } else {
898
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;
916 }
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));
939 }
940 }
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");
951 }
952 addr += (*bytes_written);
953 length -= (*bytes_written);
954 }
955
956 if (ret)
957 break;
958
959 }
960
961 return ret ? -EIO : 0;
962}
963
964/* Remember: Read data in packet is in machine-endianess! So for
965 * byte, word, 24bit, long no endian correction is necessary.
966 */
967
968static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
969 u32 addr, u8 *data)
970{
971 struct sisusb_packet packet;
972 int ret;
973
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;
980}
981
982static int sisusb_read_memio_word(struct sisusb_usb_data *sisusb, int type,
983 u32 addr, u16 *data)
984{
985 struct sisusb_packet packet;
986 int ret = 0;
987
988 CLEARPACKET(&packet);
989
990 packet.address = addr & ~3;
991
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);
1016 }
1017
1018 return ret;
1019}
1020
1021static int sisusb_read_memio_24bit(struct sisusb_usb_data *sisusb, int type,
1022 u32 addr, u32 *data)
1023{
1024 struct sisusb_packet packet;
1025 int ret = 0;
1026
1027 packet.address = addr & ~3;
1028
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);
1057 }
1058
1059 return ret;
1060}
1061
1062static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type,
1063 u32 addr, u32 *data)
1064{
1065 struct sisusb_packet packet;
1066 int ret = 0;
1067
1068 packet.address = addr & ~3;
1069
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);
1102 }
1103
1104 return ret;
1105}
1106
1107static 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)
1110{
1111 int ret = 0;
1112 char buf[4];
1113 u16 swap16;
1114 u32 swap32;
1115
1116 (*bytes_read = 0);
1117
1118 length &= 0x00ffffff;
1119
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];
1132 }
1133 return ret;
1134
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;
1145 }
1146 }
1147 return ret;
1148
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];
1171 }
1172 }
1173 return ret;
1174
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;
1183
1184 userbuffer += 4;
1185 } else {
1186 *((u32 *)kernbuffer) = swap32;
1187 kernbuffer += 4;
1188 }
1189 addr += 4;
1190 length -= 4;
1191 }
1192 }
1193 if (ret)
1194 break;
1195 }
1196
1197 return ret;
1198}
1199
1200/* High level: Gfx (indexed) register access */
1201
1202#ifdef INCL_SISUSB_CON
1203int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data)
1204{
1205 return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1206}
1207
1208int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data)
1209{
1210 return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1211}
1212#endif
1213
1214int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port,
1215 u8 index, u8 data)
1216{
1217 int ret;
1218
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;
1222}
1223
1224int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port,
1225 u8 index, u8 *data)
1226{
1227 int ret;
1228
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;
1232}
1233
1234int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
1235 u8 myand, u8 myor)
1236{
1237 int ret;
1238 u8 tmp;
1239
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;
1246}
1247
1248static int sisusb_setidxregmask(struct sisusb_usb_data *sisusb,
1249 int port, u8 idx, u8 data, u8 mask)
1250{
1251 int ret;
1252 u8 tmp;
1253
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;
1260}
1261
1262int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port,
1263 u8 index, u8 myor)
1264{
1265 return sisusb_setidxregandor(sisusb, port, index, 0xff, myor);
1266}
1267
1268int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port,
1269 u8 idx, u8 myand)
1270{
1271 return sisusb_setidxregandor(sisusb, port, idx, myand, 0x00);
1272}
1273
1274/* Write/read video ram */
1275
1276#ifdef INCL_SISUSB_CON
1277int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data)
1278{
1279 return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data);
1280}
1281
1282int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)
1283{
1284 return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data);
1285}
1286
1287int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
1288 u32 dest, int length, size_t *bytes_written)
1289{
1290 return sisusb_write_mem_bulk(sisusb, dest, src, length,
1291 NULL, 0, bytes_written);
1292}
1293
1294#ifdef SISUSBENDIANTEST
1295int sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
1296 u32 src, int length, size_t *bytes_written)
1297{
1298 return sisusb_read_mem_bulk(sisusb, src, dest, length,
1299 NULL, bytes_written);
1300}
1301#endif
1302#endif
1303
1304#ifdef SISUSBENDIANTEST
1305static void sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
1306{
1307 static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1308 char destbuffer[10];
1309 size_t dummy;
1310 int i, j;
1311
1312 sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy);
1313
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]);
1323 }
1324 }
1325}
1326#endif
1327
1328/* access pci config registers (reg numbers 0, 4, 8, etc) */
1329
1330static int sisusb_write_pci_config(struct sisusb_usb_data *sisusb,
1331 int regnum, u32 data)
1332{
1333 struct sisusb_packet packet;
1334 int ret;
1335
1336 packet.header = 0x008f;
1337 packet.address = regnum | 0x10000;
1338 packet.data = data;
1339 ret = sisusb_send_packet(sisusb, 10, &packet);
1340 return ret;
1341}
1342
1343static int sisusb_read_pci_config(struct sisusb_usb_data *sisusb,
1344 int regnum, u32 *data)
1345{
1346 struct sisusb_packet packet;
1347 int ret;
1348
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;
1354}
1355
1356/* Clear video RAM */
1357
1358static int sisusb_clear_vram(struct sisusb_usb_data *sisusb,
1359 u32 address, int length)
1360{
1361 int ret, i;
1362 ssize_t j;
1363
1364 if (address < sisusb->vrambase)
1365 return 1;
1366
1367 if (address >= sisusb->vrambase + sisusb->vramsize)
1368 return 1;
1369
1370 if (address + length > sisusb->vrambase + sisusb->vramsize)
1371 length = sisusb->vrambase + sisusb->vramsize - address;
1372
1373 if (length <= 0)
1374 return 0;
1375
1376 /* allocate free buffer/urb and clear the buffer */
1377 i = sisusb_alloc_outbuf(sisusb);
1378 if (i < 0)
1379 return -EBUSY;
1380
1381 memset(sisusb->obuf[i], 0, sisusb->obufsize);
1382
1383 /* We can write a length > buffer size here. The buffer
1384 * data will simply be re-used (like a ring-buffer).
1385 */
1386 ret = sisusb_write_mem_bulk(sisusb, address, NULL, length, NULL, i, &j);
1387
1388 /* Free the buffer/urb */
1389 sisusb_free_outbuf(sisusb, i);
1390
1391 return ret;
1392}
1393
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)
1397 */
1398
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)
1410
1411static int sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype)
1412{
1413 int ret;
1414 u8 tmp8;
1415
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);
1437 }
1438 return ret;
1439}
1440
1441static int sisusb_getbuswidth(struct sisusb_usb_data *sisusb,
1442 int *bw, int *chab)
1443{
1444 int ret;
1445 u8 ramtype, done = 0;
1446 u32 t0, t1, t2, t3;
1447 u32 ramptr = SISUSB_PCI_MEMBASE;
1448
1449 ret = GETIREG(SISSR, 0x3a, &ramtype);
1450 ramtype &= 3;
1451
1452 ret |= SETIREG(SISSR, 0x13, 0x00);
1453
1454 if (ramtype <= 1) {
1455 ret |= SETIREG(SISSR, 0x14, 0x12);
1456 ret |= SETIREGAND(SISSR, 0x15, 0xef);
1457 } else {
1458 ret |= SETIREG(SISSR, 0x14, 0x02);
1459 }
1460
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);
1474
1475 if (ramtype <= 1) {
1476
1477 *chab = 0; *bw = 64;
1478
1479 if ((t3 != 0xcdef0123) || (t2 != 0x89abcdef)) {
1480 if ((t1 == 0x456789ab) && (t0 == 0x01234567)) {
1481 *chab = 0; *bw = 64;
1482 ret |= SETIREGAND(SISSR, 0x14, 0xfd);
1483 }
1484 }
1485 if ((t1 != 0x456789ab) || (t0 != 0x01234567)) {
1486 *chab = 1; *bw = 64;
1487 ret |= SETIREGANDOR(SISSR, 0x14, 0xfc, 0x01);
1488
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);
1497
1498 if (t1 != 0xcdef0123) {
1499 *bw = 32;
1500 ret |= SETIREGOR(SISSR, 0x15, 0x10);
1501 }
1502 }
1503
1504 } else {
1505
1506 *chab = 0; *bw = 64; /* default: cha, bw = 64 */
1507
1508 done = 0;
1509
1510 if (t1 == 0x456789ab) {
1511 if (t0 == 0x01234567) {
1512 *chab = 0; *bw = 64;
1513 done = 1;
1514 }
1515 } else {
1516 if (t0 == 0x01234567) {
1517 *chab = 0; *bw = 32;
1518 ret |= SETIREG(SISSR, 0x14, 0x00);
1519 done = 1;
1520 }
1521 }
1522
1523 if (!done) {
1524 ret |= SETIREG(SISSR, 0x14, 0x03);
1525 ret |= sisusb_triggersr16(sisusb, ramtype);
1526
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);
1537
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 */
1548 }
1549 }
1550 }
1551 return ret;
1552}
1553
1554static int sisusb_verify_mclk(struct sisusb_usb_data *sisusb)
1555{
1556 int ret = 0;
1557 u32 ramptr = SISUSB_PCI_MEMBASE;
1558 u8 tmp1, tmp2, i, j;
1559
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;
1576 }
1577 }
1578 }
1579 return ret;
1580}
1581
1582static int sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret,
1583 int index, u8 rankno, u8 chab, const u8 dramtype[][5], int bw)
1584{
1585 int ret = 0, ranksize;
1586 u8 tmp;
1587
1588 *iret = 0;
1589
1590 if ((rankno == 2) && (dramtype[index][0] == 2))
1591 return ret;
1592
1593 ranksize = dramtype[index][3] / 2 * bw / 32;
1594
1595 if ((ranksize * rankno) > 128)
1596 return ret;
1597
1598 tmp = 0;
1599 while ((ranksize >>= 1) > 0)
1600 tmp += 0x10;
1601
1602 tmp |= ((rankno - 1) << 2);
1603 tmp |= ((bw / 64) & 0x02);
1604 tmp |= (chab & 0x01);
1605
1606 ret = SETIREG(SISSR, 0x14, tmp);
1607 ret |= sisusb_triggersr16(sisusb, 0); /* sic! */
1608
1609 *iret = 1;
1610
1611 return ret;
1612}
1613
1614static int sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret,
1615 u32 inc, int testn)
1616{
1617 int ret = 0, i;
1618 u32 j, tmp;
1619
1620 *iret = 0;
1621
1622 for (i = 0, j = 0; i < testn; i++) {
1623 ret |= WRITEL(sisusb->vrambase + j, j);
1624 j += inc;
1625 }
1626
1627 for (i = 0, j = 0; i < testn; i++) {
1628 ret |= READL(sisusb->vrambase + j, &tmp);
1629 if (tmp != j)
1630 return ret;
1631
1632 j += inc;
1633 }
1634
1635 *iret = 1;
1636 return ret;
1637}
1638
1639static int sisusb_check_ranks(struct sisusb_usb_data *sisusb,
1640 int *iret, int rankno, int idx, int bw, const u8 rtype[][5])
1641{
1642 int ret = 0, i, i2ret;
1643 u32 inc;
1644
1645 *iret = 0;
1646
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;
1653 }
1654
1655 inc = 1 << (rtype[idx][2] + bw / 64 + 2);
1656 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 4);
1657 if (!i2ret)
1658 return ret;
1659
1660 inc = 1 << (10 + bw / 64);
1661 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1662 if (!i2ret)
1663 return ret;
1664
1665 *iret = 1;
1666 return ret;
1667}
1668
1669static int sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret,
1670 int bw, int chab)
1671{
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 }
1687 };
1688
1689 *iret = 1; /* error */
1690
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;
1698
1699 ret |= sisusb_check_ranks(sisusb, &i2ret, j, i, bw,
1700 sdramtype);
1701 if (i2ret) {
1702 *iret = 0; /* ram size found */
1703 return ret;
1704 }
1705 }
1706 }
1707
1708 return ret;
1709}
1710
1711static int sisusb_setup_screen(struct sisusb_usb_data *sisusb,
1712 int clrall, int drwfr)
1713{
1714 int ret = 0;
1715 u32 address;
1716 int i, length, modex, modey, bpp;
1717
1718 modex = 640; modey = 480; bpp = 2;
1719
1720 address = sisusb->vrambase; /* Clear video ram */
1721
1722 if (clrall)
1723 length = sisusb->vramsize;
1724 else
1725 length = modex * bpp * modey;
1726
1727 ret = sisusb_clear_vram(sisusb, address, length);
1728
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);
1737 }
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);
1745 }
1746 }
1747
1748 return ret;
1749}
1750
1751static int sisusb_set_default_mode(struct sisusb_usb_data *sisusb,
1752 int touchengines)
1753{
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
1760 };
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
1766 };
1767 static const char grcdata[] = {
1768 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
1769 0xff
1770 };
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
1775 };
1776
1777 modex = 640; modey = 480; bpp = 2;
1778
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]);
1794 }
1795 for (i = 0; i <= 0x13; i++) { /* att */
1796 GETREG(SISINPSTAT, &tmp8);
1797 SETREG(SISAR, i);
1798 SETREG(SISAR, attrdata[i]);
1799 }
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]);
1808 }
1809 SETIREGAND(SISGR, 0x05, 0xbf);
1810 for (i = 0x0A; i <= 0x0E; i++) { /* clr ext */
1811 SETIREG(SISSR, i, 0x00);
1812 }
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]);
1818
1819 for (j = 0x10; i <= 10; i++, j++)
1820 SETIREG(SISCR, j, crtcdata[i]);
1821
1822 for (j = 0x15; i <= 12; i++, j++)
1823 SETIREG(SISCR, j, crtcdata[i]);
1824
1825 for (j = 0x0A; i <= 15; i++, j++)
1826 SETIREG(SISSR, j, crtcdata[i]);
1827
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;
1834
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++;
1841
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);
1862
1863 SETIREG(SISCR, 0x0d, 0x00); /* adjust frame */
1864 SETIREG(SISCR, 0x0c, 0x00);
1865 SETIREG(SISSR, 0x0d, 0x00);
1866 SETIREGAND(SISSR, 0x37, 0xfe);
1867
1868 SETIREG(SISCR, 0x32, 0x20);
1869 SETIREGAND(SISSR, 0x01, 0xdf); /* enable display */
1870 SETIREG(SISCR, 0x63, (cr63 & 0xbf));
1871 SETIREG(SISSR, 0x31, (sr31 & 0xfb));
1872
1873 if (touchengines) {
1874 SETIREG(SISSR, 0x20, 0xa1); /* enable engines */
1875 SETIREGOR(SISSR, 0x1e, 0x5a);
1876
1877 SETIREG(SISSR, 0x26, 0x01); /* disable cmdqueue */
1878 SETIREG(SISSR, 0x27, 0x1f);
1879 SETIREG(SISSR, 0x26, 0x00);
1880 }
1881
1882 SETIREG(SISCR, 0x34, 0x44); /* we just set std mode #44 */
1883
1884 return ret;
1885}
1886
1887static int sisusb_init_gfxcore(struct sisusb_usb_data *sisusb)
1888{
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
1897 };
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
1903 };
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
1912 };
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
1919 };
1920
1921 while (retry--) {
1922
1923 /* Enable VGA */
1924 ret = GETREG(SISVGAEN, &tmp8);
1925 ret |= SETREG(SISVGAEN, (tmp8 | 0x01));
1926
1927 /* Enable GPU access to VRAM */
1928 ret |= GETREG(SISMISCR, &tmp8);
1929 ret |= SETREG(SISMISCW, (tmp8 | 0x01));
1930
1931 if (ret)
1932 continue;
1933
1934 /* Reset registers */
1935 ret |= SETIREGAND(SISCR, 0x5b, 0xdf);
1936 ret |= SETIREG(SISSR, 0x05, 0x86);
1937 ret |= SETIREGOR(SISSR, 0x20, 0x01);
1938
1939 ret |= SETREG(SISMISCW, 0x67);
1940
1941 for (i = 0x06; i <= 0x1f; i++)
1942 ret |= SETIREG(SISSR, i, 0x00);
1943
1944 for (i = 0x21; i <= 0x27; i++)
1945 ret |= SETIREG(SISSR, i, 0x00);
1946
1947 for (i = 0x31; i <= 0x3d; i++)
1948 ret |= SETIREG(SISSR, i, 0x00);
1949
1950 for (i = 0x12; i <= 0x1b; i++)
1951 ret |= SETIREG(SISSR, i, 0x00);
1952
1953 for (i = 0x79; i <= 0x7c; i++)
1954 ret |= SETIREG(SISCR, i, 0x00);
1955
1956 if (ret)
1957 continue;
1958
1959 ret |= SETIREG(SISCR, 0x63, 0x80);
1960
1961 ret |= GETIREG(SISSR, 0x3a, &ramtype);
1962 ramtype &= 0x03;
1963
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]);
1967
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]);
1971
1972 ret |= SETIREG(SISSR, 0x07, 0x18);
1973 ret |= SETIREG(SISSR, 0x11, 0x0f);
1974
1975 if (ret)
1976 continue;
1977
1978 for (i = 0x15, j = 0; i <= 0x1b; i++, j++) {
1979 ret |= SETIREG(SISSR, i,
1980 ramtypetable1[(j*4) + ramtype]);
1981 }
1982 for (i = 0x40, j = 0; i <= 0x44; i++, j++) {
1983 ret |= SETIREG(SISCR, i,
1984 ramtypetable2[(j*4) + ramtype]);
1985 }
1986
1987 ret |= SETIREG(SISCR, 0x49, 0xaa);
1988
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);
1994
1995 ret |= SETIREG(SISSR, 0x11, 0x0f);
1996
1997 ret |= SETIREGOR(SISPART1, 0x2f, 0x01);
1998
1999 ret |= SETIREGAND(SISCAP, 0x3f, 0xef);
2000
2001 if (ret)
2002 continue;
2003
2004 ret |= SETIREG(SISPART1, 0x00, 0x00);
2005
2006 ret |= GETIREG(SISSR, 0x13, &tmp8);
2007 tmp8 >>= 4;
2008
2009 ret |= SETIREG(SISPART1, 0x02, 0x00);
2010 ret |= SETIREG(SISPART1, 0x2e, 0x08);
2011
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);
2018
2019 ret |= SETIREG(SISSR, 0x27, 0x1f);
2020 ret |= SETIREG(SISSR, 0x31, 0x00);
2021 ret |= SETIREG(SISSR, 0x32, 0x11);
2022 ret |= SETIREG(SISSR, 0x33, 0x00);
2023
2024 if (ret)
2025 continue;
2026
2027 ret |= SETIREG(SISCR, 0x83, 0x00);
2028
2029 ret |= sisusb_set_default_mode(sisusb, 0);
2030
2031 ret |= SETIREGAND(SISSR, 0x21, 0xdf);
2032 ret |= SETIREGOR(SISSR, 0x01, 0x20);
2033 ret |= SETIREGOR(SISSR, 0x16, 0x0f);
2034
2035 ret |= sisusb_triggersr16(sisusb, ramtype);
2036
2037 /* Disable refresh */
2038 ret |= SETIREGAND(SISSR, 0x17, 0xf8);
2039 ret |= SETIREGOR(SISSR, 0x19, 0x03);
2040
2041 ret |= sisusb_getbuswidth(sisusb, &bw, &chab);
2042 ret |= sisusb_verify_mclk(sisusb);
2043
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 */
2051 }
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 *** */
2057 }
2058
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]);
2063
2064 ret |= SETIREGOR(SISSR, 0x21, 0x20);
2065
2066 ret |= SETIREG(SISSR, 0x22, 0xfb);
2067 ret |= SETIREG(SISSR, 0x21, 0xa5);
2068
2069 if (ret == 0)
2070 break;
2071 }
2072
2073 return ret;
2074}
2075
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
2085
2086static void sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
2087{
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};
2096
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)];
2109
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;
2126 }
2127
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);
2132}
2133
2134static int sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb)
2135{
2136 struct sisusb_packet packet;
2137 int ret;
2138 u32 tmp32;
2139
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);
2145
2146 packet.header = 0x001f;
2147 packet.address = 0x00000364;
2148 packet.data = 0x00000004;
2149 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2150
2151 packet.header = 0x001f;
2152 packet.address = 0x00000384;
2153 packet.data = 0x00000004;
2154 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2155
2156 packet.header = 0x001f;
2157 packet.address = 0x00000100;
2158 packet.data = 0x00000700;
2159 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2160
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);
2166
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);
2174
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);
2182
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);
2190
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);
2195
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);
2202 }
2203
2204 return ret;
2205}
2206
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.
2210 */
2211
2212static int sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
2213{
2214 int ret = 0, test = 0;
2215 u32 tmp32;
2216
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;
2222
2223 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE)
2224 test++;
2225
2226 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2227 if (ret)
2228 return ret;
2229
2230 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE)
2231 test++;
2232
2233 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2234 if (ret)
2235 return ret;
2236
2237 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE)
2238 test++;
2239 }
2240
2241 /* No? So reset the device */
2242 if ((sisusb->devinit == 0) || (test != 3)) {
2243
2244 ret |= sisusb_do_init_gfxdevice(sisusb);
2245
2246 if (ret == 0)
2247 sisusb->devinit = 1;
2248
2249 }
2250
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);
2258 }
2259 }
2260
2261 return ret;
2262}
2263
2264
2265#ifdef INCL_SISUSB_CON
2266
2267/* Set up default text mode:
2268 * - Set text mode (0x03)
2269 * - Upload default font
2270 * - Upload user font (if available)
2271 */
2272
2273int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
2274{
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_/_";
2283
2284 /* sisusb->lock is down */
2285
2286 if (!sisusb->SiS_Pr)
2287 return 1;
2288
2289 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2290 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2291
2292 /* Set mode 0x03 */
2293 SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
2294
2295 myfont = find_font("VGA8x16");
2296 if (!myfont)
2297 return 1;
2298
2299 tempbuf = vmalloc(8192);
2300 if (!tempbuf)
2301 return 1;
2302
2303 for (i = 0; i < 256; i++)
2304 memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
2305
2306 /* Upload default font */
2307 ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192,
2308 0, 1, NULL, 16, 0);
2309
2310 vfree(tempbuf);
2311
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);
2320 }
2321
2322 if (init && !sisusb->scrbuf) {
2323
2324 tempbuf = vmalloc(8192);
2325 if (tempbuf) {
2326
2327 i = 4096;
2328 tempbufb = (u16 *)tempbuf;
2329 while (i--)
2330 *(tempbufb++) = 0x0720;
2331
2332 i = 0;
2333 tempbufb = (u16 *)tempbuf;
2334 while (bootlogo[i]) {
2335 *(tempbufb++) = 0x0700 | bootlogo[i++];
2336 if (!(i % 4))
2337 tempbufb += 76;
2338 }
2339
2340 i = 0;
2341 tempbufb = (u16 *)tempbuf + 6;
2342 while (bootstring[i])
2343 *(tempbufb++) = 0x0700 | bootstring[i++];
2344
2345 ret |= sisusb_copy_memory(sisusb, tempbuf,
2346 sisusb->vrambase, 8192, &written);
2347
2348 vfree(tempbuf);
2349
2350 }
2351
2352 } else if (sisusb->scrbuf) {
2353
2354 ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
2355 sisusb->vrambase, sisusb->scrbuf_size,
2356 &written);
2357
2358 }
2359
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;
2370 }
2371
2372 slot = sisusb->sisusb_cursor_loc;
2373 if (slot < 0)
2374 slot = 0;
2375
2376 sisusb->sisusb_cursor_loc = -1;
2377 sisusb->bad_cursor_pos = 1;
2378
2379 sisusb_set_cursor(sisusb, slot);
2380
2381 sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
2382 sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
2383
2384 sisusb->textmodedestroyed = 0;
2385
2386 /* sisusb->lock is down */
2387
2388 return ret;
2389}
2390
2391#endif
2392
2393/* fops */
2394
2395static int sisusb_open(struct inode *inode, struct file *file)
2396{
2397 struct sisusb_usb_data *sisusb;
2398 struct usb_interface *interface;
2399 int subminor = iminor(inode);
2400
2401 interface = usb_find_interface(&sisusb_driver, subminor);
2402 if (!interface)
2403 return -ENODEV;
2404
2405 sisusb = usb_get_intfdata(interface);
2406 if (!sisusb)
2407 return -ENODEV;
2408
2409 mutex_lock(&sisusb->lock);
2410
2411 if (!sisusb->present || !sisusb->ready) {
2412 mutex_unlock(&sisusb->lock);
2413 return -ENODEV;
2414 }
2415
2416 if (sisusb->isopen) {
2417 mutex_unlock(&sisusb->lock);
2418 return -EBUSY;
2419 }
2420
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;
2429 }
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;
2435 }
2436 }
2437
2438 /* Increment usage count for our sisusb */
2439 kref_get(&sisusb->kref);
2440
2441 sisusb->isopen = 1;
2442
2443 file->private_data = sisusb;
2444
2445 mutex_unlock(&sisusb->lock);
2446
2447 return 0;
2448}
2449
2450void sisusb_delete(struct kref *kref)
2451{
2452 struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
2453
2454 if (!sisusb)
2455 return;
2456
2457 usb_put_dev(sisusb->sisusb_dev);
2458
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);
2466}
2467
2468static int sisusb_release(struct inode *inode, struct file *file)
2469{
2470 struct sisusb_usb_data *sisusb;
2471
2472 sisusb = file->private_data;
2473 if (!sisusb)
2474 return -ENODEV;
2475
2476 mutex_lock(&sisusb->lock);
2477
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);
2482 }
2483
2484 sisusb->isopen = 0;
2485 file->private_data = NULL;
2486
2487 mutex_unlock(&sisusb->lock);
2488
2489 /* decrement the usage count on our device */
2490 kref_put(&sisusb->kref, sisusb_delete);
2491
2492 return 0;
2493}
2494
2495static ssize_t sisusb_read(struct file *file, char __user *buffer,
2496 size_t count, loff_t *ppos)
2497{
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;
2504
2505 sisusb = file->private_data;
2506 if (!sisusb)
2507 return -ENODEV;
2508
2509 mutex_lock(&sisusb->lock);
2510
2511 /* Sanity check */
2512 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2513 mutex_unlock(&sisusb->lock);
2514 return -ENODEV;
2515 }
2516
2517 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2518 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2519
2520 address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE +
2521 SISUSB_PCI_IOPORTBASE;
2522
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.
2527 */
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;
2537
2538 break;
2539
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;
2548
2549 break;
2550
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;
2559
2560 break;
2561
2562 default:
2563 errno = -EIO;
2564
2565 }
2566
2567 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && (*ppos) <
2568 SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2569
2570 address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE +
2571 SISUSB_PCI_MEMBASE;
2572
2573 /* Read video ram
2574 * Remember: Data delivered is never endian-corrected
2575 */
2576 errno = sisusb_read_mem_bulk(sisusb, address,
2577 NULL, count, buffer, &bytes_read);
2578
2579 if (bytes_read)
2580 errno = bytes_read;
2581
2582 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2583 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE +
2584 SISUSB_PCI_MMIOSIZE) {
2585
2586 address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE +
2587 SISUSB_PCI_MMIOBASE;
2588
2589 /* Read MMIO
2590 * Remember: Data delivered is never endian-corrected
2591 */
2592 errno = sisusb_read_mem_bulk(sisusb, address,
2593 NULL, count, buffer, &bytes_read);
2594
2595 if (bytes_read)
2596 errno = bytes_read;
2597
2598 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2599 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
2600
2601 if (count != 4) {
2602 mutex_unlock(&sisusb->lock);
2603 return -EINVAL;
2604 }
2605
2606 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2607
2608 /* Read PCI config register
2609 * Return value delivered in machine endianness.
2610 */
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;
2617
2618 } else {
2619
2620 errno = -EBADFD;
2621
2622 }
2623
2624 (*ppos) += bytes_read;
2625
2626 mutex_unlock(&sisusb->lock);
2627
2628 return errno ? errno : bytes_read;
2629}
2630
2631static ssize_t sisusb_write(struct file *file, const char __user *buffer,
2632 size_t count, loff_t *ppos)
2633{
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;
2640
2641 sisusb = file->private_data;
2642 if (!sisusb)
2643 return -ENODEV;
2644
2645 mutex_lock(&sisusb->lock);
2646
2647 /* Sanity check */
2648 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2649 mutex_unlock(&sisusb->lock);
2650 return -ENODEV;
2651 }
2652
2653 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2654 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2655
2656 address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE +
2657 SISUSB_PCI_IOPORTBASE;
2658
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.
2663 */
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;
2673
2674 break;
2675
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;
2684
2685 break;
2686
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;
2695
2696 break;
2697
2698 default:
2699 errno = -EIO;
2700 }
2701
2702 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2703 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE +
2704 sisusb->vramsize) {
2705
2706 address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE +
2707 SISUSB_PCI_MEMBASE;
2708
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).
2714 */
2715 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2716 count, buffer, 0, &bytes_written);
2717
2718 if (bytes_written)
2719 errno = bytes_written;
2720
2721 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2722 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE +
2723 SISUSB_PCI_MMIOSIZE) {
2724
2725 address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE +
2726 SISUSB_PCI_MMIOBASE;
2727
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.
2732 */
2733 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2734 count, buffer, 0, &bytes_written);
2735
2736 if (bytes_written)
2737 errno = bytes_written;
2738
2739 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2740 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE +
2741 SISUSB_PCI_PCONFSIZE) {
2742
2743 if (count != 4) {
2744 mutex_unlock(&sisusb->lock);
2745 return -EINVAL;
2746 }
2747
2748 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2749
2750 /* Write PCI config register.
2751 * Given value expected in machine endianness.
2752 */
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;
2759
2760
2761 } else {
2762
2763 /* Error */
2764 errno = -EBADFD;
2765
2766 }
2767
2768 (*ppos) += bytes_written;
2769
2770 mutex_unlock(&sisusb->lock);
2771
2772 return errno ? errno : bytes_written;
2773}
2774
2775static loff_t sisusb_lseek(struct file *file, loff_t offset, int orig)
2776{
2777 struct sisusb_usb_data *sisusb;
2778 loff_t ret;
2779
2780 sisusb = file->private_data;
2781 if (!sisusb)
2782 return -ENODEV;
2783
2784 mutex_lock(&sisusb->lock);
2785
2786 /* Sanity check */
2787 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2788 mutex_unlock(&sisusb->lock);
2789 return -ENODEV;
2790 }
2791
2792 ret = no_seek_end_llseek(file, offset, orig);
2793
2794 mutex_unlock(&sisusb->lock);
2795 return ret;
2796}
2797
2798static int sisusb_handle_command(struct sisusb_usb_data *sisusb,
2799 struct sisusb_command *y, unsigned long arg)
2800{
2801 int retval, port, length;
2802 u32 address;
2803
2804 /* All our commands require the device
2805 * to be initialized.
2806 */
2807 if (!sisusb->devinit)
2808 return -ENODEV;
2809
2810 port = y->data3 -
2811 SISUSB_PCI_PSEUDO_IOPORTBASE +
2812 SISUSB_PCI_IOPORTBASE;
2813
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;
2820 }
2821 break;
2822
2823 case SUCMD_SET:
2824 retval = sisusb_setidxreg(sisusb, port, y->data0, y->data1);
2825 break;
2826
2827 case SUCMD_SETOR:
2828 retval = sisusb_setidxregor(sisusb, port, y->data0, y->data1);
2829 break;
2830
2831 case SUCMD_SETAND:
2832 retval = sisusb_setidxregand(sisusb, port, y->data0, y->data1);
2833 break;
2834
2835 case SUCMD_SETANDOR:
2836 retval = sisusb_setidxregandor(sisusb, port, y->data0,
2837 y->data1, y->data2);
2838 break;
2839
2840 case SUCMD_SETMASK:
2841 retval = sisusb_setidxregmask(sisusb, port, y->data0,
2842 y->data1, y->data2);
2843 break;
2844
2845 case SUCMD_CLRSCR:
2846 /* Gfx core must be initialized */
2847 if (!sisusb->gfxinit)
2848 return -ENODEV;
2849
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;
2855
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;
2862
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;
2870 }
2871#endif
2872 break;
2873
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;
2879
2880 retval = 0;
2881
2882 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2883 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2884
2885 if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
2886 retval = -EINVAL;
2887
2888 break;
2889
2890 case SUCMD_SETVESAMODE:
2891 /* Gfx core must be initialized, SiS_Pr must exist */
2892 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2893 return -ENODEV;
2894
2895 retval = 0;
2896
2897 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2898 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2899
2900 if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
2901 retval = -EINVAL;
2902
2903 break;
2904#endif
2905
2906 default:
2907 retval = -EINVAL;
2908 }
2909
2910 if (retval > 0)
2911 retval = -EIO;
2912
2913 return retval;
2914}
2915
2916static long sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2917{
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;
2923
2924 sisusb = file->private_data;
2925 if (!sisusb)
2926 return -ENODEV;
2927
2928 mutex_lock(&sisusb->lock);
2929
2930 /* Sanity check */
2931 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2932 retval = -ENODEV;
2933 goto err_out;
2934 }
2935
2936 switch (cmd) {
2937 case SISUSB_GET_CONFIG_SIZE:
2938
2939 if (put_user(sizeof(x), argp))
2940 retval = -EFAULT;
2941
2942 break;
2943
2944 case SISUSB_GET_CONFIG:
2945
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));
2964
2965 if (copy_to_user((void __user *)arg, &x, sizeof(x)))
2966 retval = -EFAULT;
2967
2968 break;
2969
2970 case SISUSB_COMMAND:
2971
2972 if (copy_from_user(&y, (void __user *)arg, sizeof(y)))
2973 retval = -EFAULT;
2974 else
2975 retval = sisusb_handle_command(sisusb, &y, arg);
2976
2977 break;
2978
2979 default:
2980 retval = -ENOTTY;
2981 break;
2982 }
2983
2984err_out:
2985 mutex_unlock(&sisusb->lock);
2986 return retval;
2987}
2988
2989#ifdef SISUSB_NEW_CONFIG_COMPAT
2990static long sisusb_compat_ioctl(struct file *f, unsigned int cmd,
2991 unsigned long arg)
2992{
2993 long retval;
2994
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;
3001
3002 default:
3003 return -ENOIOCTLCMD;
3004 }
3005}
3006#endif
3007
3008static 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
3019};
3020
3021static struct usb_class_driver usb_sisusb_class = {
3022 .name = "sisusbvga%d",
3023 .fops = &usb_sisusb_fops,
3024 .minor_base = SISUSB_MINOR
3025};
3026
3027static int sisusb_probe(struct usb_interface *intf,
3028 const struct usb_device_id *id)
3029{
3030 struct usb_device *dev = interface_to_usbdev(intf);
3031 struct sisusb_usb_data *sisusb;
3032 int retval = 0, i;
3033
3034 dev_info(&dev->dev, "USB2VGA dongle found at address %d\n",
3035 dev->devnum);
3036
3037 /* Allocate memory for our private */
3038 sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL);
3039 if (!sisusb)
3040 return -ENOMEM;
3041
3042 kref_init(&sisusb->kref);
3043
3044 mutex_init(&(sisusb->lock));
3045
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;
3054 }
3055
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 */
3063
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;
3070 }
3071
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;
3080 }
3081 break;
3082 }
3083 sisusb->numobufs++;
3084 }
3085
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;
3092 }
3093 sisusb->completein = 1;
3094
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;
3102 }
3103 sisusb->urbout_context[i].sisusb = (void *)sisusb;
3104 sisusb->urbout_context[i].urbindex = i;
3105 sisusb->urbstatus[i] = 0;
3106 }
3107
3108 dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n",
3109 sisusb->numobufs);
3110
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;
3117 }
3118#endif
3119
3120 /* Do remaining init stuff */
3121
3122 init_waitqueue_head(&sisusb->wait_q);
3123
3124 usb_set_intfdata(intf, sisusb);
3125
3126 usb_get_dev(sisusb->sisusb_dev);
3127
3128 sisusb->present = 1;
3129
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");
3141
3142 } else
3143 dev_info(&sisusb->sisusb_dev->dev,
3144 "Not attached to USB 2.0 hub, deferring init\n");
3145
3146 sisusb->ready = 1;
3147
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
3153
3154#ifdef INCL_SISUSB_CON
3155 sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
3156#endif
3157
3158 return 0;
3159
3160error_4:
3161 sisusb_free_urbs(sisusb);
3162error_3:
3163 sisusb_free_buffers(sisusb);
3164error_2:
3165 usb_deregister_dev(intf, &usb_sisusb_class);
3166error_1:
3167 kfree(sisusb);
3168 return retval;
3169}
3170
3171static void sisusb_disconnect(struct usb_interface *intf)
3172{
3173 struct sisusb_usb_data *sisusb;
3174
3175 /* This should *not* happen */
3176 sisusb = usb_get_intfdata(intf);
3177 if (!sisusb)
3178 return;
3179
3180#ifdef INCL_SISUSB_CON
3181 sisusb_console_exit(sisusb);
3182#endif
3183
3184 usb_deregister_dev(intf, &usb_sisusb_class);
3185
3186 mutex_lock(&sisusb->lock);
3187
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);
3191
3192 usb_set_intfdata(intf, NULL);
3193
3194 sisusb->present = 0;
3195 sisusb->ready = 0;
3196
3197 mutex_unlock(&sisusb->lock);
3198
3199 /* decrement our usage count */
3200 kref_put(&sisusb->kref, sisusb_delete);
3201}
3202
3203static 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) },
3215 { }
3216};
3217
3218MODULE_DEVICE_TABLE(usb, sisusb_table);
3219
3220static struct usb_driver sisusb_driver = {
3221 .name = "sisusb",
3222 .probe = sisusb_probe,
3223 .disconnect = sisusb_disconnect,
3224 .id_table = sisusb_table,
3225};
3226
3227static int __init usb_sisusb_init(void)
3228{
3229
3230#ifdef INCL_SISUSB_CON
3231 sisusb_init_concode();
3232#endif
3233
3234 return usb_register(&sisusb_driver);
3235}
3236
3237static void __exit usb_sisusb_exit(void)
3238{
3239 usb_deregister(&sisusb_driver);
3240}
3241
3242module_init(usb_sisusb_init);
3243module_exit(usb_sisusb_exit);
3244
3245MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3246MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3247MODULE_LICENSE("GPL");
3248
1/*
2 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
3 *
4 * Main part
5 *
6 * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
7 *
8 * If distributed as part of the Linux kernel, this code is licensed under the
9 * terms of the GPL v2.
10 *
11 * Otherwise, the following license terms apply:
12 *
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.
34 *
35 * Author: Thomas Winischhofer <thomas@winischhofer.net>
36 *
37 */
38
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>
51
52#include "sisusb.h"
53#include "sisusb_init.h"
54
55#ifdef INCL_SISUSB_CON
56#include <linux/font.h>
57#endif
58
59#define SISUSB_DONTSYNC
60
61/* Forward declarations / clean-up routines */
62
63#ifdef INCL_SISUSB_CON
64static int sisusb_first_vc = 0;
65static int sisusb_last_vc = 0;
66module_param_named(first, sisusb_first_vc, int, 0);
67module_param_named(last, sisusb_last_vc, int, 0);
68MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
69MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
70#endif
71
72static struct usb_driver sisusb_driver;
73
74static void
75sisusb_free_buffers(struct sisusb_usb_data *sisusb)
76{
77 int i;
78
79 for (i = 0; i < NUMOBUFS; i++) {
80 if (sisusb->obuf[i]) {
81 kfree(sisusb->obuf[i]);
82 sisusb->obuf[i] = NULL;
83 }
84 }
85 if (sisusb->ibuf) {
86 kfree(sisusb->ibuf);
87 sisusb->ibuf = NULL;
88 }
89}
90
91static void
92sisusb_free_urbs(struct sisusb_usb_data *sisusb)
93{
94 int i;
95
96 for (i = 0; i < NUMOBUFS; i++) {
97 usb_free_urb(sisusb->sisurbout[i]);
98 sisusb->sisurbout[i] = NULL;
99 }
100 usb_free_urb(sisusb->sisurbin);
101 sisusb->sisurbin = NULL;
102}
103
104/* Level 0: USB transport layer */
105
106/* 1. out-bulks */
107
108/* out-urb management */
109
110/* Return 1 if all free, 0 otherwise */
111static int
112sisusb_all_free(struct sisusb_usb_data *sisusb)
113{
114 int i;
115
116 for (i = 0; i < sisusb->numobufs; i++) {
117
118 if (sisusb->urbstatus[i] & SU_URB_BUSY)
119 return 0;
120
121 }
122
123 return 1;
124}
125
126/* Kill all busy URBs */
127static void
128sisusb_kill_all_busy(struct sisusb_usb_data *sisusb)
129{
130 int i;
131
132 if (sisusb_all_free(sisusb))
133 return;
134
135 for (i = 0; i < sisusb->numobufs; i++) {
136
137 if (sisusb->urbstatus[i] & SU_URB_BUSY)
138 usb_kill_urb(sisusb->sisurbout[i]);
139
140 }
141}
142
143/* Return 1 if ok, 0 if error (not all complete within timeout) */
144static int
145sisusb_wait_all_out_complete(struct sisusb_usb_data *sisusb)
146{
147 int timeout = 5 * HZ, i = 1;
148
149 wait_event_timeout(sisusb->wait_q,
150 (i = sisusb_all_free(sisusb)),
151 timeout);
152
153 return i;
154}
155
156static int
157sisusb_outurb_available(struct sisusb_usb_data *sisusb)
158{
159 int i;
160
161 for (i = 0; i < sisusb->numobufs; i++) {
162
163 if ((sisusb->urbstatus[i] & (SU_URB_BUSY|SU_URB_ALLOC)) == 0)
164 return i;
165
166 }
167
168 return -1;
169}
170
171static int
172sisusb_get_free_outbuf(struct sisusb_usb_data *sisusb)
173{
174 int i, timeout = 5 * HZ;
175
176 wait_event_timeout(sisusb->wait_q,
177 ((i = sisusb_outurb_available(sisusb)) >= 0),
178 timeout);
179
180 return i;
181}
182
183static int
184sisusb_alloc_outbuf(struct sisusb_usb_data *sisusb)
185{
186 int i;
187
188 i = sisusb_outurb_available(sisusb);
189
190 if (i >= 0)
191 sisusb->urbstatus[i] |= SU_URB_ALLOC;
192
193 return i;
194}
195
196static void
197sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index)
198{
199 if ((index >= 0) && (index < sisusb->numobufs))
200 sisusb->urbstatus[index] &= ~SU_URB_ALLOC;
201}
202
203/* completion callback */
204
205static void
206sisusb_bulk_completeout(struct urb *urb)
207{
208 struct sisusb_urb_context *context = urb->context;
209 struct sisusb_usb_data *sisusb;
210
211 if (!context)
212 return;
213
214 sisusb = context->sisusb;
215
216 if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
217 return;
218
219#ifndef SISUSB_DONTSYNC
220 if (context->actual_length)
221 *(context->actual_length) += urb->actual_length;
222#endif
223
224 sisusb->urbstatus[context->urbindex] &= ~SU_URB_BUSY;
225 wake_up(&sisusb->wait_q);
226}
227
228static int
229sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe, void *data,
230 int len, int *actual_length, int timeout, unsigned int tflags)
231{
232 struct urb *urb = sisusb->sisurbout[index];
233 int retval, byteswritten = 0;
234
235 /* Set up URB */
236 urb->transfer_flags = 0;
237
238 usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
239 sisusb_bulk_completeout, &sisusb->urbout_context[index]);
240
241 urb->transfer_flags |= tflags;
242 urb->actual_length = 0;
243
244 /* Set up context */
245 sisusb->urbout_context[index].actual_length = (timeout) ?
246 NULL : actual_length;
247
248 /* Declare this urb/buffer in use */
249 sisusb->urbstatus[index] |= SU_URB_BUSY;
250
251 /* Submit URB */
252 retval = usb_submit_urb(urb, GFP_KERNEL);
253
254 /* If OK, and if timeout > 0, wait for completion */
255 if ((retval == 0) && timeout) {
256 wait_event_timeout(sisusb->wait_q,
257 (!(sisusb->urbstatus[index] & SU_URB_BUSY)),
258 timeout);
259 if (sisusb->urbstatus[index] & SU_URB_BUSY) {
260 /* URB timed out... kill it and report error */
261 usb_kill_urb(urb);
262 retval = -ETIMEDOUT;
263 } else {
264 /* Otherwise, report urb status */
265 retval = urb->status;
266 byteswritten = urb->actual_length;
267 }
268 }
269
270 if (actual_length)
271 *actual_length = byteswritten;
272
273 return retval;
274}
275
276/* 2. in-bulks */
277
278/* completion callback */
279
280static void
281sisusb_bulk_completein(struct urb *urb)
282{
283 struct sisusb_usb_data *sisusb = urb->context;
284
285 if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
286 return;
287
288 sisusb->completein = 1;
289 wake_up(&sisusb->wait_q);
290}
291
292static int
293sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data,
294 int len, int *actual_length, int timeout, unsigned int tflags)
295{
296 struct urb *urb = sisusb->sisurbin;
297 int retval, readbytes = 0;
298
299 urb->transfer_flags = 0;
300
301 usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
302 sisusb_bulk_completein, sisusb);
303
304 urb->transfer_flags |= tflags;
305 urb->actual_length = 0;
306
307 sisusb->completein = 0;
308 retval = usb_submit_urb(urb, GFP_KERNEL);
309 if (retval == 0) {
310 wait_event_timeout(sisusb->wait_q, sisusb->completein, timeout);
311 if (!sisusb->completein) {
312 /* URB timed out... kill it and report error */
313 usb_kill_urb(urb);
314 retval = -ETIMEDOUT;
315 } else {
316 /* URB completed within timeout */
317 retval = urb->status;
318 readbytes = urb->actual_length;
319 }
320 }
321
322 if (actual_length)
323 *actual_length = readbytes;
324
325 return retval;
326}
327
328
329/* Level 1: */
330
331/* Send a bulk message of variable size
332 *
333 * To copy the data from userspace, give pointer to "userbuffer",
334 * to copy from (non-DMA) kernel memory, give "kernbuffer". If
335 * both of these are NULL, it is assumed, that the transfer
336 * buffer "sisusb->obuf[index]" is set up with the data to send.
337 * Index is ignored if either kernbuffer or userbuffer is set.
338 * If async is nonzero, URBs will be sent without waiting for
339 * completion of the previous URB.
340 *
341 * (return 0 on success)
342 */
343
344static int sisusb_send_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
345 char *kernbuffer, const char __user *userbuffer, int index,
346 ssize_t *bytes_written, unsigned int tflags, int async)
347{
348 int result = 0, retry, count = len;
349 int passsize, thispass, transferred_len = 0;
350 int fromuser = (userbuffer != NULL) ? 1 : 0;
351 int fromkern = (kernbuffer != NULL) ? 1 : 0;
352 unsigned int pipe;
353 char *buffer;
354
355 (*bytes_written) = 0;
356
357 /* Sanity check */
358 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
359 return -ENODEV;
360
361 /* If we copy data from kernel or userspace, force the
362 * allocation of a buffer/urb. If we have the data in
363 * the transfer buffer[index] already, reuse the buffer/URB
364 * if the length is > buffer size. (So, transmitting
365 * large data amounts directly from the transfer buffer
366 * treats the buffer as a ring buffer. However, we need
367 * to sync in this case.)
368 */
369 if (fromuser || fromkern)
370 index = -1;
371 else if (len > sisusb->obufsize)
372 async = 0;
373
374 pipe = usb_sndbulkpipe(sisusb->sisusb_dev, ep);
375
376 do {
377 passsize = thispass = (sisusb->obufsize < count) ?
378 sisusb->obufsize : count;
379
380 if (index < 0)
381 index = sisusb_get_free_outbuf(sisusb);
382
383 if (index < 0)
384 return -EIO;
385
386 buffer = sisusb->obuf[index];
387
388 if (fromuser) {
389
390 if (copy_from_user(buffer, userbuffer, passsize))
391 return -EFAULT;
392
393 userbuffer += passsize;
394
395 } else if (fromkern) {
396
397 memcpy(buffer, kernbuffer, passsize);
398 kernbuffer += passsize;
399
400 }
401
402 retry = 5;
403 while (thispass) {
404
405 if (!sisusb->sisusb_dev)
406 return -ENODEV;
407
408 result = sisusb_bulkout_msg(sisusb,
409 index,
410 pipe,
411 buffer,
412 thispass,
413 &transferred_len,
414 async ? 0 : 5 * HZ,
415 tflags);
416
417 if (result == -ETIMEDOUT) {
418
419 /* Will not happen if async */
420 if (!retry--)
421 return -ETIME;
422
423 continue;
424 }
425
426 if ((result == 0) && !async && transferred_len) {
427
428 thispass -= transferred_len;
429 buffer += transferred_len;
430
431 } else
432 break;
433 }
434
435 if (result)
436 return result;
437
438 (*bytes_written) += passsize;
439 count -= passsize;
440
441 /* Force new allocation in next iteration */
442 if (fromuser || fromkern)
443 index = -1;
444
445 } while (count > 0);
446
447 if (async) {
448#ifdef SISUSB_DONTSYNC
449 (*bytes_written) = len;
450 /* Some URBs/buffers might be busy */
451#else
452 sisusb_wait_all_out_complete(sisusb);
453 (*bytes_written) = transferred_len;
454 /* All URBs and all buffers are available */
455#endif
456 }
457
458 return ((*bytes_written) == len) ? 0 : -EIO;
459}
460
461/* Receive a bulk message of variable size
462 *
463 * To copy the data to userspace, give pointer to "userbuffer",
464 * to copy to kernel memory, give "kernbuffer". One of them
465 * MUST be set. (There is no technique for letting the caller
466 * read directly from the ibuf.)
467 *
468 */
469
470static int sisusb_recv_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
471 void *kernbuffer, char __user *userbuffer, ssize_t *bytes_read,
472 unsigned int tflags)
473{
474 int result = 0, retry, count = len;
475 int bufsize, thispass, transferred_len;
476 unsigned int pipe;
477 char *buffer;
478
479 (*bytes_read) = 0;
480
481 /* Sanity check */
482 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
483 return -ENODEV;
484
485 pipe = usb_rcvbulkpipe(sisusb->sisusb_dev, ep);
486 buffer = sisusb->ibuf;
487 bufsize = sisusb->ibufsize;
488
489 retry = 5;
490
491#ifdef SISUSB_DONTSYNC
492 if (!(sisusb_wait_all_out_complete(sisusb)))
493 return -EIO;
494#endif
495
496 while (count > 0) {
497
498 if (!sisusb->sisusb_dev)
499 return -ENODEV;
500
501 thispass = (bufsize < count) ? bufsize : count;
502
503 result = sisusb_bulkin_msg(sisusb,
504 pipe,
505 buffer,
506 thispass,
507 &transferred_len,
508 5 * HZ,
509 tflags);
510
511 if (transferred_len)
512 thispass = transferred_len;
513
514 else if (result == -ETIMEDOUT) {
515
516 if (!retry--)
517 return -ETIME;
518
519 continue;
520
521 } else
522 return -EIO;
523
524
525 if (thispass) {
526
527 (*bytes_read) += thispass;
528 count -= thispass;
529
530 if (userbuffer) {
531
532 if (copy_to_user(userbuffer, buffer, thispass))
533 return -EFAULT;
534
535 userbuffer += thispass;
536
537 } else {
538
539 memcpy(kernbuffer, buffer, thispass);
540 kernbuffer += thispass;
541
542 }
543
544 }
545
546 }
547
548 return ((*bytes_read) == len) ? 0 : -EIO;
549}
550
551static int sisusb_send_packet(struct sisusb_usb_data *sisusb, int len,
552 struct sisusb_packet *packet)
553{
554 int ret;
555 ssize_t bytes_transferred = 0;
556 __le32 tmp;
557
558 if (len == 6)
559 packet->data = 0;
560
561#ifdef SISUSB_DONTSYNC
562 if (!(sisusb_wait_all_out_complete(sisusb)))
563 return 1;
564#endif
565
566 /* Eventually correct endianness */
567 SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
568
569 /* 1. send the packet */
570 ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_OUT, len,
571 (char *)packet, NULL, 0, &bytes_transferred, 0, 0);
572
573 if ((ret == 0) && (len == 6)) {
574
575 /* 2. if packet len == 6, it means we read, so wait for 32bit
576 * return value and write it to packet->data
577 */
578 ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_GFX_IN, 4,
579 (char *)&tmp, NULL, &bytes_transferred, 0);
580
581 packet->data = le32_to_cpu(tmp);
582 }
583
584 return ret;
585}
586
587static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
588 struct sisusb_packet *packet,
589 unsigned int tflags)
590{
591 int ret;
592 ssize_t bytes_transferred = 0;
593 __le32 tmp;
594
595 if (len == 6)
596 packet->data = 0;
597
598#ifdef SISUSB_DONTSYNC
599 if (!(sisusb_wait_all_out_complete(sisusb)))
600 return 1;
601#endif
602
603 /* Eventually correct endianness */
604 SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
605
606 /* 1. send the packet */
607 ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_BRIDGE_OUT, len,
608 (char *)packet, NULL, 0, &bytes_transferred, tflags, 0);
609
610 if ((ret == 0) && (len == 6)) {
611
612 /* 2. if packet len == 6, it means we read, so wait for 32bit
613 * return value and write it to packet->data
614 */
615 ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_BRIDGE_IN, 4,
616 (char *)&tmp, NULL, &bytes_transferred, 0);
617
618 packet->data = le32_to_cpu(tmp);
619 }
620
621 return ret;
622}
623
624/* access video memory and mmio (return 0 on success) */
625
626/* Low level */
627
628/* The following routines assume being used to transfer byte, word,
629 * long etc.
630 * This means that
631 * - the write routines expect "data" in machine endianness format.
632 * The data will be converted to leXX in sisusb_xxx_packet.
633 * - the read routines can expect read data in machine-endianess.
634 */
635
636static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,
637 u32 addr, u8 data)
638{
639 struct sisusb_packet packet;
640 int ret;
641
642 packet.header = (1 << (addr & 3)) | (type << 6);
643 packet.address = addr & ~3;
644 packet.data = data << ((addr & 3) << 3);
645 ret = sisusb_send_packet(sisusb, 10, &packet);
646 return ret;
647}
648
649static int sisusb_write_memio_word(struct sisusb_usb_data *sisusb, int type,
650 u32 addr, u16 data)
651{
652 struct sisusb_packet packet;
653 int ret = 0;
654
655 packet.address = addr & ~3;
656
657 switch (addr & 3) {
658 case 0:
659 packet.header = (type << 6) | 0x0003;
660 packet.data = (u32)data;
661 ret = sisusb_send_packet(sisusb, 10, &packet);
662 break;
663 case 1:
664 packet.header = (type << 6) | 0x0006;
665 packet.data = (u32)data << 8;
666 ret = sisusb_send_packet(sisusb, 10, &packet);
667 break;
668 case 2:
669 packet.header = (type << 6) | 0x000c;
670 packet.data = (u32)data << 16;
671 ret = sisusb_send_packet(sisusb, 10, &packet);
672 break;
673 case 3:
674 packet.header = (type << 6) | 0x0008;
675 packet.data = (u32)data << 24;
676 ret = sisusb_send_packet(sisusb, 10, &packet);
677 packet.header = (type << 6) | 0x0001;
678 packet.address = (addr & ~3) + 4;
679 packet.data = (u32)data >> 8;
680 ret |= sisusb_send_packet(sisusb, 10, &packet);
681 }
682
683 return ret;
684}
685
686static int sisusb_write_memio_24bit(struct sisusb_usb_data *sisusb, int type,
687 u32 addr, u32 data)
688{
689 struct sisusb_packet packet;
690 int ret = 0;
691
692 packet.address = addr & ~3;
693
694 switch (addr & 3) {
695 case 0:
696 packet.header = (type << 6) | 0x0007;
697 packet.data = data & 0x00ffffff;
698 ret = sisusb_send_packet(sisusb, 10, &packet);
699 break;
700 case 1:
701 packet.header = (type << 6) | 0x000e;
702 packet.data = data << 8;
703 ret = sisusb_send_packet(sisusb, 10, &packet);
704 break;
705 case 2:
706 packet.header = (type << 6) | 0x000c;
707 packet.data = data << 16;
708 ret = sisusb_send_packet(sisusb, 10, &packet);
709 packet.header = (type << 6) | 0x0001;
710 packet.address = (addr & ~3) + 4;
711 packet.data = (data >> 16) & 0x00ff;
712 ret |= sisusb_send_packet(sisusb, 10, &packet);
713 break;
714 case 3:
715 packet.header = (type << 6) | 0x0008;
716 packet.data = data << 24;
717 ret = sisusb_send_packet(sisusb, 10, &packet);
718 packet.header = (type << 6) | 0x0003;
719 packet.address = (addr & ~3) + 4;
720 packet.data = (data >> 8) & 0xffff;
721 ret |= sisusb_send_packet(sisusb, 10, &packet);
722 }
723
724 return ret;
725}
726
727static int sisusb_write_memio_long(struct sisusb_usb_data *sisusb, int type,
728 u32 addr, u32 data)
729{
730 struct sisusb_packet packet;
731 int ret = 0;
732
733 packet.address = addr & ~3;
734
735 switch (addr & 3) {
736 case 0:
737 packet.header = (type << 6) | 0x000f;
738 packet.data = data;
739 ret = sisusb_send_packet(sisusb, 10, &packet);
740 break;
741 case 1:
742 packet.header = (type << 6) | 0x000e;
743 packet.data = data << 8;
744 ret = sisusb_send_packet(sisusb, 10, &packet);
745 packet.header = (type << 6) | 0x0001;
746 packet.address = (addr & ~3) + 4;
747 packet.data = data >> 24;
748 ret |= sisusb_send_packet(sisusb, 10, &packet);
749 break;
750 case 2:
751 packet.header = (type << 6) | 0x000c;
752 packet.data = data << 16;
753 ret = sisusb_send_packet(sisusb, 10, &packet);
754 packet.header = (type << 6) | 0x0003;
755 packet.address = (addr & ~3) + 4;
756 packet.data = data >> 16;
757 ret |= sisusb_send_packet(sisusb, 10, &packet);
758 break;
759 case 3:
760 packet.header = (type << 6) | 0x0008;
761 packet.data = data << 24;
762 ret = sisusb_send_packet(sisusb, 10, &packet);
763 packet.header = (type << 6) | 0x0007;
764 packet.address = (addr & ~3) + 4;
765 packet.data = data >> 8;
766 ret |= sisusb_send_packet(sisusb, 10, &packet);
767 }
768
769 return ret;
770}
771
772/* The xxx_bulk routines copy a buffer of variable size. They treat the
773 * buffer as chars, therefore lsb/msb has to be corrected if using the
774 * byte/word/long/etc routines for speed-up
775 *
776 * If data is from userland, set "userbuffer" (and clear "kernbuffer"),
777 * if data is in kernel space, set "kernbuffer" (and clear "userbuffer");
778 * if neither "kernbuffer" nor "userbuffer" are given, it is assumed
779 * that the data already is in the transfer buffer "sisusb->obuf[index]".
780 */
781
782static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
783 char *kernbuffer, int length,
784 const char __user *userbuffer, int index,
785 ssize_t *bytes_written)
786{
787 struct sisusb_packet packet;
788 int ret = 0;
789 static int msgcount = 0;
790 u8 swap8, fromkern = kernbuffer ? 1 : 0;
791 u16 swap16;
792 u32 swap32, flag = (length >> 28) & 1;
793 char buf[4];
794
795 /* if neither kernbuffer not userbuffer are given, assume
796 * data in obuf
797 */
798 if (!fromkern && !userbuffer)
799 kernbuffer = sisusb->obuf[index];
800
801 (*bytes_written = 0);
802
803 length &= 0x00ffffff;
804
805 while (length) {
806
807 switch (length) {
808
809 case 1:
810 if (userbuffer) {
811 if (get_user(swap8, (u8 __user *)userbuffer))
812 return -EFAULT;
813 } else
814 swap8 = kernbuffer[0];
815
816 ret = sisusb_write_memio_byte(sisusb,
817 SISUSB_TYPE_MEM,
818 addr, swap8);
819
820 if (!ret)
821 (*bytes_written)++;
822
823 return ret;
824
825 case 2:
826 if (userbuffer) {
827 if (get_user(swap16, (u16 __user *)userbuffer))
828 return -EFAULT;
829 } else
830 swap16 = *((u16 *)kernbuffer);
831
832 ret = sisusb_write_memio_word(sisusb,
833 SISUSB_TYPE_MEM,
834 addr,
835 swap16);
836
837 if (!ret)
838 (*bytes_written) += 2;
839
840 return ret;
841
842 case 3:
843 if (userbuffer) {
844 if (copy_from_user(&buf, userbuffer, 3))
845 return -EFAULT;
846#ifdef __BIG_ENDIAN
847 swap32 = (buf[0] << 16) |
848 (buf[1] << 8) |
849 buf[2];
850#else
851 swap32 = (buf[2] << 16) |
852 (buf[1] << 8) |
853 buf[0];
854#endif
855 } else
856#ifdef __BIG_ENDIAN
857 swap32 = (kernbuffer[0] << 16) |
858 (kernbuffer[1] << 8) |
859 kernbuffer[2];
860#else
861 swap32 = (kernbuffer[2] << 16) |
862 (kernbuffer[1] << 8) |
863 kernbuffer[0];
864#endif
865
866 ret = sisusb_write_memio_24bit(sisusb,
867 SISUSB_TYPE_MEM,
868 addr,
869 swap32);
870
871 if (!ret)
872 (*bytes_written) += 3;
873
874 return ret;
875
876 case 4:
877 if (userbuffer) {
878 if (get_user(swap32, (u32 __user *)userbuffer))
879 return -EFAULT;
880 } else
881 swap32 = *((u32 *)kernbuffer);
882
883 ret = sisusb_write_memio_long(sisusb,
884 SISUSB_TYPE_MEM,
885 addr,
886 swap32);
887 if (!ret)
888 (*bytes_written) += 4;
889
890 return ret;
891
892 default:
893 if ((length & ~3) > 0x10000) {
894
895 packet.header = 0x001f;
896 packet.address = 0x000001d4;
897 packet.data = addr;
898 ret = sisusb_send_bridge_packet(sisusb, 10,
899 &packet, 0);
900 packet.header = 0x001f;
901 packet.address = 0x000001d0;
902 packet.data = (length & ~3);
903 ret |= sisusb_send_bridge_packet(sisusb, 10,
904 &packet, 0);
905 packet.header = 0x001f;
906 packet.address = 0x000001c0;
907 packet.data = flag | 0x16;
908 ret |= sisusb_send_bridge_packet(sisusb, 10,
909 &packet, 0);
910 if (userbuffer) {
911 ret |= sisusb_send_bulk_msg(sisusb,
912 SISUSB_EP_GFX_LBULK_OUT,
913 (length & ~3),
914 NULL, userbuffer, 0,
915 bytes_written, 0, 1);
916 userbuffer += (*bytes_written);
917 } else if (fromkern) {
918 ret |= sisusb_send_bulk_msg(sisusb,
919 SISUSB_EP_GFX_LBULK_OUT,
920 (length & ~3),
921 kernbuffer, NULL, 0,
922 bytes_written, 0, 1);
923 kernbuffer += (*bytes_written);
924 } else {
925 ret |= sisusb_send_bulk_msg(sisusb,
926 SISUSB_EP_GFX_LBULK_OUT,
927 (length & ~3),
928 NULL, NULL, index,
929 bytes_written, 0, 1);
930 kernbuffer += ((*bytes_written) &
931 (sisusb->obufsize-1));
932 }
933
934 } else {
935
936 packet.header = 0x001f;
937 packet.address = 0x00000194;
938 packet.data = addr;
939 ret = sisusb_send_bridge_packet(sisusb, 10,
940 &packet, 0);
941 packet.header = 0x001f;
942 packet.address = 0x00000190;
943 packet.data = (length & ~3);
944 ret |= sisusb_send_bridge_packet(sisusb, 10,
945 &packet, 0);
946 if (sisusb->flagb0 != 0x16) {
947 packet.header = 0x001f;
948 packet.address = 0x00000180;
949 packet.data = flag | 0x16;
950 ret |= sisusb_send_bridge_packet(sisusb, 10,
951 &packet, 0);
952 sisusb->flagb0 = 0x16;
953 }
954 if (userbuffer) {
955 ret |= sisusb_send_bulk_msg(sisusb,
956 SISUSB_EP_GFX_BULK_OUT,
957 (length & ~3),
958 NULL, userbuffer, 0,
959 bytes_written, 0, 1);
960 userbuffer += (*bytes_written);
961 } else if (fromkern) {
962 ret |= sisusb_send_bulk_msg(sisusb,
963 SISUSB_EP_GFX_BULK_OUT,
964 (length & ~3),
965 kernbuffer, NULL, 0,
966 bytes_written, 0, 1);
967 kernbuffer += (*bytes_written);
968 } else {
969 ret |= sisusb_send_bulk_msg(sisusb,
970 SISUSB_EP_GFX_BULK_OUT,
971 (length & ~3),
972 NULL, NULL, index,
973 bytes_written, 0, 1);
974 kernbuffer += ((*bytes_written) &
975 (sisusb->obufsize-1));
976 }
977 }
978 if (ret) {
979 msgcount++;
980 if (msgcount < 500)
981 dev_err(&sisusb->sisusb_dev->dev, "Wrote %zd of %d bytes, error %d\n",
982 *bytes_written, length, ret);
983 else if (msgcount == 500)
984 dev_err(&sisusb->sisusb_dev->dev, "Too many errors, logging stopped\n");
985 }
986 addr += (*bytes_written);
987 length -= (*bytes_written);
988 }
989
990 if (ret)
991 break;
992
993 }
994
995 return ret ? -EIO : 0;
996}
997
998/* Remember: Read data in packet is in machine-endianess! So for
999 * byte, word, 24bit, long no endian correction is necessary.
1000 */
1001
1002static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
1003 u32 addr, u8 *data)
1004{
1005 struct sisusb_packet packet;
1006 int ret;
1007
1008 CLEARPACKET(&packet);
1009 packet.header = (1 << (addr & 3)) | (type << 6);
1010 packet.address = addr & ~3;
1011 ret = sisusb_send_packet(sisusb, 6, &packet);
1012 *data = (u8)(packet.data >> ((addr & 3) << 3));
1013 return ret;
1014}
1015
1016static int sisusb_read_memio_word(struct sisusb_usb_data *sisusb, int type,
1017 u32 addr, u16 *data)
1018{
1019 struct sisusb_packet packet;
1020 int ret = 0;
1021
1022 CLEARPACKET(&packet);
1023
1024 packet.address = addr & ~3;
1025
1026 switch (addr & 3) {
1027 case 0:
1028 packet.header = (type << 6) | 0x0003;
1029 ret = sisusb_send_packet(sisusb, 6, &packet);
1030 *data = (u16)(packet.data);
1031 break;
1032 case 1:
1033 packet.header = (type << 6) | 0x0006;
1034 ret = sisusb_send_packet(sisusb, 6, &packet);
1035 *data = (u16)(packet.data >> 8);
1036 break;
1037 case 2:
1038 packet.header = (type << 6) | 0x000c;
1039 ret = sisusb_send_packet(sisusb, 6, &packet);
1040 *data = (u16)(packet.data >> 16);
1041 break;
1042 case 3:
1043 packet.header = (type << 6) | 0x0008;
1044 ret = sisusb_send_packet(sisusb, 6, &packet);
1045 *data = (u16)(packet.data >> 24);
1046 packet.header = (type << 6) | 0x0001;
1047 packet.address = (addr & ~3) + 4;
1048 ret |= sisusb_send_packet(sisusb, 6, &packet);
1049 *data |= (u16)(packet.data << 8);
1050 }
1051
1052 return ret;
1053}
1054
1055static int sisusb_read_memio_24bit(struct sisusb_usb_data *sisusb, int type,
1056 u32 addr, u32 *data)
1057{
1058 struct sisusb_packet packet;
1059 int ret = 0;
1060
1061 packet.address = addr & ~3;
1062
1063 switch (addr & 3) {
1064 case 0:
1065 packet.header = (type << 6) | 0x0007;
1066 ret = sisusb_send_packet(sisusb, 6, &packet);
1067 *data = packet.data & 0x00ffffff;
1068 break;
1069 case 1:
1070 packet.header = (type << 6) | 0x000e;
1071 ret = sisusb_send_packet(sisusb, 6, &packet);
1072 *data = packet.data >> 8;
1073 break;
1074 case 2:
1075 packet.header = (type << 6) | 0x000c;
1076 ret = sisusb_send_packet(sisusb, 6, &packet);
1077 *data = packet.data >> 16;
1078 packet.header = (type << 6) | 0x0001;
1079 packet.address = (addr & ~3) + 4;
1080 ret |= sisusb_send_packet(sisusb, 6, &packet);
1081 *data |= ((packet.data & 0xff) << 16);
1082 break;
1083 case 3:
1084 packet.header = (type << 6) | 0x0008;
1085 ret = sisusb_send_packet(sisusb, 6, &packet);
1086 *data = packet.data >> 24;
1087 packet.header = (type << 6) | 0x0003;
1088 packet.address = (addr & ~3) + 4;
1089 ret |= sisusb_send_packet(sisusb, 6, &packet);
1090 *data |= ((packet.data & 0xffff) << 8);
1091 }
1092
1093 return ret;
1094}
1095
1096static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type,
1097 u32 addr, u32 *data)
1098{
1099 struct sisusb_packet packet;
1100 int ret = 0;
1101
1102 packet.address = addr & ~3;
1103
1104 switch (addr & 3) {
1105 case 0:
1106 packet.header = (type << 6) | 0x000f;
1107 ret = sisusb_send_packet(sisusb, 6, &packet);
1108 *data = packet.data;
1109 break;
1110 case 1:
1111 packet.header = (type << 6) | 0x000e;
1112 ret = sisusb_send_packet(sisusb, 6, &packet);
1113 *data = packet.data >> 8;
1114 packet.header = (type << 6) | 0x0001;
1115 packet.address = (addr & ~3) + 4;
1116 ret |= sisusb_send_packet(sisusb, 6, &packet);
1117 *data |= (packet.data << 24);
1118 break;
1119 case 2:
1120 packet.header = (type << 6) | 0x000c;
1121 ret = sisusb_send_packet(sisusb, 6, &packet);
1122 *data = packet.data >> 16;
1123 packet.header = (type << 6) | 0x0003;
1124 packet.address = (addr & ~3) + 4;
1125 ret |= sisusb_send_packet(sisusb, 6, &packet);
1126 *data |= (packet.data << 16);
1127 break;
1128 case 3:
1129 packet.header = (type << 6) | 0x0008;
1130 ret = sisusb_send_packet(sisusb, 6, &packet);
1131 *data = packet.data >> 24;
1132 packet.header = (type << 6) | 0x0007;
1133 packet.address = (addr & ~3) + 4;
1134 ret |= sisusb_send_packet(sisusb, 6, &packet);
1135 *data |= (packet.data << 8);
1136 }
1137
1138 return ret;
1139}
1140
1141static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1142 char *kernbuffer, int length,
1143 char __user *userbuffer, ssize_t *bytes_read)
1144{
1145 int ret = 0;
1146 char buf[4];
1147 u16 swap16;
1148 u32 swap32;
1149
1150 (*bytes_read = 0);
1151
1152 length &= 0x00ffffff;
1153
1154 while (length) {
1155
1156 switch (length) {
1157
1158 case 1:
1159
1160 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM,
1161 addr, &buf[0]);
1162 if (!ret) {
1163 (*bytes_read)++;
1164 if (userbuffer) {
1165 if (put_user(buf[0],
1166 (u8 __user *)userbuffer)) {
1167 return -EFAULT;
1168 }
1169 } else {
1170 kernbuffer[0] = buf[0];
1171 }
1172 }
1173 return ret;
1174
1175 case 2:
1176 ret |= sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM,
1177 addr, &swap16);
1178 if (!ret) {
1179 (*bytes_read) += 2;
1180 if (userbuffer) {
1181 if (put_user(swap16,
1182 (u16 __user *)userbuffer))
1183 return -EFAULT;
1184 } else {
1185 *((u16 *)kernbuffer) = swap16;
1186 }
1187 }
1188 return ret;
1189
1190 case 3:
1191 ret |= sisusb_read_memio_24bit(sisusb, SISUSB_TYPE_MEM,
1192 addr, &swap32);
1193 if (!ret) {
1194 (*bytes_read) += 3;
1195#ifdef __BIG_ENDIAN
1196 buf[0] = (swap32 >> 16) & 0xff;
1197 buf[1] = (swap32 >> 8) & 0xff;
1198 buf[2] = swap32 & 0xff;
1199#else
1200 buf[2] = (swap32 >> 16) & 0xff;
1201 buf[1] = (swap32 >> 8) & 0xff;
1202 buf[0] = swap32 & 0xff;
1203#endif
1204 if (userbuffer) {
1205 if (copy_to_user(userbuffer, &buf[0], 3))
1206 return -EFAULT;
1207 } else {
1208 kernbuffer[0] = buf[0];
1209 kernbuffer[1] = buf[1];
1210 kernbuffer[2] = buf[2];
1211 }
1212 }
1213 return ret;
1214
1215 default:
1216 ret |= sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM,
1217 addr, &swap32);
1218 if (!ret) {
1219 (*bytes_read) += 4;
1220 if (userbuffer) {
1221 if (put_user(swap32,
1222 (u32 __user *)userbuffer))
1223 return -EFAULT;
1224
1225 userbuffer += 4;
1226 } else {
1227 *((u32 *)kernbuffer) = swap32;
1228 kernbuffer += 4;
1229 }
1230 addr += 4;
1231 length -= 4;
1232 }
1233 }
1234
1235 if (ret)
1236 break;
1237 }
1238
1239 return ret;
1240}
1241
1242/* High level: Gfx (indexed) register access */
1243
1244#ifdef INCL_SISUSB_CON
1245int
1246sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data)
1247{
1248 return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1249}
1250
1251int
1252sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data)
1253{
1254 return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1255}
1256#endif
1257
1258int
1259sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
1260{
1261 int ret;
1262 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1263 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1264 return ret;
1265}
1266
1267int
1268sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
1269{
1270 int ret;
1271 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1272 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1273 return ret;
1274}
1275
1276int
1277sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
1278 u8 myand, u8 myor)
1279{
1280 int ret;
1281 u8 tmp;
1282
1283 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1284 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1285 tmp &= myand;
1286 tmp |= myor;
1287 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1288 return ret;
1289}
1290
1291static int
1292sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx,
1293 u8 data, u8 mask)
1294{
1295 int ret;
1296 u8 tmp;
1297 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1298 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1299 tmp &= ~(mask);
1300 tmp |= (data & mask);
1301 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1302 return ret;
1303}
1304
1305int
1306sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor)
1307{
1308 return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));
1309}
1310
1311int
1312sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand)
1313{
1314 return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00));
1315}
1316
1317/* Write/read video ram */
1318
1319#ifdef INCL_SISUSB_CON
1320int
1321sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data)
1322{
1323 return(sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
1324}
1325
1326int
1327sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)
1328{
1329 return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
1330}
1331
1332int
1333sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
1334 u32 dest, int length, size_t *bytes_written)
1335{
1336 return(sisusb_write_mem_bulk(sisusb, dest, src, length, NULL, 0, bytes_written));
1337}
1338
1339#ifdef SISUSBENDIANTEST
1340int
1341sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
1342 u32 src, int length, size_t *bytes_written)
1343{
1344 return(sisusb_read_mem_bulk(sisusb, src, dest, length, NULL, bytes_written));
1345}
1346#endif
1347#endif
1348
1349#ifdef SISUSBENDIANTEST
1350static void
1351sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
1352{
1353 static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1354 char destbuffer[10];
1355 size_t dummy;
1356 int i,j;
1357
1358 sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy);
1359
1360 for(i = 1; i <= 7; i++) {
1361 dev_dbg(&sisusb->sisusb_dev->dev, "sisusb: rwtest %d bytes\n", i);
1362 sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy);
1363 for(j = 0; j < i; j++) {
1364 dev_dbg(&sisusb->sisusb_dev->dev, "rwtest read[%d] = %x\n", j, destbuffer[j]);
1365 }
1366 }
1367}
1368#endif
1369
1370/* access pci config registers (reg numbers 0, 4, 8, etc) */
1371
1372static int
1373sisusb_write_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 data)
1374{
1375 struct sisusb_packet packet;
1376 int ret;
1377
1378 packet.header = 0x008f;
1379 packet.address = regnum | 0x10000;
1380 packet.data = data;
1381 ret = sisusb_send_packet(sisusb, 10, &packet);
1382 return ret;
1383}
1384
1385static int
1386sisusb_read_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 *data)
1387{
1388 struct sisusb_packet packet;
1389 int ret;
1390
1391 packet.header = 0x008f;
1392 packet.address = (u32)regnum | 0x10000;
1393 ret = sisusb_send_packet(sisusb, 6, &packet);
1394 *data = packet.data;
1395 return ret;
1396}
1397
1398/* Clear video RAM */
1399
1400static int
1401sisusb_clear_vram(struct sisusb_usb_data *sisusb, u32 address, int length)
1402{
1403 int ret, i;
1404 ssize_t j;
1405
1406 if (address < sisusb->vrambase)
1407 return 1;
1408
1409 if (address >= sisusb->vrambase + sisusb->vramsize)
1410 return 1;
1411
1412 if (address + length > sisusb->vrambase + sisusb->vramsize)
1413 length = sisusb->vrambase + sisusb->vramsize - address;
1414
1415 if (length <= 0)
1416 return 0;
1417
1418 /* allocate free buffer/urb and clear the buffer */
1419 if ((i = sisusb_alloc_outbuf(sisusb)) < 0)
1420 return -EBUSY;
1421
1422 memset(sisusb->obuf[i], 0, sisusb->obufsize);
1423
1424 /* We can write a length > buffer size here. The buffer
1425 * data will simply be re-used (like a ring-buffer).
1426 */
1427 ret = sisusb_write_mem_bulk(sisusb, address, NULL, length, NULL, i, &j);
1428
1429 /* Free the buffer/urb */
1430 sisusb_free_outbuf(sisusb, i);
1431
1432 return ret;
1433}
1434
1435/* Initialize the graphics core (return 0 on success)
1436 * This resets the graphics hardware and puts it into
1437 * a defined mode (640x480@60Hz)
1438 */
1439
1440#define GETREG(r,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1441#define SETREG(r,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1442#define SETIREG(r,i,d) sisusb_setidxreg(sisusb, r, i, d)
1443#define GETIREG(r,i,d) sisusb_getidxreg(sisusb, r, i, d)
1444#define SETIREGOR(r,i,o) sisusb_setidxregor(sisusb, r, i, o)
1445#define SETIREGAND(r,i,a) sisusb_setidxregand(sisusb, r, i, a)
1446#define SETIREGANDOR(r,i,a,o) sisusb_setidxregandor(sisusb, r, i, a, o)
1447#define READL(a,d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1448#define WRITEL(a,d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1449#define READB(a,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1450#define WRITEB(a,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1451
1452static int
1453sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype)
1454{
1455 int ret;
1456 u8 tmp8;
1457
1458 ret = GETIREG(SISSR, 0x16, &tmp8);
1459 if (ramtype <= 1) {
1460 tmp8 &= 0x3f;
1461 ret |= SETIREG(SISSR, 0x16, tmp8);
1462 tmp8 |= 0x80;
1463 ret |= SETIREG(SISSR, 0x16, tmp8);
1464 } else {
1465 tmp8 |= 0xc0;
1466 ret |= SETIREG(SISSR, 0x16, tmp8);
1467 tmp8 &= 0x0f;
1468 ret |= SETIREG(SISSR, 0x16, tmp8);
1469 tmp8 |= 0x80;
1470 ret |= SETIREG(SISSR, 0x16, tmp8);
1471 tmp8 &= 0x0f;
1472 ret |= SETIREG(SISSR, 0x16, tmp8);
1473 tmp8 |= 0xd0;
1474 ret |= SETIREG(SISSR, 0x16, tmp8);
1475 tmp8 &= 0x0f;
1476 ret |= SETIREG(SISSR, 0x16, tmp8);
1477 tmp8 |= 0xa0;
1478 ret |= SETIREG(SISSR, 0x16, tmp8);
1479 }
1480 return ret;
1481}
1482
1483static int
1484sisusb_getbuswidth(struct sisusb_usb_data *sisusb, int *bw, int *chab)
1485{
1486 int ret;
1487 u8 ramtype, done = 0;
1488 u32 t0, t1, t2, t3;
1489 u32 ramptr = SISUSB_PCI_MEMBASE;
1490
1491 ret = GETIREG(SISSR, 0x3a, &ramtype);
1492 ramtype &= 3;
1493
1494 ret |= SETIREG(SISSR, 0x13, 0x00);
1495
1496 if (ramtype <= 1) {
1497 ret |= SETIREG(SISSR, 0x14, 0x12);
1498 ret |= SETIREGAND(SISSR, 0x15, 0xef);
1499 } else {
1500 ret |= SETIREG(SISSR, 0x14, 0x02);
1501 }
1502
1503 ret |= sisusb_triggersr16(sisusb, ramtype);
1504 ret |= WRITEL(ramptr + 0, 0x01234567);
1505 ret |= WRITEL(ramptr + 4, 0x456789ab);
1506 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1507 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1508 ret |= WRITEL(ramptr + 16, 0x55555555);
1509 ret |= WRITEL(ramptr + 20, 0x55555555);
1510 ret |= WRITEL(ramptr + 24, 0xffffffff);
1511 ret |= WRITEL(ramptr + 28, 0xffffffff);
1512 ret |= READL(ramptr + 0, &t0);
1513 ret |= READL(ramptr + 4, &t1);
1514 ret |= READL(ramptr + 8, &t2);
1515 ret |= READL(ramptr + 12, &t3);
1516
1517 if (ramtype <= 1) {
1518
1519 *chab = 0; *bw = 64;
1520
1521 if ((t3 != 0xcdef0123) || (t2 != 0x89abcdef)) {
1522 if ((t1 == 0x456789ab) && (t0 == 0x01234567)) {
1523 *chab = 0; *bw = 64;
1524 ret |= SETIREGAND(SISSR, 0x14, 0xfd);
1525 }
1526 }
1527 if ((t1 != 0x456789ab) || (t0 != 0x01234567)) {
1528 *chab = 1; *bw = 64;
1529 ret |= SETIREGANDOR(SISSR, 0x14, 0xfc,0x01);
1530
1531 ret |= sisusb_triggersr16(sisusb, ramtype);
1532 ret |= WRITEL(ramptr + 0, 0x89abcdef);
1533 ret |= WRITEL(ramptr + 4, 0xcdef0123);
1534 ret |= WRITEL(ramptr + 8, 0x55555555);
1535 ret |= WRITEL(ramptr + 12, 0x55555555);
1536 ret |= WRITEL(ramptr + 16, 0xaaaaaaaa);
1537 ret |= WRITEL(ramptr + 20, 0xaaaaaaaa);
1538 ret |= READL(ramptr + 4, &t1);
1539
1540 if (t1 != 0xcdef0123) {
1541 *bw = 32;
1542 ret |= SETIREGOR(SISSR, 0x15, 0x10);
1543 }
1544 }
1545
1546 } else {
1547
1548 *chab = 0; *bw = 64; /* default: cha, bw = 64 */
1549
1550 done = 0;
1551
1552 if (t1 == 0x456789ab) {
1553 if (t0 == 0x01234567) {
1554 *chab = 0; *bw = 64;
1555 done = 1;
1556 }
1557 } else {
1558 if (t0 == 0x01234567) {
1559 *chab = 0; *bw = 32;
1560 ret |= SETIREG(SISSR, 0x14, 0x00);
1561 done = 1;
1562 }
1563 }
1564
1565 if (!done) {
1566 ret |= SETIREG(SISSR, 0x14, 0x03);
1567 ret |= sisusb_triggersr16(sisusb, ramtype);
1568
1569 ret |= WRITEL(ramptr + 0, 0x01234567);
1570 ret |= WRITEL(ramptr + 4, 0x456789ab);
1571 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1572 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1573 ret |= WRITEL(ramptr + 16, 0x55555555);
1574 ret |= WRITEL(ramptr + 20, 0x55555555);
1575 ret |= WRITEL(ramptr + 24, 0xffffffff);
1576 ret |= WRITEL(ramptr + 28, 0xffffffff);
1577 ret |= READL(ramptr + 0, &t0);
1578 ret |= READL(ramptr + 4, &t1);
1579
1580 if (t1 == 0x456789ab) {
1581 if (t0 == 0x01234567) {
1582 *chab = 1; *bw = 64;
1583 return ret;
1584 } /* else error */
1585 } else {
1586 if (t0 == 0x01234567) {
1587 *chab = 1; *bw = 32;
1588 ret |= SETIREG(SISSR, 0x14, 0x01);
1589 } /* else error */
1590 }
1591 }
1592 }
1593 return ret;
1594}
1595
1596static int
1597sisusb_verify_mclk(struct sisusb_usb_data *sisusb)
1598{
1599 int ret = 0;
1600 u32 ramptr = SISUSB_PCI_MEMBASE;
1601 u8 tmp1, tmp2, i, j;
1602
1603 ret |= WRITEB(ramptr, 0xaa);
1604 ret |= WRITEB(ramptr + 16, 0x55);
1605 ret |= READB(ramptr, &tmp1);
1606 ret |= READB(ramptr + 16, &tmp2);
1607 if ((tmp1 != 0xaa) || (tmp2 != 0x55)) {
1608 for (i = 0, j = 16; i < 2; i++, j += 16) {
1609 ret |= GETIREG(SISSR, 0x21, &tmp1);
1610 ret |= SETIREGAND(SISSR, 0x21, (tmp1 & 0xfb));
1611 ret |= SETIREGOR(SISSR, 0x3c, 0x01); /* not on 330 */
1612 ret |= SETIREGAND(SISSR, 0x3c, 0xfe); /* not on 330 */
1613 ret |= SETIREG(SISSR, 0x21, tmp1);
1614 ret |= WRITEB(ramptr + 16 + j, j);
1615 ret |= READB(ramptr + 16 + j, &tmp1);
1616 if (tmp1 == j) {
1617 ret |= WRITEB(ramptr + j, j);
1618 break;
1619 }
1620 }
1621 }
1622 return ret;
1623}
1624
1625static int
1626sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret, int index,
1627 u8 rankno, u8 chab, const u8 dramtype[][5],
1628 int bw)
1629{
1630 int ret = 0, ranksize;
1631 u8 tmp;
1632
1633 *iret = 0;
1634
1635 if ((rankno == 2) && (dramtype[index][0] == 2))
1636 return ret;
1637
1638 ranksize = dramtype[index][3] / 2 * bw / 32;
1639
1640 if ((ranksize * rankno) > 128)
1641 return ret;
1642
1643 tmp = 0;
1644 while ((ranksize >>= 1) > 0) tmp += 0x10;
1645 tmp |= ((rankno - 1) << 2);
1646 tmp |= ((bw / 64) & 0x02);
1647 tmp |= (chab & 0x01);
1648
1649 ret = SETIREG(SISSR, 0x14, tmp);
1650 ret |= sisusb_triggersr16(sisusb, 0); /* sic! */
1651
1652 *iret = 1;
1653
1654 return ret;
1655}
1656
1657static int
1658sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret, u32 inc, int testn)
1659{
1660 int ret = 0, i;
1661 u32 j, tmp;
1662
1663 *iret = 0;
1664
1665 for (i = 0, j = 0; i < testn; i++) {
1666 ret |= WRITEL(sisusb->vrambase + j, j);
1667 j += inc;
1668 }
1669
1670 for (i = 0, j = 0; i < testn; i++) {
1671 ret |= READL(sisusb->vrambase + j, &tmp);
1672 if (tmp != j) return ret;
1673 j += inc;
1674 }
1675
1676 *iret = 1;
1677 return ret;
1678}
1679
1680static int
1681sisusb_check_ranks(struct sisusb_usb_data *sisusb, int *iret, int rankno,
1682 int idx, int bw, const u8 rtype[][5])
1683{
1684 int ret = 0, i, i2ret;
1685 u32 inc;
1686
1687 *iret = 0;
1688
1689 for (i = rankno; i >= 1; i--) {
1690 inc = 1 << (rtype[idx][2] +
1691 rtype[idx][1] +
1692 rtype[idx][0] +
1693 bw / 64 + i);
1694 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1695 if (!i2ret)
1696 return ret;
1697 }
1698
1699 inc = 1 << (rtype[idx][2] + bw / 64 + 2);
1700 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 4);
1701 if (!i2ret)
1702 return ret;
1703
1704 inc = 1 << (10 + bw / 64);
1705 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1706 if (!i2ret)
1707 return ret;
1708
1709 *iret = 1;
1710 return ret;
1711}
1712
1713static int
1714sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret, int bw,
1715 int chab)
1716{
1717 int ret = 0, i2ret = 0, i, j;
1718 static const u8 sdramtype[13][5] = {
1719 { 2, 12, 9, 64, 0x35 },
1720 { 1, 13, 9, 64, 0x44 },
1721 { 2, 12, 8, 32, 0x31 },
1722 { 2, 11, 9, 32, 0x25 },
1723 { 1, 12, 9, 32, 0x34 },
1724 { 1, 13, 8, 32, 0x40 },
1725 { 2, 11, 8, 16, 0x21 },
1726 { 1, 12, 8, 16, 0x30 },
1727 { 1, 11, 9, 16, 0x24 },
1728 { 1, 11, 8, 8, 0x20 },
1729 { 2, 9, 8, 4, 0x01 },
1730 { 1, 10, 8, 4, 0x10 },
1731 { 1, 9, 8, 2, 0x00 }
1732 };
1733
1734 *iret = 1; /* error */
1735
1736 for (i = 0; i < 13; i++) {
1737 ret |= SETIREGANDOR(SISSR, 0x13, 0x80, sdramtype[i][4]);
1738 for (j = 2; j > 0; j--) {
1739 ret |= sisusb_set_rank(sisusb, &i2ret, i, j,
1740 chab, sdramtype, bw);
1741 if (!i2ret)
1742 continue;
1743
1744 ret |= sisusb_check_ranks(sisusb, &i2ret, j, i,
1745 bw, sdramtype);
1746 if (i2ret) {
1747 *iret = 0; /* ram size found */
1748 return ret;
1749 }
1750 }
1751 }
1752
1753 return ret;
1754}
1755
1756static int
1757sisusb_setup_screen(struct sisusb_usb_data *sisusb, int clrall, int drwfr)
1758{
1759 int ret = 0;
1760 u32 address;
1761 int i, length, modex, modey, bpp;
1762
1763 modex = 640; modey = 480; bpp = 2;
1764
1765 address = sisusb->vrambase; /* Clear video ram */
1766
1767 if (clrall)
1768 length = sisusb->vramsize;
1769 else
1770 length = modex * bpp * modey;
1771
1772 ret = sisusb_clear_vram(sisusb, address, length);
1773
1774 if (!ret && drwfr) {
1775 for (i = 0; i < modex; i++) {
1776 address = sisusb->vrambase + (i * bpp);
1777 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1778 address, 0xf100);
1779 address += (modex * (modey-1) * bpp);
1780 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1781 address, 0xf100);
1782 }
1783 for (i = 0; i < modey; i++) {
1784 address = sisusb->vrambase + ((i * modex) * bpp);
1785 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1786 address, 0xf100);
1787 address += ((modex - 1) * bpp);
1788 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1789 address, 0xf100);
1790 }
1791 }
1792
1793 return ret;
1794}
1795
1796static int
1797sisusb_set_default_mode(struct sisusb_usb_data *sisusb, int touchengines)
1798{
1799 int ret = 0, i, j, modex, modey, bpp, du;
1800 u8 sr31, cr63, tmp8;
1801 static const char attrdata[] = {
1802 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
1803 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
1804 0x01,0x00,0x00,0x00
1805 };
1806 static const char crtcrdata[] = {
1807 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
1808 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
1809 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
1810 0xff
1811 };
1812 static const char grcdata[] = {
1813 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
1814 0xff
1815 };
1816 static const char crtcdata[] = {
1817 0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
1818 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
1819 0x00
1820 };
1821
1822 modex = 640; modey = 480; bpp = 2;
1823
1824 GETIREG(SISSR, 0x31, &sr31);
1825 GETIREG(SISCR, 0x63, &cr63);
1826 SETIREGOR(SISSR, 0x01, 0x20);
1827 SETIREG(SISCR, 0x63, cr63 & 0xbf);
1828 SETIREGOR(SISCR, 0x17, 0x80);
1829 SETIREGOR(SISSR, 0x1f, 0x04);
1830 SETIREGAND(SISSR, 0x07, 0xfb);
1831 SETIREG(SISSR, 0x00, 0x03); /* seq */
1832 SETIREG(SISSR, 0x01, 0x21);
1833 SETIREG(SISSR, 0x02, 0x0f);
1834 SETIREG(SISSR, 0x03, 0x00);
1835 SETIREG(SISSR, 0x04, 0x0e);
1836 SETREG(SISMISCW, 0x23); /* misc */
1837 for (i = 0; i <= 0x18; i++) { /* crtc */
1838 SETIREG(SISCR, i, crtcrdata[i]);
1839 }
1840 for (i = 0; i <= 0x13; i++) { /* att */
1841 GETREG(SISINPSTAT, &tmp8);
1842 SETREG(SISAR, i);
1843 SETREG(SISAR, attrdata[i]);
1844 }
1845 GETREG(SISINPSTAT, &tmp8);
1846 SETREG(SISAR, 0x14);
1847 SETREG(SISAR, 0x00);
1848 GETREG(SISINPSTAT, &tmp8);
1849 SETREG(SISAR, 0x20);
1850 GETREG(SISINPSTAT, &tmp8);
1851 for (i = 0; i <= 0x08; i++) { /* grc */
1852 SETIREG(SISGR, i, grcdata[i]);
1853 }
1854 SETIREGAND(SISGR, 0x05, 0xbf);
1855 for (i = 0x0A; i <= 0x0E; i++) { /* clr ext */
1856 SETIREG(SISSR, i, 0x00);
1857 }
1858 SETIREGAND(SISSR, 0x37, 0xfe);
1859 SETREG(SISMISCW, 0xef); /* sync */
1860 SETIREG(SISCR, 0x11, 0x00); /* crtc */
1861 for (j = 0x00, i = 0; i <= 7; i++, j++) {
1862 SETIREG(SISCR, j, crtcdata[i]);
1863 }
1864 for (j = 0x10; i <= 10; i++, j++) {
1865 SETIREG(SISCR, j, crtcdata[i]);
1866 }
1867 for (j = 0x15; i <= 12; i++, j++) {
1868 SETIREG(SISCR, j, crtcdata[i]);
1869 }
1870 for (j = 0x0A; i <= 15; i++, j++) {
1871 SETIREG(SISSR, j, crtcdata[i]);
1872 }
1873 SETIREG(SISSR, 0x0E, (crtcdata[16] & 0xE0));
1874 SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5));
1875 SETIREG(SISCR, 0x14, 0x4f);
1876 du = (modex / 16) * (bpp * 2); /* offset/pitch */
1877 if (modex % 16) du += bpp;
1878 SETIREGANDOR(SISSR, 0x0e, 0xf0, ((du >> 8) & 0x0f));
1879 SETIREG(SISCR, 0x13, (du & 0xff));
1880 du <<= 5;
1881 tmp8 = du >> 8;
1882 if (du & 0xff) tmp8++;
1883 SETIREG(SISSR, 0x10, tmp8);
1884 SETIREG(SISSR, 0x31, 0x00); /* VCLK */
1885 SETIREG(SISSR, 0x2b, 0x1b);
1886 SETIREG(SISSR, 0x2c, 0xe1);
1887 SETIREG(SISSR, 0x2d, 0x01);
1888 SETIREGAND(SISSR, 0x3d, 0xfe); /* FIFO */
1889 SETIREG(SISSR, 0x08, 0xae);
1890 SETIREGAND(SISSR, 0x09, 0xf0);
1891 SETIREG(SISSR, 0x08, 0x34);
1892 SETIREGOR(SISSR, 0x3d, 0x01);
1893 SETIREGAND(SISSR, 0x1f, 0x3f); /* mode regs */
1894 SETIREGANDOR(SISSR, 0x06, 0xc0, 0x0a);
1895 SETIREG(SISCR, 0x19, 0x00);
1896 SETIREGAND(SISCR, 0x1a, 0xfc);
1897 SETIREGAND(SISSR, 0x0f, 0xb7);
1898 SETIREGAND(SISSR, 0x31, 0xfb);
1899 SETIREGANDOR(SISSR, 0x21, 0x1f, 0xa0);
1900 SETIREGAND(SISSR, 0x32, 0xf3);
1901 SETIREGANDOR(SISSR, 0x07, 0xf8, 0x03);
1902 SETIREG(SISCR, 0x52, 0x6c);
1903
1904 SETIREG(SISCR, 0x0d, 0x00); /* adjust frame */
1905 SETIREG(SISCR, 0x0c, 0x00);
1906 SETIREG(SISSR, 0x0d, 0x00);
1907 SETIREGAND(SISSR, 0x37, 0xfe);
1908
1909 SETIREG(SISCR, 0x32, 0x20);
1910 SETIREGAND(SISSR, 0x01, 0xdf); /* enable display */
1911 SETIREG(SISCR, 0x63, (cr63 & 0xbf));
1912 SETIREG(SISSR, 0x31, (sr31 & 0xfb));
1913
1914 if (touchengines) {
1915 SETIREG(SISSR, 0x20, 0xa1); /* enable engines */
1916 SETIREGOR(SISSR, 0x1e, 0x5a);
1917
1918 SETIREG(SISSR, 0x26, 0x01); /* disable cmdqueue */
1919 SETIREG(SISSR, 0x27, 0x1f);
1920 SETIREG(SISSR, 0x26, 0x00);
1921 }
1922
1923 SETIREG(SISCR, 0x34, 0x44); /* we just set std mode #44 */
1924
1925 return ret;
1926}
1927
1928static int
1929sisusb_init_gfxcore(struct sisusb_usb_data *sisusb)
1930{
1931 int ret = 0, i, j, bw, chab, iret, retry = 3;
1932 u8 tmp8, ramtype;
1933 u32 tmp32;
1934 static const char mclktable[] = {
1935 0x3b, 0x22, 0x01, 143,
1936 0x3b, 0x22, 0x01, 143,
1937 0x3b, 0x22, 0x01, 143,
1938 0x3b, 0x22, 0x01, 143
1939 };
1940 static const char eclktable[] = {
1941 0x3b, 0x22, 0x01, 143,
1942 0x3b, 0x22, 0x01, 143,
1943 0x3b, 0x22, 0x01, 143,
1944 0x3b, 0x22, 0x01, 143
1945 };
1946 static const char ramtypetable1[] = {
1947 0x00, 0x04, 0x60, 0x60,
1948 0x0f, 0x0f, 0x1f, 0x1f,
1949 0xba, 0xba, 0xba, 0xba,
1950 0xa9, 0xa9, 0xac, 0xac,
1951 0xa0, 0xa0, 0xa0, 0xa8,
1952 0x00, 0x00, 0x02, 0x02,
1953 0x30, 0x30, 0x40, 0x40
1954 };
1955 static const char ramtypetable2[] = {
1956 0x77, 0x77, 0x44, 0x44,
1957 0x77, 0x77, 0x44, 0x44,
1958 0x00, 0x00, 0x00, 0x00,
1959 0x5b, 0x5b, 0xab, 0xab,
1960 0x00, 0x00, 0xf0, 0xf8
1961 };
1962
1963 while (retry--) {
1964
1965 /* Enable VGA */
1966 ret = GETREG(SISVGAEN, &tmp8);
1967 ret |= SETREG(SISVGAEN, (tmp8 | 0x01));
1968
1969 /* Enable GPU access to VRAM */
1970 ret |= GETREG(SISMISCR, &tmp8);
1971 ret |= SETREG(SISMISCW, (tmp8 | 0x01));
1972
1973 if (ret) continue;
1974
1975 /* Reset registers */
1976 ret |= SETIREGAND(SISCR, 0x5b, 0xdf);
1977 ret |= SETIREG(SISSR, 0x05, 0x86);
1978 ret |= SETIREGOR(SISSR, 0x20, 0x01);
1979
1980 ret |= SETREG(SISMISCW, 0x67);
1981
1982 for (i = 0x06; i <= 0x1f; i++) {
1983 ret |= SETIREG(SISSR, i, 0x00);
1984 }
1985 for (i = 0x21; i <= 0x27; i++) {
1986 ret |= SETIREG(SISSR, i, 0x00);
1987 }
1988 for (i = 0x31; i <= 0x3d; i++) {
1989 ret |= SETIREG(SISSR, i, 0x00);
1990 }
1991 for (i = 0x12; i <= 0x1b; i++) {
1992 ret |= SETIREG(SISSR, i, 0x00);
1993 }
1994 for (i = 0x79; i <= 0x7c; i++) {
1995 ret |= SETIREG(SISCR, i, 0x00);
1996 }
1997
1998 if (ret) continue;
1999
2000 ret |= SETIREG(SISCR, 0x63, 0x80);
2001
2002 ret |= GETIREG(SISSR, 0x3a, &ramtype);
2003 ramtype &= 0x03;
2004
2005 ret |= SETIREG(SISSR, 0x28, mclktable[ramtype * 4]);
2006 ret |= SETIREG(SISSR, 0x29, mclktable[(ramtype * 4) + 1]);
2007 ret |= SETIREG(SISSR, 0x2a, mclktable[(ramtype * 4) + 2]);
2008
2009 ret |= SETIREG(SISSR, 0x2e, eclktable[ramtype * 4]);
2010 ret |= SETIREG(SISSR, 0x2f, eclktable[(ramtype * 4) + 1]);
2011 ret |= SETIREG(SISSR, 0x30, eclktable[(ramtype * 4) + 2]);
2012
2013 ret |= SETIREG(SISSR, 0x07, 0x18);
2014 ret |= SETIREG(SISSR, 0x11, 0x0f);
2015
2016 if (ret) continue;
2017
2018 for (i = 0x15, j = 0; i <= 0x1b; i++, j++) {
2019 ret |= SETIREG(SISSR, i, ramtypetable1[(j*4) + ramtype]);
2020 }
2021 for (i = 0x40, j = 0; i <= 0x44; i++, j++) {
2022 ret |= SETIREG(SISCR, i, ramtypetable2[(j*4) + ramtype]);
2023 }
2024
2025 ret |= SETIREG(SISCR, 0x49, 0xaa);
2026
2027 ret |= SETIREG(SISSR, 0x1f, 0x00);
2028 ret |= SETIREG(SISSR, 0x20, 0xa0);
2029 ret |= SETIREG(SISSR, 0x23, 0xf6);
2030 ret |= SETIREG(SISSR, 0x24, 0x0d);
2031 ret |= SETIREG(SISSR, 0x25, 0x33);
2032
2033 ret |= SETIREG(SISSR, 0x11, 0x0f);
2034
2035 ret |= SETIREGOR(SISPART1, 0x2f, 0x01);
2036
2037 ret |= SETIREGAND(SISCAP, 0x3f, 0xef);
2038
2039 if (ret) continue;
2040
2041 ret |= SETIREG(SISPART1, 0x00, 0x00);
2042
2043 ret |= GETIREG(SISSR, 0x13, &tmp8);
2044 tmp8 >>= 4;
2045
2046 ret |= SETIREG(SISPART1, 0x02, 0x00);
2047 ret |= SETIREG(SISPART1, 0x2e, 0x08);
2048
2049 ret |= sisusb_read_pci_config(sisusb, 0x50, &tmp32);
2050 tmp32 &= 0x00f00000;
2051 tmp8 = (tmp32 == 0x100000) ? 0x33 : 0x03;
2052 ret |= SETIREG(SISSR, 0x25, tmp8);
2053 tmp8 = (tmp32 == 0x100000) ? 0xaa : 0x88;
2054 ret |= SETIREG(SISCR, 0x49, tmp8);
2055
2056 ret |= SETIREG(SISSR, 0x27, 0x1f);
2057 ret |= SETIREG(SISSR, 0x31, 0x00);
2058 ret |= SETIREG(SISSR, 0x32, 0x11);
2059 ret |= SETIREG(SISSR, 0x33, 0x00);
2060
2061 if (ret) continue;
2062
2063 ret |= SETIREG(SISCR, 0x83, 0x00);
2064
2065 ret |= sisusb_set_default_mode(sisusb, 0);
2066
2067 ret |= SETIREGAND(SISSR, 0x21, 0xdf);
2068 ret |= SETIREGOR(SISSR, 0x01, 0x20);
2069 ret |= SETIREGOR(SISSR, 0x16, 0x0f);
2070
2071 ret |= sisusb_triggersr16(sisusb, ramtype);
2072
2073 /* Disable refresh */
2074 ret |= SETIREGAND(SISSR, 0x17, 0xf8);
2075 ret |= SETIREGOR(SISSR, 0x19, 0x03);
2076
2077 ret |= sisusb_getbuswidth(sisusb, &bw, &chab);
2078 ret |= sisusb_verify_mclk(sisusb);
2079
2080 if (ramtype <= 1) {
2081 ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab);
2082 if (iret) {
2083 dev_err(&sisusb->sisusb_dev->dev,"RAM size detection failed, assuming 8MB video RAM\n");
2084 ret |= SETIREG(SISSR,0x14,0x31);
2085 /* TODO */
2086 }
2087 } else {
2088 dev_err(&sisusb->sisusb_dev->dev, "DDR RAM device found, assuming 8MB video RAM\n");
2089 ret |= SETIREG(SISSR,0x14,0x31);
2090 /* *** TODO *** */
2091 }
2092
2093 /* Enable refresh */
2094 ret |= SETIREG(SISSR, 0x16, ramtypetable1[4 + ramtype]);
2095 ret |= SETIREG(SISSR, 0x17, ramtypetable1[8 + ramtype]);
2096 ret |= SETIREG(SISSR, 0x19, ramtypetable1[16 + ramtype]);
2097
2098 ret |= SETIREGOR(SISSR, 0x21, 0x20);
2099
2100 ret |= SETIREG(SISSR, 0x22, 0xfb);
2101 ret |= SETIREG(SISSR, 0x21, 0xa5);
2102
2103 if (ret == 0)
2104 break;
2105 }
2106
2107 return ret;
2108}
2109
2110#undef SETREG
2111#undef GETREG
2112#undef SETIREG
2113#undef GETIREG
2114#undef SETIREGOR
2115#undef SETIREGAND
2116#undef SETIREGANDOR
2117#undef READL
2118#undef WRITEL
2119
2120static void
2121sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
2122{
2123 u8 tmp8, tmp82, ramtype;
2124 int bw = 0;
2125 char *ramtypetext1 = NULL;
2126 static const char ram_datarate[4] = {'S', 'S', 'D', 'D'};
2127 static const char ram_dynamictype[4] = {'D', 'G', 'D', 'G'};
2128 static const int busSDR[4] = {64, 64, 128, 128};
2129 static const int busDDR[4] = {32, 32, 64, 64};
2130 static const int busDDRA[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2};
2131
2132 sisusb_getidxreg(sisusb, SISSR, 0x14, &tmp8);
2133 sisusb_getidxreg(sisusb, SISSR, 0x15, &tmp82);
2134 sisusb_getidxreg(sisusb, SISSR, 0x3a, &ramtype);
2135 sisusb->vramsize = (1 << ((tmp8 & 0xf0) >> 4)) * 1024 * 1024;
2136 ramtype &= 0x03;
2137 switch ((tmp8 >> 2) & 0x03) {
2138 case 0: ramtypetext1 = "1 ch/1 r";
2139 if (tmp82 & 0x10) {
2140 bw = 32;
2141 } else {
2142 bw = busSDR[(tmp8 & 0x03)];
2143 }
2144 break;
2145 case 1: ramtypetext1 = "1 ch/2 r";
2146 sisusb->vramsize <<= 1;
2147 bw = busSDR[(tmp8 & 0x03)];
2148 break;
2149 case 2: ramtypetext1 = "asymmeric";
2150 sisusb->vramsize += sisusb->vramsize/2;
2151 bw = busDDRA[(tmp8 & 0x03)];
2152 break;
2153 case 3: ramtypetext1 = "2 channel";
2154 sisusb->vramsize <<= 1;
2155 bw = busDDR[(tmp8 & 0x03)];
2156 break;
2157 }
2158
2159
2160 dev_info(&sisusb->sisusb_dev->dev, "%dMB %s %cDR S%cRAM, bus width %d\n",
2161 sisusb->vramsize >> 20, ramtypetext1,
2162 ram_datarate[ramtype], ram_dynamictype[ramtype], bw);
2163}
2164
2165static int
2166sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb)
2167{
2168 struct sisusb_packet packet;
2169 int ret;
2170 u32 tmp32;
2171
2172 /* Do some magic */
2173 packet.header = 0x001f;
2174 packet.address = 0x00000324;
2175 packet.data = 0x00000004;
2176 ret = sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2177
2178 packet.header = 0x001f;
2179 packet.address = 0x00000364;
2180 packet.data = 0x00000004;
2181 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2182
2183 packet.header = 0x001f;
2184 packet.address = 0x00000384;
2185 packet.data = 0x00000004;
2186 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2187
2188 packet.header = 0x001f;
2189 packet.address = 0x00000100;
2190 packet.data = 0x00000700;
2191 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2192
2193 packet.header = 0x000f;
2194 packet.address = 0x00000004;
2195 ret |= sisusb_send_bridge_packet(sisusb, 6, &packet, 0);
2196 packet.data |= 0x17;
2197 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2198
2199 /* Init BAR 0 (VRAM) */
2200 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2201 ret |= sisusb_write_pci_config(sisusb, 0x10, 0xfffffff0);
2202 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2203 tmp32 &= 0x0f;
2204 tmp32 |= SISUSB_PCI_MEMBASE;
2205 ret |= sisusb_write_pci_config(sisusb, 0x10, tmp32);
2206
2207 /* Init BAR 1 (MMIO) */
2208 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2209 ret |= sisusb_write_pci_config(sisusb, 0x14, 0xfffffff0);
2210 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2211 tmp32 &= 0x0f;
2212 tmp32 |= SISUSB_PCI_MMIOBASE;
2213 ret |= sisusb_write_pci_config(sisusb, 0x14, tmp32);
2214
2215 /* Init BAR 2 (i/o ports) */
2216 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2217 ret |= sisusb_write_pci_config(sisusb, 0x18, 0xfffffff0);
2218 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2219 tmp32 &= 0x0f;
2220 tmp32 |= SISUSB_PCI_IOPORTBASE;
2221 ret |= sisusb_write_pci_config(sisusb, 0x18, tmp32);
2222
2223 /* Enable memory and i/o access */
2224 ret |= sisusb_read_pci_config(sisusb, 0x04, &tmp32);
2225 tmp32 |= 0x3;
2226 ret |= sisusb_write_pci_config(sisusb, 0x04, tmp32);
2227
2228 if (ret == 0) {
2229 /* Some further magic */
2230 packet.header = 0x001f;
2231 packet.address = 0x00000050;
2232 packet.data = 0x000000ff;
2233 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2234 }
2235
2236 return ret;
2237}
2238
2239/* Initialize the graphics device (return 0 on success)
2240 * This initializes the net2280 as well as the PCI registers
2241 * of the graphics board.
2242 */
2243
2244static int
2245sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
2246{
2247 int ret = 0, test = 0;
2248 u32 tmp32;
2249
2250 if (sisusb->devinit == 1) {
2251 /* Read PCI BARs and see if they have been set up */
2252 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2253 if (ret) return ret;
2254 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE) test++;
2255
2256 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2257 if (ret) return ret;
2258 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE) test++;
2259
2260 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2261 if (ret) return ret;
2262 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE) test++;
2263 }
2264
2265 /* No? So reset the device */
2266 if ((sisusb->devinit == 0) || (test != 3)) {
2267
2268 ret |= sisusb_do_init_gfxdevice(sisusb);
2269
2270 if (ret == 0)
2271 sisusb->devinit = 1;
2272
2273 }
2274
2275 if (sisusb->devinit) {
2276 /* Initialize the graphics core */
2277 if (sisusb_init_gfxcore(sisusb) == 0) {
2278 sisusb->gfxinit = 1;
2279 sisusb_get_ramconfig(sisusb);
2280 ret |= sisusb_set_default_mode(sisusb, 1);
2281 ret |= sisusb_setup_screen(sisusb, 1, initscreen);
2282 }
2283 }
2284
2285 return ret;
2286}
2287
2288
2289#ifdef INCL_SISUSB_CON
2290
2291/* Set up default text mode:
2292 - Set text mode (0x03)
2293 - Upload default font
2294 - Upload user font (if available)
2295*/
2296
2297int
2298sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
2299{
2300 int ret = 0, slot = sisusb->font_slot, i;
2301 const struct font_desc *myfont;
2302 u8 *tempbuf;
2303 u16 *tempbufb;
2304 size_t written;
2305 static const char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2306 static const char bootlogo[] = "(o_ //\\ V_/_";
2307
2308 /* sisusb->lock is down */
2309
2310 if (!sisusb->SiS_Pr)
2311 return 1;
2312
2313 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2314 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2315
2316 /* Set mode 0x03 */
2317 SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
2318
2319 if (!(myfont = find_font("VGA8x16")))
2320 return 1;
2321
2322 if (!(tempbuf = vmalloc(8192)))
2323 return 1;
2324
2325 for (i = 0; i < 256; i++)
2326 memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
2327
2328 /* Upload default font */
2329 ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, 0, 1, NULL, 16, 0);
2330
2331 vfree(tempbuf);
2332
2333 /* Upload user font (and reset current slot) */
2334 if (sisusb->font_backup) {
2335 ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
2336 8192, sisusb->font_backup_512, 1, NULL,
2337 sisusb->font_backup_height, 0);
2338 if (slot != 2)
2339 sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
2340 NULL, 16, 0);
2341 }
2342
2343 if (init && !sisusb->scrbuf) {
2344
2345 if ((tempbuf = vmalloc(8192))) {
2346
2347 i = 4096;
2348 tempbufb = (u16 *)tempbuf;
2349 while (i--)
2350 *(tempbufb++) = 0x0720;
2351
2352 i = 0;
2353 tempbufb = (u16 *)tempbuf;
2354 while (bootlogo[i]) {
2355 *(tempbufb++) = 0x0700 | bootlogo[i++];
2356 if (!(i % 4))
2357 tempbufb += 76;
2358 }
2359
2360 i = 0;
2361 tempbufb = (u16 *)tempbuf + 6;
2362 while (bootstring[i])
2363 *(tempbufb++) = 0x0700 | bootstring[i++];
2364
2365 ret |= sisusb_copy_memory(sisusb, tempbuf,
2366 sisusb->vrambase, 8192, &written);
2367
2368 vfree(tempbuf);
2369
2370 }
2371
2372 } else if (sisusb->scrbuf) {
2373
2374 ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
2375 sisusb->vrambase, sisusb->scrbuf_size, &written);
2376
2377 }
2378
2379 if (sisusb->sisusb_cursor_size_from >= 0 &&
2380 sisusb->sisusb_cursor_size_to >= 0) {
2381 sisusb_setidxreg(sisusb, SISCR, 0x0a,
2382 sisusb->sisusb_cursor_size_from);
2383 sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
2384 sisusb->sisusb_cursor_size_to);
2385 } else {
2386 sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
2387 sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
2388 sisusb->sisusb_cursor_size_to = -1;
2389 }
2390
2391 slot = sisusb->sisusb_cursor_loc;
2392 if(slot < 0) slot = 0;
2393
2394 sisusb->sisusb_cursor_loc = -1;
2395 sisusb->bad_cursor_pos = 1;
2396
2397 sisusb_set_cursor(sisusb, slot);
2398
2399 sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
2400 sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
2401
2402 sisusb->textmodedestroyed = 0;
2403
2404 /* sisusb->lock is down */
2405
2406 return ret;
2407}
2408
2409#endif
2410
2411/* fops */
2412
2413static int
2414sisusb_open(struct inode *inode, struct file *file)
2415{
2416 struct sisusb_usb_data *sisusb;
2417 struct usb_interface *interface;
2418 int subminor = iminor(inode);
2419
2420 if (!(interface = usb_find_interface(&sisusb_driver, subminor))) {
2421 return -ENODEV;
2422 }
2423
2424 if (!(sisusb = usb_get_intfdata(interface))) {
2425 return -ENODEV;
2426 }
2427
2428 mutex_lock(&sisusb->lock);
2429
2430 if (!sisusb->present || !sisusb->ready) {
2431 mutex_unlock(&sisusb->lock);
2432 return -ENODEV;
2433 }
2434
2435 if (sisusb->isopen) {
2436 mutex_unlock(&sisusb->lock);
2437 return -EBUSY;
2438 }
2439
2440 if (!sisusb->devinit) {
2441 if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH ||
2442 sisusb->sisusb_dev->speed == USB_SPEED_SUPER) {
2443 if (sisusb_init_gfxdevice(sisusb, 0)) {
2444 mutex_unlock(&sisusb->lock);
2445 dev_err(&sisusb->sisusb_dev->dev, "Failed to initialize device\n");
2446 return -EIO;
2447 }
2448 } else {
2449 mutex_unlock(&sisusb->lock);
2450 dev_err(&sisusb->sisusb_dev->dev, "Device not attached to USB 2.0 hub\n");
2451 return -EIO;
2452 }
2453 }
2454
2455 /* Increment usage count for our sisusb */
2456 kref_get(&sisusb->kref);
2457
2458 sisusb->isopen = 1;
2459
2460 file->private_data = sisusb;
2461
2462 mutex_unlock(&sisusb->lock);
2463
2464 return 0;
2465}
2466
2467void
2468sisusb_delete(struct kref *kref)
2469{
2470 struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
2471
2472 if (!sisusb)
2473 return;
2474
2475 if (sisusb->sisusb_dev)
2476 usb_put_dev(sisusb->sisusb_dev);
2477
2478 sisusb->sisusb_dev = NULL;
2479 sisusb_free_buffers(sisusb);
2480 sisusb_free_urbs(sisusb);
2481#ifdef INCL_SISUSB_CON
2482 kfree(sisusb->SiS_Pr);
2483#endif
2484 kfree(sisusb);
2485}
2486
2487static int
2488sisusb_release(struct inode *inode, struct file *file)
2489{
2490 struct sisusb_usb_data *sisusb;
2491
2492 if (!(sisusb = file->private_data))
2493 return -ENODEV;
2494
2495 mutex_lock(&sisusb->lock);
2496
2497 if (sisusb->present) {
2498 /* Wait for all URBs to finish if device still present */
2499 if (!sisusb_wait_all_out_complete(sisusb))
2500 sisusb_kill_all_busy(sisusb);
2501 }
2502
2503 sisusb->isopen = 0;
2504 file->private_data = NULL;
2505
2506 mutex_unlock(&sisusb->lock);
2507
2508 /* decrement the usage count on our device */
2509 kref_put(&sisusb->kref, sisusb_delete);
2510
2511 return 0;
2512}
2513
2514static ssize_t
2515sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
2516{
2517 struct sisusb_usb_data *sisusb;
2518 ssize_t bytes_read = 0;
2519 int errno = 0;
2520 u8 buf8;
2521 u16 buf16;
2522 u32 buf32, address;
2523
2524 if (!(sisusb = file->private_data))
2525 return -ENODEV;
2526
2527 mutex_lock(&sisusb->lock);
2528
2529 /* Sanity check */
2530 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2531 mutex_unlock(&sisusb->lock);
2532 return -ENODEV;
2533 }
2534
2535 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2536 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2537
2538 address = (*ppos) -
2539 SISUSB_PCI_PSEUDO_IOPORTBASE +
2540 SISUSB_PCI_IOPORTBASE;
2541
2542 /* Read i/o ports
2543 * Byte, word and long(32) can be read. As this
2544 * emulates inX instructions, the data returned is
2545 * in machine-endianness.
2546 */
2547 switch (count) {
2548
2549 case 1:
2550 if (sisusb_read_memio_byte(sisusb,
2551 SISUSB_TYPE_IO,
2552 address, &buf8))
2553 errno = -EIO;
2554 else if (put_user(buf8, (u8 __user *)buffer))
2555 errno = -EFAULT;
2556 else
2557 bytes_read = 1;
2558
2559 break;
2560
2561 case 2:
2562 if (sisusb_read_memio_word(sisusb,
2563 SISUSB_TYPE_IO,
2564 address, &buf16))
2565 errno = -EIO;
2566 else if (put_user(buf16, (u16 __user *)buffer))
2567 errno = -EFAULT;
2568 else
2569 bytes_read = 2;
2570
2571 break;
2572
2573 case 4:
2574 if (sisusb_read_memio_long(sisusb,
2575 SISUSB_TYPE_IO,
2576 address, &buf32))
2577 errno = -EIO;
2578 else if (put_user(buf32, (u32 __user *)buffer))
2579 errno = -EFAULT;
2580 else
2581 bytes_read = 4;
2582
2583 break;
2584
2585 default:
2586 errno = -EIO;
2587
2588 }
2589
2590 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2591 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2592
2593 address = (*ppos) -
2594 SISUSB_PCI_PSEUDO_MEMBASE +
2595 SISUSB_PCI_MEMBASE;
2596
2597 /* Read video ram
2598 * Remember: Data delivered is never endian-corrected
2599 */
2600 errno = sisusb_read_mem_bulk(sisusb, address,
2601 NULL, count, buffer, &bytes_read);
2602
2603 if (bytes_read)
2604 errno = bytes_read;
2605
2606 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2607 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) {
2608
2609 address = (*ppos) -
2610 SISUSB_PCI_PSEUDO_MMIOBASE +
2611 SISUSB_PCI_MMIOBASE;
2612
2613 /* Read MMIO
2614 * Remember: Data delivered is never endian-corrected
2615 */
2616 errno = sisusb_read_mem_bulk(sisusb, address,
2617 NULL, count, buffer, &bytes_read);
2618
2619 if (bytes_read)
2620 errno = bytes_read;
2621
2622 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2623 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
2624
2625 if (count != 4) {
2626 mutex_unlock(&sisusb->lock);
2627 return -EINVAL;
2628 }
2629
2630 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2631
2632 /* Read PCI config register
2633 * Return value delivered in machine endianness.
2634 */
2635 if (sisusb_read_pci_config(sisusb, address, &buf32))
2636 errno = -EIO;
2637 else if (put_user(buf32, (u32 __user *)buffer))
2638 errno = -EFAULT;
2639 else
2640 bytes_read = 4;
2641
2642 } else {
2643
2644 errno = -EBADFD;
2645
2646 }
2647
2648 (*ppos) += bytes_read;
2649
2650 mutex_unlock(&sisusb->lock);
2651
2652 return errno ? errno : bytes_read;
2653}
2654
2655static ssize_t
2656sisusb_write(struct file *file, const char __user *buffer, size_t count,
2657 loff_t *ppos)
2658{
2659 struct sisusb_usb_data *sisusb;
2660 int errno = 0;
2661 ssize_t bytes_written = 0;
2662 u8 buf8;
2663 u16 buf16;
2664 u32 buf32, address;
2665
2666 if (!(sisusb = file->private_data))
2667 return -ENODEV;
2668
2669 mutex_lock(&sisusb->lock);
2670
2671 /* Sanity check */
2672 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2673 mutex_unlock(&sisusb->lock);
2674 return -ENODEV;
2675 }
2676
2677 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2678 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2679
2680 address = (*ppos) -
2681 SISUSB_PCI_PSEUDO_IOPORTBASE +
2682 SISUSB_PCI_IOPORTBASE;
2683
2684 /* Write i/o ports
2685 * Byte, word and long(32) can be written. As this
2686 * emulates outX instructions, the data is expected
2687 * in machine-endianness.
2688 */
2689 switch (count) {
2690
2691 case 1:
2692 if (get_user(buf8, (u8 __user *)buffer))
2693 errno = -EFAULT;
2694 else if (sisusb_write_memio_byte(sisusb,
2695 SISUSB_TYPE_IO,
2696 address, buf8))
2697 errno = -EIO;
2698 else
2699 bytes_written = 1;
2700
2701 break;
2702
2703 case 2:
2704 if (get_user(buf16, (u16 __user *)buffer))
2705 errno = -EFAULT;
2706 else if (sisusb_write_memio_word(sisusb,
2707 SISUSB_TYPE_IO,
2708 address, buf16))
2709 errno = -EIO;
2710 else
2711 bytes_written = 2;
2712
2713 break;
2714
2715 case 4:
2716 if (get_user(buf32, (u32 __user *)buffer))
2717 errno = -EFAULT;
2718 else if (sisusb_write_memio_long(sisusb,
2719 SISUSB_TYPE_IO,
2720 address, buf32))
2721 errno = -EIO;
2722 else
2723 bytes_written = 4;
2724
2725 break;
2726
2727 default:
2728 errno = -EIO;
2729 }
2730
2731 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2732 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2733
2734 address = (*ppos) -
2735 SISUSB_PCI_PSEUDO_MEMBASE +
2736 SISUSB_PCI_MEMBASE;
2737
2738 /* Write video ram.
2739 * Buffer is copied 1:1, therefore, on big-endian
2740 * machines, the data must be swapped by userland
2741 * in advance (if applicable; no swapping in 8bpp
2742 * mode or if YUV data is being transferred).
2743 */
2744 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2745 count, buffer, 0, &bytes_written);
2746
2747 if (bytes_written)
2748 errno = bytes_written;
2749
2750 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2751 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) {
2752
2753 address = (*ppos) -
2754 SISUSB_PCI_PSEUDO_MMIOBASE +
2755 SISUSB_PCI_MMIOBASE;
2756
2757 /* Write MMIO.
2758 * Buffer is copied 1:1, therefore, on big-endian
2759 * machines, the data must be swapped by userland
2760 * in advance.
2761 */
2762 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2763 count, buffer, 0, &bytes_written);
2764
2765 if (bytes_written)
2766 errno = bytes_written;
2767
2768 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2769 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + SISUSB_PCI_PCONFSIZE) {
2770
2771 if (count != 4) {
2772 mutex_unlock(&sisusb->lock);
2773 return -EINVAL;
2774 }
2775
2776 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2777
2778 /* Write PCI config register.
2779 * Given value expected in machine endianness.
2780 */
2781 if (get_user(buf32, (u32 __user *)buffer))
2782 errno = -EFAULT;
2783 else if (sisusb_write_pci_config(sisusb, address, buf32))
2784 errno = -EIO;
2785 else
2786 bytes_written = 4;
2787
2788
2789 } else {
2790
2791 /* Error */
2792 errno = -EBADFD;
2793
2794 }
2795
2796 (*ppos) += bytes_written;
2797
2798 mutex_unlock(&sisusb->lock);
2799
2800 return errno ? errno : bytes_written;
2801}
2802
2803static loff_t
2804sisusb_lseek(struct file *file, loff_t offset, int orig)
2805{
2806 struct sisusb_usb_data *sisusb;
2807 loff_t ret;
2808
2809 if (!(sisusb = file->private_data))
2810 return -ENODEV;
2811
2812 mutex_lock(&sisusb->lock);
2813
2814 /* Sanity check */
2815 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2816 mutex_unlock(&sisusb->lock);
2817 return -ENODEV;
2818 }
2819
2820 switch (orig) {
2821 case 0:
2822 file->f_pos = offset;
2823 ret = file->f_pos;
2824 /* never negative, no force_successful_syscall needed */
2825 break;
2826 case 1:
2827 file->f_pos += offset;
2828 ret = file->f_pos;
2829 /* never negative, no force_successful_syscall needed */
2830 break;
2831 default:
2832 /* seeking relative to "end of file" is not supported */
2833 ret = -EINVAL;
2834 }
2835
2836 mutex_unlock(&sisusb->lock);
2837 return ret;
2838}
2839
2840static int
2841sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
2842 unsigned long arg)
2843{
2844 int retval, port, length;
2845 u32 address;
2846
2847 /* All our commands require the device
2848 * to be initialized.
2849 */
2850 if (!sisusb->devinit)
2851 return -ENODEV;
2852
2853 port = y->data3 -
2854 SISUSB_PCI_PSEUDO_IOPORTBASE +
2855 SISUSB_PCI_IOPORTBASE;
2856
2857 switch (y->operation) {
2858 case SUCMD_GET:
2859 retval = sisusb_getidxreg(sisusb, port,
2860 y->data0, &y->data1);
2861 if (!retval) {
2862 if (copy_to_user((void __user *)arg, y,
2863 sizeof(*y)))
2864 retval = -EFAULT;
2865 }
2866 break;
2867
2868 case SUCMD_SET:
2869 retval = sisusb_setidxreg(sisusb, port,
2870 y->data0, y->data1);
2871 break;
2872
2873 case SUCMD_SETOR:
2874 retval = sisusb_setidxregor(sisusb, port,
2875 y->data0, y->data1);
2876 break;
2877
2878 case SUCMD_SETAND:
2879 retval = sisusb_setidxregand(sisusb, port,
2880 y->data0, y->data1);
2881 break;
2882
2883 case SUCMD_SETANDOR:
2884 retval = sisusb_setidxregandor(sisusb, port,
2885 y->data0, y->data1, y->data2);
2886 break;
2887
2888 case SUCMD_SETMASK:
2889 retval = sisusb_setidxregmask(sisusb, port,
2890 y->data0, y->data1, y->data2);
2891 break;
2892
2893 case SUCMD_CLRSCR:
2894 /* Gfx core must be initialized */
2895 if (!sisusb->gfxinit)
2896 return -ENODEV;
2897
2898 length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
2899 address = y->data3 -
2900 SISUSB_PCI_PSEUDO_MEMBASE +
2901 SISUSB_PCI_MEMBASE;
2902 retval = sisusb_clear_vram(sisusb, address, length);
2903 break;
2904
2905 case SUCMD_HANDLETEXTMODE:
2906 retval = 0;
2907#ifdef INCL_SISUSB_CON
2908 /* Gfx core must be initialized, SiS_Pr must exist */
2909 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2910 return -ENODEV;
2911
2912 switch (y->data0) {
2913 case 0:
2914 retval = sisusb_reset_text_mode(sisusb, 0);
2915 break;
2916 case 1:
2917 sisusb->textmodedestroyed = 1;
2918 break;
2919 }
2920#endif
2921 break;
2922
2923#ifdef INCL_SISUSB_CON
2924 case SUCMD_SETMODE:
2925 /* Gfx core must be initialized, SiS_Pr must exist */
2926 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2927 return -ENODEV;
2928
2929 retval = 0;
2930
2931 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2932 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2933
2934 if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
2935 retval = -EINVAL;
2936
2937 break;
2938
2939 case SUCMD_SETVESAMODE:
2940 /* Gfx core must be initialized, SiS_Pr must exist */
2941 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2942 return -ENODEV;
2943
2944 retval = 0;
2945
2946 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2947 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2948
2949 if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
2950 retval = -EINVAL;
2951
2952 break;
2953#endif
2954
2955 default:
2956 retval = -EINVAL;
2957 }
2958
2959 if (retval > 0)
2960 retval = -EIO;
2961
2962 return retval;
2963}
2964
2965static long
2966sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2967{
2968 struct sisusb_usb_data *sisusb;
2969 struct sisusb_info x;
2970 struct sisusb_command y;
2971 long retval = 0;
2972 u32 __user *argp = (u32 __user *)arg;
2973
2974 if (!(sisusb = file->private_data))
2975 return -ENODEV;
2976
2977 mutex_lock(&sisusb->lock);
2978
2979 /* Sanity check */
2980 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2981 retval = -ENODEV;
2982 goto err_out;
2983 }
2984
2985 switch (cmd) {
2986
2987 case SISUSB_GET_CONFIG_SIZE:
2988
2989 if (put_user(sizeof(x), argp))
2990 retval = -EFAULT;
2991
2992 break;
2993
2994 case SISUSB_GET_CONFIG:
2995
2996 x.sisusb_id = SISUSB_ID;
2997 x.sisusb_version = SISUSB_VERSION;
2998 x.sisusb_revision = SISUSB_REVISION;
2999 x.sisusb_patchlevel = SISUSB_PATCHLEVEL;
3000 x.sisusb_gfxinit = sisusb->gfxinit;
3001 x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE;
3002 x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE;
3003 x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE;
3004 x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE;
3005 x.sisusb_vramsize = sisusb->vramsize;
3006 x.sisusb_minor = sisusb->minor;
3007 x.sisusb_fbdevactive= 0;
3008#ifdef INCL_SISUSB_CON
3009 x.sisusb_conactive = sisusb->haveconsole ? 1 : 0;
3010#else
3011 x.sisusb_conactive = 0;
3012#endif
3013 memset(x.sisusb_reserved, 0, sizeof(x.sisusb_reserved));
3014
3015 if (copy_to_user((void __user *)arg, &x, sizeof(x)))
3016 retval = -EFAULT;
3017
3018 break;
3019
3020 case SISUSB_COMMAND:
3021
3022 if (copy_from_user(&y, (void __user *)arg, sizeof(y)))
3023 retval = -EFAULT;
3024 else
3025 retval = sisusb_handle_command(sisusb, &y, arg);
3026
3027 break;
3028
3029 default:
3030 retval = -ENOTTY;
3031 break;
3032 }
3033
3034err_out:
3035 mutex_unlock(&sisusb->lock);
3036 return retval;
3037}
3038
3039#ifdef SISUSB_NEW_CONFIG_COMPAT
3040static long
3041sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
3042{
3043 long retval;
3044
3045 switch (cmd) {
3046 case SISUSB_GET_CONFIG_SIZE:
3047 case SISUSB_GET_CONFIG:
3048 case SISUSB_COMMAND:
3049 retval = sisusb_ioctl(f, cmd, arg);
3050 return retval;
3051
3052 default:
3053 return -ENOIOCTLCMD;
3054 }
3055}
3056#endif
3057
3058static const struct file_operations usb_sisusb_fops = {
3059 .owner = THIS_MODULE,
3060 .open = sisusb_open,
3061 .release = sisusb_release,
3062 .read = sisusb_read,
3063 .write = sisusb_write,
3064 .llseek = sisusb_lseek,
3065#ifdef SISUSB_NEW_CONFIG_COMPAT
3066 .compat_ioctl = sisusb_compat_ioctl,
3067#endif
3068 .unlocked_ioctl = sisusb_ioctl
3069};
3070
3071static struct usb_class_driver usb_sisusb_class = {
3072 .name = "sisusbvga%d",
3073 .fops = &usb_sisusb_fops,
3074 .minor_base = SISUSB_MINOR
3075};
3076
3077static int sisusb_probe(struct usb_interface *intf,
3078 const struct usb_device_id *id)
3079{
3080 struct usb_device *dev = interface_to_usbdev(intf);
3081 struct sisusb_usb_data *sisusb;
3082 int retval = 0, i;
3083
3084 dev_info(&dev->dev, "USB2VGA dongle found at address %d\n",
3085 dev->devnum);
3086
3087 /* Allocate memory for our private */
3088 if (!(sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL))) {
3089 dev_err(&dev->dev, "Failed to allocate memory for private data\n");
3090 return -ENOMEM;
3091 }
3092 kref_init(&sisusb->kref);
3093
3094 mutex_init(&(sisusb->lock));
3095
3096 /* Register device */
3097 if ((retval = usb_register_dev(intf, &usb_sisusb_class))) {
3098 dev_err(&sisusb->sisusb_dev->dev, "Failed to get a minor for device %d\n",
3099 dev->devnum);
3100 retval = -ENODEV;
3101 goto error_1;
3102 }
3103
3104 sisusb->sisusb_dev = dev;
3105 sisusb->minor = intf->minor;
3106 sisusb->vrambase = SISUSB_PCI_MEMBASE;
3107 sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
3108 sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
3109 sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
3110 /* Everything else is zero */
3111
3112 /* Allocate buffers */
3113 sisusb->ibufsize = SISUSB_IBUF_SIZE;
3114 if (!(sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL))) {
3115 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for input buffer");
3116 retval = -ENOMEM;
3117 goto error_2;
3118 }
3119
3120 sisusb->numobufs = 0;
3121 sisusb->obufsize = SISUSB_OBUF_SIZE;
3122 for (i = 0; i < NUMOBUFS; i++) {
3123 if (!(sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL))) {
3124 if (i == 0) {
3125 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for output buffer\n");
3126 retval = -ENOMEM;
3127 goto error_3;
3128 }
3129 break;
3130 } else
3131 sisusb->numobufs++;
3132
3133 }
3134
3135 /* Allocate URBs */
3136 if (!(sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL))) {
3137 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n");
3138 retval = -ENOMEM;
3139 goto error_3;
3140 }
3141 sisusb->completein = 1;
3142
3143 for (i = 0; i < sisusb->numobufs; i++) {
3144 if (!(sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL))) {
3145 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n");
3146 retval = -ENOMEM;
3147 goto error_4;
3148 }
3149 sisusb->urbout_context[i].sisusb = (void *)sisusb;
3150 sisusb->urbout_context[i].urbindex = i;
3151 sisusb->urbstatus[i] = 0;
3152 }
3153
3154 dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n", sisusb->numobufs);
3155
3156#ifdef INCL_SISUSB_CON
3157 /* Allocate our SiS_Pr */
3158 if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) {
3159 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate SiS_Pr\n");
3160 }
3161#endif
3162
3163 /* Do remaining init stuff */
3164
3165 init_waitqueue_head(&sisusb->wait_q);
3166
3167 usb_set_intfdata(intf, sisusb);
3168
3169 usb_get_dev(sisusb->sisusb_dev);
3170
3171 sisusb->present = 1;
3172
3173 if (dev->speed == USB_SPEED_HIGH || dev->speed == USB_SPEED_SUPER) {
3174 int initscreen = 1;
3175#ifdef INCL_SISUSB_CON
3176 if (sisusb_first_vc > 0 &&
3177 sisusb_last_vc > 0 &&
3178 sisusb_first_vc <= sisusb_last_vc &&
3179 sisusb_last_vc <= MAX_NR_CONSOLES)
3180 initscreen = 0;
3181#endif
3182 if (sisusb_init_gfxdevice(sisusb, initscreen))
3183 dev_err(&sisusb->sisusb_dev->dev, "Failed to early initialize device\n");
3184
3185 } else
3186 dev_info(&sisusb->sisusb_dev->dev, "Not attached to USB 2.0 hub, deferring init\n");
3187
3188 sisusb->ready = 1;
3189
3190#ifdef SISUSBENDIANTEST
3191 dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST ***\n");
3192 sisusb_testreadwrite(sisusb);
3193 dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST END ***\n");
3194#endif
3195
3196#ifdef INCL_SISUSB_CON
3197 sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
3198#endif
3199
3200 return 0;
3201
3202error_4:
3203 sisusb_free_urbs(sisusb);
3204error_3:
3205 sisusb_free_buffers(sisusb);
3206error_2:
3207 usb_deregister_dev(intf, &usb_sisusb_class);
3208error_1:
3209 kfree(sisusb);
3210 return retval;
3211}
3212
3213static void sisusb_disconnect(struct usb_interface *intf)
3214{
3215 struct sisusb_usb_data *sisusb;
3216
3217 /* This should *not* happen */
3218 if (!(sisusb = usb_get_intfdata(intf)))
3219 return;
3220
3221#ifdef INCL_SISUSB_CON
3222 sisusb_console_exit(sisusb);
3223#endif
3224
3225 usb_deregister_dev(intf, &usb_sisusb_class);
3226
3227 mutex_lock(&sisusb->lock);
3228
3229 /* Wait for all URBs to complete and kill them in case (MUST do) */
3230 if (!sisusb_wait_all_out_complete(sisusb))
3231 sisusb_kill_all_busy(sisusb);
3232
3233 usb_set_intfdata(intf, NULL);
3234
3235 sisusb->present = 0;
3236 sisusb->ready = 0;
3237
3238 mutex_unlock(&sisusb->lock);
3239
3240 /* decrement our usage count */
3241 kref_put(&sisusb->kref, sisusb_delete);
3242}
3243
3244static const struct usb_device_id sisusb_table[] = {
3245 { USB_DEVICE(0x0711, 0x0550) },
3246 { USB_DEVICE(0x0711, 0x0900) },
3247 { USB_DEVICE(0x0711, 0x0901) },
3248 { USB_DEVICE(0x0711, 0x0902) },
3249 { USB_DEVICE(0x0711, 0x0903) },
3250 { USB_DEVICE(0x0711, 0x0918) },
3251 { USB_DEVICE(0x0711, 0x0920) },
3252 { USB_DEVICE(0x0711, 0x0950) },
3253 { USB_DEVICE(0x182d, 0x021c) },
3254 { USB_DEVICE(0x182d, 0x0269) },
3255 { }
3256};
3257
3258MODULE_DEVICE_TABLE (usb, sisusb_table);
3259
3260static struct usb_driver sisusb_driver = {
3261 .name = "sisusb",
3262 .probe = sisusb_probe,
3263 .disconnect = sisusb_disconnect,
3264 .id_table = sisusb_table,
3265};
3266
3267static int __init usb_sisusb_init(void)
3268{
3269
3270#ifdef INCL_SISUSB_CON
3271 sisusb_init_concode();
3272#endif
3273
3274 return usb_register(&sisusb_driver);
3275}
3276
3277static void __exit usb_sisusb_exit(void)
3278{
3279 usb_deregister(&sisusb_driver);
3280}
3281
3282module_init(usb_sisusb_init);
3283module_exit(usb_sisusb_exit);
3284
3285MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3286MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3287MODULE_LICENSE("GPL");
3288