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