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