]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/usb/misc/sisusbvga/sisusb.c
Merge remote-tracking branch 'usb-chipidea-next/ci-for-usb-next'
[karo-tx-linux.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         char buf[4];
766
767         /* if neither kernbuffer not userbuffer are given, assume
768          * data in obuf
769          */
770         if (!fromkern && !userbuffer)
771                 kernbuffer = sisusb->obuf[index];
772
773         (*bytes_written = 0);
774
775         length &= 0x00ffffff;
776
777         while (length) {
778                 switch (length) {
779                 case 1:
780                         if (userbuffer) {
781                                 if (get_user(swap8, (u8 __user *)userbuffer))
782                                         return -EFAULT;
783                         } else
784                                 swap8 = kernbuffer[0];
785
786                         ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM,
787                                         addr, swap8);
788
789                         if (!ret)
790                                 (*bytes_written)++;
791
792                         return ret;
793
794                 case 2:
795                         if (userbuffer) {
796                                 if (get_user(swap16, (u16 __user *)userbuffer))
797                                         return -EFAULT;
798                         } else
799                                 swap16 = *((u16 *)kernbuffer);
800
801                         ret = sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
802                                         addr, swap16);
803
804                         if (!ret)
805                                 (*bytes_written) += 2;
806
807                         return ret;
808
809                 case 3:
810                         if (userbuffer) {
811                                 if (copy_from_user(&buf, userbuffer, 3))
812                                         return -EFAULT;
813 #ifdef __BIG_ENDIAN
814                                 swap32 = (buf[0] << 16) |
815                                          (buf[1] <<  8) |
816                                          buf[2];
817 #else
818                                 swap32 = (buf[2] << 16) |
819                                          (buf[1] <<  8) |
820                                          buf[0];
821 #endif
822                         } else
823 #ifdef __BIG_ENDIAN
824                                 swap32 = (kernbuffer[0] << 16) |
825                                          (kernbuffer[1] <<  8) |
826                                          kernbuffer[2];
827 #else
828                                 swap32 = (kernbuffer[2] << 16) |
829                                          (kernbuffer[1] <<  8) |
830                                          kernbuffer[0];
831 #endif
832
833                         ret = sisusb_write_memio_24bit(sisusb, SISUSB_TYPE_MEM,
834                                         addr, swap32);
835
836                         if (!ret)
837                                 (*bytes_written) += 3;
838
839                         return ret;
840
841                 case 4:
842                         if (userbuffer) {
843                                 if (get_user(swap32, (u32 __user *)userbuffer))
844                                         return -EFAULT;
845                         } else
846                                 swap32 = *((u32 *)kernbuffer);
847
848                         ret = sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM,
849                                         addr, swap32);
850                         if (!ret)
851                                 (*bytes_written) += 4;
852
853                         return ret;
854
855                 default:
856                         if ((length & ~3) > 0x10000) {
857
858                                 packet.header  = 0x001f;
859                                 packet.address = 0x000001d4;
860                                 packet.data    = addr;
861                                 ret = sisusb_send_bridge_packet(sisusb, 10,
862                                                 &packet, 0);
863                                 packet.header  = 0x001f;
864                                 packet.address = 0x000001d0;
865                                 packet.data    = (length & ~3);
866                                 ret |= sisusb_send_bridge_packet(sisusb, 10,
867                                                 &packet, 0);
868                                 packet.header  = 0x001f;
869                                 packet.address = 0x000001c0;
870                                 packet.data    = flag | 0x16;
871                                 ret |= sisusb_send_bridge_packet(sisusb, 10,
872                                                 &packet, 0);
873                                 if (userbuffer) {
874                                         ret |= sisusb_send_bulk_msg(sisusb,
875                                                         SISUSB_EP_GFX_LBULK_OUT,
876                                                         (length & ~3),
877                                                         NULL, userbuffer, 0,
878                                                         bytes_written, 0, 1);
879                                         userbuffer += (*bytes_written);
880                                 } else if (fromkern) {
881                                         ret |= sisusb_send_bulk_msg(sisusb,
882                                                         SISUSB_EP_GFX_LBULK_OUT,
883                                                         (length & ~3),
884                                                         kernbuffer, NULL, 0,
885                                                         bytes_written, 0, 1);
886                                         kernbuffer += (*bytes_written);
887                                 } else {
888                                         ret |= sisusb_send_bulk_msg(sisusb,
889                                                         SISUSB_EP_GFX_LBULK_OUT,
890                                                         (length & ~3),
891                                                         NULL, NULL, index,
892                                                         bytes_written, 0, 1);
893                                         kernbuffer += ((*bytes_written) &
894                                                         (sisusb->obufsize-1));
895                                 }
896
897                         } else {
898
899                                 packet.header  = 0x001f;
900                                 packet.address = 0x00000194;
901                                 packet.data    = addr;
902                                 ret = sisusb_send_bridge_packet(sisusb, 10,
903                                                 &packet, 0);
904                                 packet.header  = 0x001f;
905                                 packet.address = 0x00000190;
906                                 packet.data    = (length & ~3);
907                                 ret |= sisusb_send_bridge_packet(sisusb, 10,
908                                                 &packet, 0);
909                                 if (sisusb->flagb0 != 0x16) {
910                                         packet.header  = 0x001f;
911                                         packet.address = 0x00000180;
912                                         packet.data    = flag | 0x16;
913                                         ret |= sisusb_send_bridge_packet(sisusb,
914                                                         10, &packet, 0);
915                                         sisusb->flagb0 = 0x16;
916                                 }
917                                 if (userbuffer) {
918                                         ret |= sisusb_send_bulk_msg(sisusb,
919                                                         SISUSB_EP_GFX_BULK_OUT,
920                                                         (length & ~3),
921                                                         NULL, userbuffer, 0,
922                                                         bytes_written, 0, 1);
923                                         userbuffer += (*bytes_written);
924                                 } else if (fromkern) {
925                                         ret |= sisusb_send_bulk_msg(sisusb,
926                                                         SISUSB_EP_GFX_BULK_OUT,
927                                                         (length & ~3),
928                                                         kernbuffer, NULL, 0,
929                                                         bytes_written, 0, 1);
930                                         kernbuffer += (*bytes_written);
931                                 } else {
932                                         ret |= sisusb_send_bulk_msg(sisusb,
933                                                         SISUSB_EP_GFX_BULK_OUT,
934                                                         (length & ~3),
935                                                         NULL, NULL, index,
936                                                         bytes_written, 0, 1);
937                                         kernbuffer += ((*bytes_written) &
938                                                         (sisusb->obufsize-1));
939                                 }
940                         }
941                         if (ret) {
942                                 msgcount++;
943                                 if (msgcount < 500)
944                                         dev_err(&sisusb->sisusb_dev->dev,
945                                                         "Wrote %zd of %d bytes, error %d\n",
946                                                         *bytes_written, length,
947                                                         ret);
948                                 else if (msgcount == 500)
949                                         dev_err(&sisusb->sisusb_dev->dev,
950                                                         "Too many errors, logging stopped\n");
951                         }
952                         addr += (*bytes_written);
953                         length -= (*bytes_written);
954                 }
955
956                 if (ret)
957                         break;
958
959         }
960
961         return ret ? -EIO : 0;
962 }
963
964 /* Remember: Read data in packet is in machine-endianess! So for
965  * byte, word, 24bit, long no endian correction is necessary.
966  */
967
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, int 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, int 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, int port,
1215                 u8 index, u8 data)
1216 {
1217         int ret;
1218
1219         ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1220         ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1221         return ret;
1222 }
1223
1224 int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port,
1225                 u8 index, u8 *data)
1226 {
1227         int ret;
1228
1229         ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1230         ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1231         return ret;
1232 }
1233
1234 int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
1235                 u8 myand, u8 myor)
1236 {
1237         int ret;
1238         u8 tmp;
1239
1240         ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1241         ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1242         tmp &= myand;
1243         tmp |= myor;
1244         ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1245         return ret;
1246 }
1247
1248 static int sisusb_setidxregmask(struct sisusb_usb_data *sisusb,
1249                 int port, u8 idx, u8 data, u8 mask)
1250 {
1251         int ret;
1252         u8 tmp;
1253
1254         ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1255         ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1256         tmp &= ~(mask);
1257         tmp |= (data & mask);
1258         ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1259         return ret;
1260 }
1261
1262 int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port,
1263                 u8 index, u8 myor)
1264 {
1265         return sisusb_setidxregandor(sisusb, port, index, 0xff, myor);
1266 }
1267
1268 int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port,
1269                 u8 idx, u8 myand)
1270 {
1271         return sisusb_setidxregandor(sisusb, port, idx, myand, 0x00);
1272 }
1273
1274 /* Write/read video ram */
1275
1276 #ifdef INCL_SISUSB_CON
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, size_t *bytes_written)
1289 {
1290         return sisusb_write_mem_bulk(sisusb, dest, src, length,
1291                         NULL, 0, bytes_written);
1292 }
1293
1294 #ifdef SISUSBENDIANTEST
1295 int sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
1296                 u32 src, int length, size_t *bytes_written)
1297 {
1298         return sisusb_read_mem_bulk(sisusb, src, dest, length,
1299                         NULL, bytes_written);
1300 }
1301 #endif
1302 #endif
1303
1304 #ifdef SISUSBENDIANTEST
1305 static void sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
1306 {
1307         static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1308         char destbuffer[10];
1309         size_t dummy;
1310         int i, j;
1311
1312         sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy);
1313
1314         for (i = 1; i <= 7; i++) {
1315                 dev_dbg(&sisusb->sisusb_dev->dev,
1316                                 "sisusb: rwtest %d bytes\n", i);
1317                 sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase,
1318                                 i, &dummy);
1319                 for (j = 0; j < i; j++) {
1320                         dev_dbg(&sisusb->sisusb_dev->dev,
1321                                         "rwtest read[%d] = %x\n",
1322                                         j, destbuffer[j]);
1323                 }
1324         }
1325 }
1326 #endif
1327
1328 /* access pci config registers (reg numbers 0, 4, 8, etc) */
1329
1330 static int sisusb_write_pci_config(struct sisusb_usb_data *sisusb,
1331                 int regnum, u32 data)
1332 {
1333         struct sisusb_packet packet;
1334         int ret;
1335
1336         packet.header = 0x008f;
1337         packet.address = regnum | 0x10000;
1338         packet.data = data;
1339         ret = sisusb_send_packet(sisusb, 10, &packet);
1340         return ret;
1341 }
1342
1343 static int sisusb_read_pci_config(struct sisusb_usb_data *sisusb,
1344                 int regnum, u32 *data)
1345 {
1346         struct sisusb_packet packet;
1347         int ret;
1348
1349         packet.header = 0x008f;
1350         packet.address = (u32)regnum | 0x10000;
1351         ret = sisusb_send_packet(sisusb, 6, &packet);
1352         *data = packet.data;
1353         return ret;
1354 }
1355
1356 /* Clear video RAM */
1357
1358 static int sisusb_clear_vram(struct sisusb_usb_data *sisusb,
1359                 u32 address, int length)
1360 {
1361         int ret, i;
1362         ssize_t j;
1363
1364         if (address < sisusb->vrambase)
1365                 return 1;
1366
1367         if (address >= sisusb->vrambase + sisusb->vramsize)
1368                 return 1;
1369
1370         if (address + length > sisusb->vrambase + sisusb->vramsize)
1371                 length = sisusb->vrambase + sisusb->vramsize - address;
1372
1373         if (length <= 0)
1374                 return 0;
1375
1376         /* allocate free buffer/urb and clear the buffer */
1377         i = sisusb_alloc_outbuf(sisusb);
1378         if (i < 0)
1379                 return -EBUSY;
1380
1381         memset(sisusb->obuf[i], 0, sisusb->obufsize);
1382
1383         /* We can write a length > buffer size here. The buffer
1384          * data will simply be re-used (like a ring-buffer).
1385          */
1386         ret = sisusb_write_mem_bulk(sisusb, address, NULL, length, NULL, i, &j);
1387
1388         /* Free the buffer/urb */
1389         sisusb_free_outbuf(sisusb, i);
1390
1391         return ret;
1392 }
1393
1394 /* Initialize the graphics core (return 0 on success)
1395  * This resets the graphics hardware and puts it into
1396  * a defined mode (640x480@60Hz)
1397  */
1398
1399 #define GETREG(r, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1400 #define SETREG(r, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1401 #define SETIREG(r, i, d) sisusb_setidxreg(sisusb, r, i, d)
1402 #define GETIREG(r, i, d) sisusb_getidxreg(sisusb, r, i, d)
1403 #define SETIREGOR(r, i, o) sisusb_setidxregor(sisusb, r, i, o)
1404 #define SETIREGAND(r, i, a) sisusb_setidxregand(sisusb, r, i, a)
1405 #define SETIREGANDOR(r, i, a, o) sisusb_setidxregandor(sisusb, r, i, a, o)
1406 #define READL(a, d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1407 #define WRITEL(a, d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1408 #define READB(a, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1409 #define WRITEB(a, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1410
1411 static int sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype)
1412 {
1413         int ret;
1414         u8 tmp8;
1415
1416         ret = GETIREG(SISSR, 0x16, &tmp8);
1417         if (ramtype <= 1) {
1418                 tmp8 &= 0x3f;
1419                 ret |= SETIREG(SISSR, 0x16, tmp8);
1420                 tmp8 |= 0x80;
1421                 ret |= SETIREG(SISSR, 0x16, tmp8);
1422         } else {
1423                 tmp8 |= 0xc0;
1424                 ret |= SETIREG(SISSR, 0x16, tmp8);
1425                 tmp8 &= 0x0f;
1426                 ret |= SETIREG(SISSR, 0x16, tmp8);
1427                 tmp8 |= 0x80;
1428                 ret |= SETIREG(SISSR, 0x16, tmp8);
1429                 tmp8 &= 0x0f;
1430                 ret |= SETIREG(SISSR, 0x16, tmp8);
1431                 tmp8 |= 0xd0;
1432                 ret |= SETIREG(SISSR, 0x16, tmp8);
1433                 tmp8 &= 0x0f;
1434                 ret |= SETIREG(SISSR, 0x16, tmp8);
1435                 tmp8 |= 0xa0;
1436                 ret |= SETIREG(SISSR, 0x16, tmp8);
1437         }
1438         return ret;
1439 }
1440
1441 static int sisusb_getbuswidth(struct sisusb_usb_data *sisusb,
1442                 int *bw, int *chab)
1443 {
1444         int ret;
1445         u8  ramtype, done = 0;
1446         u32 t0, t1, t2, t3;
1447         u32 ramptr = SISUSB_PCI_MEMBASE;
1448
1449         ret = GETIREG(SISSR, 0x3a, &ramtype);
1450         ramtype &= 3;
1451
1452         ret |= SETIREG(SISSR, 0x13, 0x00);
1453
1454         if (ramtype <= 1) {
1455                 ret |= SETIREG(SISSR, 0x14, 0x12);
1456                 ret |= SETIREGAND(SISSR, 0x15, 0xef);
1457         } else {
1458                 ret |= SETIREG(SISSR, 0x14, 0x02);
1459         }
1460
1461         ret |= sisusb_triggersr16(sisusb, ramtype);
1462         ret |= WRITEL(ramptr +  0, 0x01234567);
1463         ret |= WRITEL(ramptr +  4, 0x456789ab);
1464         ret |= WRITEL(ramptr +  8, 0x89abcdef);
1465         ret |= WRITEL(ramptr + 12, 0xcdef0123);
1466         ret |= WRITEL(ramptr + 16, 0x55555555);
1467         ret |= WRITEL(ramptr + 20, 0x55555555);
1468         ret |= WRITEL(ramptr + 24, 0xffffffff);
1469         ret |= WRITEL(ramptr + 28, 0xffffffff);
1470         ret |= READL(ramptr +  0, &t0);
1471         ret |= READL(ramptr +  4, &t1);
1472         ret |= READL(ramptr +  8, &t2);
1473         ret |= READL(ramptr + 12, &t3);
1474
1475         if (ramtype <= 1) {
1476
1477                 *chab = 0; *bw = 64;
1478
1479                 if ((t3 != 0xcdef0123) || (t2 != 0x89abcdef)) {
1480                         if ((t1 == 0x456789ab) && (t0 == 0x01234567)) {
1481                                 *chab = 0; *bw = 64;
1482                                 ret |= SETIREGAND(SISSR, 0x14, 0xfd);
1483                         }
1484                 }
1485                 if ((t1 != 0x456789ab) || (t0 != 0x01234567)) {
1486                         *chab = 1; *bw = 64;
1487                         ret |= SETIREGANDOR(SISSR, 0x14, 0xfc, 0x01);
1488
1489                         ret |= sisusb_triggersr16(sisusb, ramtype);
1490                         ret |= WRITEL(ramptr +  0, 0x89abcdef);
1491                         ret |= WRITEL(ramptr +  4, 0xcdef0123);
1492                         ret |= WRITEL(ramptr +  8, 0x55555555);
1493                         ret |= WRITEL(ramptr + 12, 0x55555555);
1494                         ret |= WRITEL(ramptr + 16, 0xaaaaaaaa);
1495                         ret |= WRITEL(ramptr + 20, 0xaaaaaaaa);
1496                         ret |= READL(ramptr +  4, &t1);
1497
1498                         if (t1 != 0xcdef0123) {
1499                                 *bw = 32;
1500                                 ret |= SETIREGOR(SISSR, 0x15, 0x10);
1501                         }
1502                 }
1503
1504         } else {
1505
1506                 *chab = 0; *bw = 64;    /* default: cha, bw = 64 */
1507
1508                 done = 0;
1509
1510                 if (t1 == 0x456789ab) {
1511                         if (t0 == 0x01234567) {
1512                                 *chab = 0; *bw = 64;
1513                                 done = 1;
1514                         }
1515                 } else {
1516                         if (t0 == 0x01234567) {
1517                                 *chab = 0; *bw = 32;
1518                                 ret |= SETIREG(SISSR, 0x14, 0x00);
1519                                 done = 1;
1520                         }
1521                 }
1522
1523                 if (!done) {
1524                         ret |= SETIREG(SISSR, 0x14, 0x03);
1525                         ret |= sisusb_triggersr16(sisusb, ramtype);
1526
1527                         ret |= WRITEL(ramptr +  0, 0x01234567);
1528                         ret |= WRITEL(ramptr +  4, 0x456789ab);
1529                         ret |= WRITEL(ramptr +  8, 0x89abcdef);
1530                         ret |= WRITEL(ramptr + 12, 0xcdef0123);
1531                         ret |= WRITEL(ramptr + 16, 0x55555555);
1532                         ret |= WRITEL(ramptr + 20, 0x55555555);
1533                         ret |= WRITEL(ramptr + 24, 0xffffffff);
1534                         ret |= WRITEL(ramptr + 28, 0xffffffff);
1535                         ret |= READL(ramptr +  0, &t0);
1536                         ret |= READL(ramptr +  4, &t1);
1537
1538                         if (t1 == 0x456789ab) {
1539                                 if (t0 == 0x01234567) {
1540                                         *chab = 1; *bw = 64;
1541                                         return ret;
1542                                 } /* else error */
1543                         } else {
1544                                 if (t0 == 0x01234567) {
1545                                         *chab = 1; *bw = 32;
1546                                         ret |= SETIREG(SISSR, 0x14, 0x01);
1547                                 } /* else error */
1548                         }
1549                 }
1550         }
1551         return ret;
1552 }
1553
1554 static int sisusb_verify_mclk(struct sisusb_usb_data *sisusb)
1555 {
1556         int ret = 0;
1557         u32 ramptr = SISUSB_PCI_MEMBASE;
1558         u8 tmp1, tmp2, i, j;
1559
1560         ret |= WRITEB(ramptr, 0xaa);
1561         ret |= WRITEB(ramptr + 16, 0x55);
1562         ret |= READB(ramptr, &tmp1);
1563         ret |= READB(ramptr + 16, &tmp2);
1564         if ((tmp1 != 0xaa) || (tmp2 != 0x55)) {
1565                 for (i = 0, j = 16; i < 2; i++, j += 16) {
1566                         ret |= GETIREG(SISSR, 0x21, &tmp1);
1567                         ret |= SETIREGAND(SISSR, 0x21, (tmp1 & 0xfb));
1568                         ret |= SETIREGOR(SISSR, 0x3c, 0x01);  /* not on 330 */
1569                         ret |= SETIREGAND(SISSR, 0x3c, 0xfe); /* not on 330 */
1570                         ret |= SETIREG(SISSR, 0x21, tmp1);
1571                         ret |= WRITEB(ramptr + 16 + j, j);
1572                         ret |= READB(ramptr + 16 + j, &tmp1);
1573                         if (tmp1 == j) {
1574                                 ret |= WRITEB(ramptr + j, j);
1575                                 break;
1576                         }
1577                 }
1578         }
1579         return ret;
1580 }
1581
1582 static int sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret,
1583                 int index, u8 rankno, u8 chab, const u8 dramtype[][5], int bw)
1584 {
1585         int ret = 0, ranksize;
1586         u8 tmp;
1587
1588         *iret = 0;
1589
1590         if ((rankno == 2) && (dramtype[index][0] == 2))
1591                 return ret;
1592
1593         ranksize = dramtype[index][3] / 2 * bw / 32;
1594
1595         if ((ranksize * rankno) > 128)
1596                 return ret;
1597
1598         tmp = 0;
1599         while ((ranksize >>= 1) > 0)
1600                 tmp += 0x10;
1601
1602         tmp |= ((rankno - 1) << 2);
1603         tmp |= ((bw / 64) & 0x02);
1604         tmp |= (chab & 0x01);
1605
1606         ret = SETIREG(SISSR, 0x14, tmp);
1607         ret |= sisusb_triggersr16(sisusb, 0); /* sic! */
1608
1609         *iret = 1;
1610
1611         return ret;
1612 }
1613
1614 static int sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret,
1615                 u32 inc, int testn)
1616 {
1617         int ret = 0, i;
1618         u32 j, tmp;
1619
1620         *iret = 0;
1621
1622         for (i = 0, j = 0; i < testn; i++) {
1623                 ret |= WRITEL(sisusb->vrambase + j, j);
1624                 j += inc;
1625         }
1626
1627         for (i = 0, j = 0; i < testn; i++) {
1628                 ret |= READL(sisusb->vrambase + j, &tmp);
1629                 if (tmp != j)
1630                         return ret;
1631
1632                 j += inc;
1633         }
1634
1635         *iret = 1;
1636         return ret;
1637 }
1638
1639 static int sisusb_check_ranks(struct sisusb_usb_data *sisusb,
1640                 int *iret, int rankno, int idx, int bw, const u8 rtype[][5])
1641 {
1642         int ret = 0, i, i2ret;
1643         u32 inc;
1644
1645         *iret = 0;
1646
1647         for (i = rankno; i >= 1; i--) {
1648                 inc = 1 << (rtype[idx][2] + rtype[idx][1] + rtype[idx][0] +
1649                                 bw / 64 + i);
1650                 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1651                 if (!i2ret)
1652                         return ret;
1653         }
1654
1655         inc = 1 << (rtype[idx][2] + bw / 64 + 2);
1656         ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 4);
1657         if (!i2ret)
1658                 return ret;
1659
1660         inc = 1 << (10 + bw / 64);
1661         ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1662         if (!i2ret)
1663                 return ret;
1664
1665         *iret = 1;
1666         return ret;
1667 }
1668
1669 static int sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret,
1670                 int bw, int chab)
1671 {
1672         int ret = 0, i2ret = 0, i, j;
1673         static const u8 sdramtype[13][5] = {
1674                 { 2, 12, 9, 64, 0x35 },
1675                 { 1, 13, 9, 64, 0x44 },
1676                 { 2, 12, 8, 32, 0x31 },
1677                 { 2, 11, 9, 32, 0x25 },
1678                 { 1, 12, 9, 32, 0x34 },
1679                 { 1, 13, 8, 32, 0x40 },
1680                 { 2, 11, 8, 16, 0x21 },
1681                 { 1, 12, 8, 16, 0x30 },
1682                 { 1, 11, 9, 16, 0x24 },
1683                 { 1, 11, 8,  8, 0x20 },
1684                 { 2,  9, 8,  4, 0x01 },
1685                 { 1, 10, 8,  4, 0x10 },
1686                 { 1,  9, 8,  2, 0x00 }
1687         };
1688
1689         *iret = 1; /* error */
1690
1691         for (i = 0; i < 13; i++) {
1692                 ret |= SETIREGANDOR(SISSR, 0x13, 0x80, sdramtype[i][4]);
1693                 for (j = 2; j > 0; j--) {
1694                         ret |= sisusb_set_rank(sisusb, &i2ret, i, j, chab,
1695                                         sdramtype, bw);
1696                         if (!i2ret)
1697                                 continue;
1698
1699                         ret |= sisusb_check_ranks(sisusb, &i2ret, j, i, bw,
1700                                         sdramtype);
1701                         if (i2ret) {
1702                                 *iret = 0;      /* ram size found */
1703                                 return ret;
1704                         }
1705                 }
1706         }
1707
1708         return ret;
1709 }
1710
1711 static int sisusb_setup_screen(struct sisusb_usb_data *sisusb,
1712                 int clrall, int drwfr)
1713 {
1714         int ret = 0;
1715         u32 address;
1716         int i, length, modex, modey, bpp;
1717
1718         modex = 640; modey = 480; bpp = 2;
1719
1720         address = sisusb->vrambase;     /* Clear video ram */
1721
1722         if (clrall)
1723                 length = sisusb->vramsize;
1724         else
1725                 length = modex * bpp * modey;
1726
1727         ret = sisusb_clear_vram(sisusb, address, length);
1728
1729         if (!ret && drwfr) {
1730                 for (i = 0; i < modex; i++) {
1731                         address = sisusb->vrambase + (i * bpp);
1732                         ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1733                                         address, 0xf100);
1734                         address += (modex * (modey-1) * bpp);
1735                         ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1736                                         address, 0xf100);
1737                 }
1738                 for (i = 0; i < modey; i++) {
1739                         address = sisusb->vrambase + ((i * modex) * bpp);
1740                         ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1741                                         address, 0xf100);
1742                         address += ((modex - 1) * bpp);
1743                         ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1744                                         address, 0xf100);
1745                 }
1746         }
1747
1748         return ret;
1749 }
1750
1751 static int sisusb_set_default_mode(struct sisusb_usb_data *sisusb,
1752                 int touchengines)
1753 {
1754         int ret = 0, i, j, modex, modey, bpp, du;
1755         u8 sr31, cr63, tmp8;
1756         static const char attrdata[] = {
1757                 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1758                 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1759                 0x01, 0x00, 0x00, 0x00
1760         };
1761         static const char crtcrdata[] = {
1762                 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
1763                 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1764                 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3,
1765                 0xff
1766         };
1767         static const char grcdata[] = {
1768                 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
1769                 0xff
1770         };
1771         static const char crtcdata[] = {
1772                 0x5f, 0x4f, 0x4f, 0x83, 0x55, 0x81, 0x0b, 0x3e,
1773                 0xe9, 0x8b, 0xdf, 0xe8, 0x0c, 0x00, 0x00, 0x05,
1774                 0x00
1775         };
1776
1777         modex = 640; modey = 480; bpp = 2;
1778
1779         GETIREG(SISSR, 0x31, &sr31);
1780         GETIREG(SISCR, 0x63, &cr63);
1781         SETIREGOR(SISSR, 0x01, 0x20);
1782         SETIREG(SISCR, 0x63, cr63 & 0xbf);
1783         SETIREGOR(SISCR, 0x17, 0x80);
1784         SETIREGOR(SISSR, 0x1f, 0x04);
1785         SETIREGAND(SISSR, 0x07, 0xfb);
1786         SETIREG(SISSR, 0x00, 0x03);     /* seq */
1787         SETIREG(SISSR, 0x01, 0x21);
1788         SETIREG(SISSR, 0x02, 0x0f);
1789         SETIREG(SISSR, 0x03, 0x00);
1790         SETIREG(SISSR, 0x04, 0x0e);
1791         SETREG(SISMISCW, 0x23);         /* misc */
1792         for (i = 0; i <= 0x18; i++) {   /* crtc */
1793                 SETIREG(SISCR, i, crtcrdata[i]);
1794         }
1795         for (i = 0; i <= 0x13; i++) {   /* att */
1796                 GETREG(SISINPSTAT, &tmp8);
1797                 SETREG(SISAR, i);
1798                 SETREG(SISAR, attrdata[i]);
1799         }
1800         GETREG(SISINPSTAT, &tmp8);
1801         SETREG(SISAR, 0x14);
1802         SETREG(SISAR, 0x00);
1803         GETREG(SISINPSTAT, &tmp8);
1804         SETREG(SISAR, 0x20);
1805         GETREG(SISINPSTAT, &tmp8);
1806         for (i = 0; i <= 0x08; i++) {   /* grc */
1807                 SETIREG(SISGR, i, grcdata[i]);
1808         }
1809         SETIREGAND(SISGR, 0x05, 0xbf);
1810         for (i = 0x0A; i <= 0x0E; i++) {        /* clr ext */
1811                 SETIREG(SISSR, i, 0x00);
1812         }
1813         SETIREGAND(SISSR, 0x37, 0xfe);
1814         SETREG(SISMISCW, 0xef);         /* sync */
1815         SETIREG(SISCR, 0x11, 0x00);     /* crtc */
1816         for (j = 0x00, i = 0; i <= 7; i++, j++)
1817                 SETIREG(SISCR, j, crtcdata[i]);
1818
1819         for (j = 0x10; i <= 10; i++, j++)
1820                 SETIREG(SISCR, j, crtcdata[i]);
1821
1822         for (j = 0x15; i <= 12; i++, j++)
1823                 SETIREG(SISCR, j, crtcdata[i]);
1824
1825         for (j = 0x0A; i <= 15; i++, j++)
1826                 SETIREG(SISSR, j, crtcdata[i]);
1827
1828         SETIREG(SISSR, 0x0E, (crtcdata[16] & 0xE0));
1829         SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5));
1830         SETIREG(SISCR, 0x14, 0x4f);
1831         du = (modex / 16) * (bpp * 2);  /* offset/pitch */
1832         if (modex % 16)
1833                 du += bpp;
1834
1835         SETIREGANDOR(SISSR, 0x0e, 0xf0, ((du >> 8) & 0x0f));
1836         SETIREG(SISCR, 0x13, (du & 0xff));
1837         du <<= 5;
1838         tmp8 = du >> 8;
1839         if (du & 0xff)
1840                 tmp8++;
1841
1842         SETIREG(SISSR, 0x10, tmp8);
1843         SETIREG(SISSR, 0x31, 0x00);     /* VCLK */
1844         SETIREG(SISSR, 0x2b, 0x1b);
1845         SETIREG(SISSR, 0x2c, 0xe1);
1846         SETIREG(SISSR, 0x2d, 0x01);
1847         SETIREGAND(SISSR, 0x3d, 0xfe);  /* FIFO */
1848         SETIREG(SISSR, 0x08, 0xae);
1849         SETIREGAND(SISSR, 0x09, 0xf0);
1850         SETIREG(SISSR, 0x08, 0x34);
1851         SETIREGOR(SISSR, 0x3d, 0x01);
1852         SETIREGAND(SISSR, 0x1f, 0x3f);  /* mode regs */
1853         SETIREGANDOR(SISSR, 0x06, 0xc0, 0x0a);
1854         SETIREG(SISCR, 0x19, 0x00);
1855         SETIREGAND(SISCR, 0x1a, 0xfc);
1856         SETIREGAND(SISSR, 0x0f, 0xb7);
1857         SETIREGAND(SISSR, 0x31, 0xfb);
1858         SETIREGANDOR(SISSR, 0x21, 0x1f, 0xa0);
1859         SETIREGAND(SISSR, 0x32, 0xf3);
1860         SETIREGANDOR(SISSR, 0x07, 0xf8, 0x03);
1861         SETIREG(SISCR, 0x52, 0x6c);
1862
1863         SETIREG(SISCR, 0x0d, 0x00);     /* adjust frame */
1864         SETIREG(SISCR, 0x0c, 0x00);
1865         SETIREG(SISSR, 0x0d, 0x00);
1866         SETIREGAND(SISSR, 0x37, 0xfe);
1867
1868         SETIREG(SISCR, 0x32, 0x20);
1869         SETIREGAND(SISSR, 0x01, 0xdf);  /* enable display */
1870         SETIREG(SISCR, 0x63, (cr63 & 0xbf));
1871         SETIREG(SISSR, 0x31, (sr31 & 0xfb));
1872
1873         if (touchengines) {
1874                 SETIREG(SISSR, 0x20, 0xa1);     /* enable engines */
1875                 SETIREGOR(SISSR, 0x1e, 0x5a);
1876
1877                 SETIREG(SISSR, 0x26, 0x01);     /* disable cmdqueue */
1878                 SETIREG(SISSR, 0x27, 0x1f);
1879                 SETIREG(SISSR, 0x26, 0x00);
1880         }
1881
1882         SETIREG(SISCR, 0x34, 0x44);     /* we just set std mode #44 */
1883
1884         return ret;
1885 }
1886
1887 static int sisusb_init_gfxcore(struct sisusb_usb_data *sisusb)
1888 {
1889         int ret = 0, i, j, bw, chab, iret, retry = 3;
1890         u8 tmp8, ramtype;
1891         u32 tmp32;
1892         static const char mclktable[] = {
1893                 0x3b, 0x22, 0x01, 143,
1894                 0x3b, 0x22, 0x01, 143,
1895                 0x3b, 0x22, 0x01, 143,
1896                 0x3b, 0x22, 0x01, 143
1897         };
1898         static const char eclktable[] = {
1899                 0x3b, 0x22, 0x01, 143,
1900                 0x3b, 0x22, 0x01, 143,
1901                 0x3b, 0x22, 0x01, 143,
1902                 0x3b, 0x22, 0x01, 143
1903         };
1904         static const char ramtypetable1[] = {
1905                 0x00, 0x04, 0x60, 0x60,
1906                 0x0f, 0x0f, 0x1f, 0x1f,
1907                 0xba, 0xba, 0xba, 0xba,
1908                 0xa9, 0xa9, 0xac, 0xac,
1909                 0xa0, 0xa0, 0xa0, 0xa8,
1910                 0x00, 0x00, 0x02, 0x02,
1911                 0x30, 0x30, 0x40, 0x40
1912         };
1913         static const char ramtypetable2[] = {
1914                 0x77, 0x77, 0x44, 0x44,
1915                 0x77, 0x77, 0x44, 0x44,
1916                 0x00, 0x00, 0x00, 0x00,
1917                 0x5b, 0x5b, 0xab, 0xab,
1918                 0x00, 0x00, 0xf0, 0xf8
1919         };
1920
1921         while (retry--) {
1922
1923                 /* Enable VGA */
1924                 ret = GETREG(SISVGAEN, &tmp8);
1925                 ret |= SETREG(SISVGAEN, (tmp8 | 0x01));
1926
1927                 /* Enable GPU access to VRAM */
1928                 ret |= GETREG(SISMISCR, &tmp8);
1929                 ret |= SETREG(SISMISCW, (tmp8 | 0x01));
1930
1931                 if (ret)
1932                         continue;
1933
1934                 /* Reset registers */
1935                 ret |= SETIREGAND(SISCR, 0x5b, 0xdf);
1936                 ret |= SETIREG(SISSR, 0x05, 0x86);
1937                 ret |= SETIREGOR(SISSR, 0x20, 0x01);
1938
1939                 ret |= SETREG(SISMISCW, 0x67);
1940
1941                 for (i = 0x06; i <= 0x1f; i++)
1942                         ret |= SETIREG(SISSR, i, 0x00);
1943
1944                 for (i = 0x21; i <= 0x27; i++)
1945                         ret |= SETIREG(SISSR, i, 0x00);
1946
1947                 for (i = 0x31; i <= 0x3d; i++)
1948                         ret |= SETIREG(SISSR, i, 0x00);
1949
1950                 for (i = 0x12; i <= 0x1b; i++)
1951                         ret |= SETIREG(SISSR, i, 0x00);
1952
1953                 for (i = 0x79; i <= 0x7c; i++)
1954                         ret |= SETIREG(SISCR, i, 0x00);
1955
1956                 if (ret)
1957                         continue;
1958
1959                 ret |= SETIREG(SISCR, 0x63, 0x80);
1960
1961                 ret |= GETIREG(SISSR, 0x3a, &ramtype);
1962                 ramtype &= 0x03;
1963
1964                 ret |= SETIREG(SISSR, 0x28, mclktable[ramtype * 4]);
1965                 ret |= SETIREG(SISSR, 0x29, mclktable[(ramtype * 4) + 1]);
1966                 ret |= SETIREG(SISSR, 0x2a, mclktable[(ramtype * 4) + 2]);
1967
1968                 ret |= SETIREG(SISSR, 0x2e, eclktable[ramtype * 4]);
1969                 ret |= SETIREG(SISSR, 0x2f, eclktable[(ramtype * 4) + 1]);
1970                 ret |= SETIREG(SISSR, 0x30, eclktable[(ramtype * 4) + 2]);
1971
1972                 ret |= SETIREG(SISSR, 0x07, 0x18);
1973                 ret |= SETIREG(SISSR, 0x11, 0x0f);
1974
1975                 if (ret)
1976                         continue;
1977
1978                 for (i = 0x15, j = 0; i <= 0x1b; i++, j++) {
1979                         ret |= SETIREG(SISSR, i,
1980                                         ramtypetable1[(j*4) + ramtype]);
1981                 }
1982                 for (i = 0x40, j = 0; i <= 0x44; i++, j++) {
1983                         ret |= SETIREG(SISCR, i,
1984                                         ramtypetable2[(j*4) + ramtype]);
1985                 }
1986
1987                 ret |= SETIREG(SISCR, 0x49, 0xaa);
1988
1989                 ret |= SETIREG(SISSR, 0x1f, 0x00);
1990                 ret |= SETIREG(SISSR, 0x20, 0xa0);
1991                 ret |= SETIREG(SISSR, 0x23, 0xf6);
1992                 ret |= SETIREG(SISSR, 0x24, 0x0d);
1993                 ret |= SETIREG(SISSR, 0x25, 0x33);
1994
1995                 ret |= SETIREG(SISSR, 0x11, 0x0f);
1996
1997                 ret |= SETIREGOR(SISPART1, 0x2f, 0x01);
1998
1999                 ret |= SETIREGAND(SISCAP, 0x3f, 0xef);
2000
2001                 if (ret)
2002                         continue;
2003
2004                 ret |= SETIREG(SISPART1, 0x00, 0x00);
2005
2006                 ret |= GETIREG(SISSR, 0x13, &tmp8);
2007                 tmp8 >>= 4;
2008
2009                 ret |= SETIREG(SISPART1, 0x02, 0x00);
2010                 ret |= SETIREG(SISPART1, 0x2e, 0x08);
2011
2012                 ret |= sisusb_read_pci_config(sisusb, 0x50, &tmp32);
2013                 tmp32 &= 0x00f00000;
2014                 tmp8 = (tmp32 == 0x100000) ? 0x33 : 0x03;
2015                 ret |= SETIREG(SISSR, 0x25, tmp8);
2016                 tmp8 = (tmp32 == 0x100000) ? 0xaa : 0x88;
2017                 ret |= SETIREG(SISCR, 0x49, tmp8);
2018
2019                 ret |= SETIREG(SISSR, 0x27, 0x1f);
2020                 ret |= SETIREG(SISSR, 0x31, 0x00);
2021                 ret |= SETIREG(SISSR, 0x32, 0x11);
2022                 ret |= SETIREG(SISSR, 0x33, 0x00);
2023
2024                 if (ret)
2025                         continue;
2026
2027                 ret |= SETIREG(SISCR, 0x83, 0x00);
2028
2029                 ret |= sisusb_set_default_mode(sisusb, 0);
2030
2031                 ret |= SETIREGAND(SISSR, 0x21, 0xdf);
2032                 ret |= SETIREGOR(SISSR, 0x01, 0x20);
2033                 ret |= SETIREGOR(SISSR, 0x16, 0x0f);
2034
2035                 ret |= sisusb_triggersr16(sisusb, ramtype);
2036
2037                 /* Disable refresh */
2038                 ret |= SETIREGAND(SISSR, 0x17, 0xf8);
2039                 ret |= SETIREGOR(SISSR, 0x19, 0x03);
2040
2041                 ret |= sisusb_getbuswidth(sisusb, &bw, &chab);
2042                 ret |= sisusb_verify_mclk(sisusb);
2043
2044                 if (ramtype <= 1) {
2045                         ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab);
2046                         if (iret) {
2047                                 dev_err(&sisusb->sisusb_dev->dev,
2048                                                 "RAM size detection failed, assuming 8MB video RAM\n");
2049                                 ret |= SETIREG(SISSR, 0x14, 0x31);
2050                                 /* TODO */
2051                         }
2052                 } else {
2053                         dev_err(&sisusb->sisusb_dev->dev,
2054                                         "DDR RAM device found, assuming 8MB video RAM\n");
2055                         ret |= SETIREG(SISSR, 0x14, 0x31);
2056                         /* *** TODO *** */
2057                 }
2058
2059                 /* Enable refresh */
2060                 ret |= SETIREG(SISSR, 0x16, ramtypetable1[4 + ramtype]);
2061                 ret |= SETIREG(SISSR, 0x17, ramtypetable1[8 + ramtype]);
2062                 ret |= SETIREG(SISSR, 0x19, ramtypetable1[16 + ramtype]);
2063
2064                 ret |= SETIREGOR(SISSR, 0x21, 0x20);
2065
2066                 ret |= SETIREG(SISSR, 0x22, 0xfb);
2067                 ret |= SETIREG(SISSR, 0x21, 0xa5);
2068
2069                 if (ret == 0)
2070                         break;
2071         }
2072
2073         return ret;
2074 }
2075
2076 #undef SETREG
2077 #undef GETREG
2078 #undef SETIREG
2079 #undef GETIREG
2080 #undef SETIREGOR
2081 #undef SETIREGAND
2082 #undef SETIREGANDOR
2083 #undef READL
2084 #undef WRITEL
2085
2086 static void sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
2087 {
2088         u8 tmp8, tmp82, ramtype;
2089         int bw = 0;
2090         char *ramtypetext1 = NULL;
2091         static const char ram_datarate[4] = {'S', 'S', 'D', 'D'};
2092         static const char ram_dynamictype[4] = {'D', 'G', 'D', 'G'};
2093         static const int busSDR[4]  = {64, 64, 128, 128};
2094         static const int busDDR[4]  = {32, 32,  64,  64};
2095         static const int busDDRA[4] = {64+32, 64+32, (64+32)*2, (64+32)*2};
2096
2097         sisusb_getidxreg(sisusb, SISSR, 0x14, &tmp8);
2098         sisusb_getidxreg(sisusb, SISSR, 0x15, &tmp82);
2099         sisusb_getidxreg(sisusb, SISSR, 0x3a, &ramtype);
2100         sisusb->vramsize = (1 << ((tmp8 & 0xf0) >> 4)) * 1024 * 1024;
2101         ramtype &= 0x03;
2102         switch ((tmp8 >> 2) & 0x03) {
2103         case 0:
2104                 ramtypetext1 = "1 ch/1 r";
2105                 if (tmp82 & 0x10)
2106                         bw = 32;
2107                 else
2108                         bw = busSDR[(tmp8 & 0x03)];
2109
2110                 break;
2111         case 1:
2112                 ramtypetext1 = "1 ch/2 r";
2113                 sisusb->vramsize <<= 1;
2114                 bw = busSDR[(tmp8 & 0x03)];
2115                 break;
2116         case 2:
2117                 ramtypetext1 = "asymmeric";
2118                 sisusb->vramsize += sisusb->vramsize/2;
2119                 bw = busDDRA[(tmp8 & 0x03)];
2120                 break;
2121         case 3:
2122                 ramtypetext1 = "2 channel";
2123                 sisusb->vramsize <<= 1;
2124                 bw = busDDR[(tmp8 & 0x03)];
2125                 break;
2126         }
2127
2128         dev_info(&sisusb->sisusb_dev->dev,
2129                         "%dMB %s %cDR S%cRAM, bus width %d\n",
2130                         sisusb->vramsize >> 20, ramtypetext1,
2131                         ram_datarate[ramtype], ram_dynamictype[ramtype], bw);
2132 }
2133
2134 static int sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb)
2135 {
2136         struct sisusb_packet packet;
2137         int ret;
2138         u32 tmp32;
2139
2140         /* Do some magic */
2141         packet.header  = 0x001f;
2142         packet.address = 0x00000324;
2143         packet.data    = 0x00000004;
2144         ret = sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2145
2146         packet.header  = 0x001f;
2147         packet.address = 0x00000364;
2148         packet.data    = 0x00000004;
2149         ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2150
2151         packet.header  = 0x001f;
2152         packet.address = 0x00000384;
2153         packet.data    = 0x00000004;
2154         ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2155
2156         packet.header  = 0x001f;
2157         packet.address = 0x00000100;
2158         packet.data    = 0x00000700;
2159         ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2160
2161         packet.header  = 0x000f;
2162         packet.address = 0x00000004;
2163         ret |= sisusb_send_bridge_packet(sisusb, 6, &packet, 0);
2164         packet.data |= 0x17;
2165         ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2166
2167         /* Init BAR 0 (VRAM) */
2168         ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2169         ret |= sisusb_write_pci_config(sisusb, 0x10, 0xfffffff0);
2170         ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2171         tmp32 &= 0x0f;
2172         tmp32 |= SISUSB_PCI_MEMBASE;
2173         ret |= sisusb_write_pci_config(sisusb, 0x10, tmp32);
2174
2175         /* Init BAR 1 (MMIO) */
2176         ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2177         ret |= sisusb_write_pci_config(sisusb, 0x14, 0xfffffff0);
2178         ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2179         tmp32 &= 0x0f;
2180         tmp32 |= SISUSB_PCI_MMIOBASE;
2181         ret |= sisusb_write_pci_config(sisusb, 0x14, tmp32);
2182
2183         /* Init BAR 2 (i/o ports) */
2184         ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2185         ret |= sisusb_write_pci_config(sisusb, 0x18, 0xfffffff0);
2186         ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2187         tmp32 &= 0x0f;
2188         tmp32 |= SISUSB_PCI_IOPORTBASE;
2189         ret |= sisusb_write_pci_config(sisusb, 0x18, tmp32);
2190
2191         /* Enable memory and i/o access */
2192         ret |= sisusb_read_pci_config(sisusb, 0x04, &tmp32);
2193         tmp32 |= 0x3;
2194         ret |= sisusb_write_pci_config(sisusb, 0x04, tmp32);
2195
2196         if (ret == 0) {
2197                 /* Some further magic */
2198                 packet.header  = 0x001f;
2199                 packet.address = 0x00000050;
2200                 packet.data    = 0x000000ff;
2201                 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2202         }
2203
2204         return ret;
2205 }
2206
2207 /* Initialize the graphics device (return 0 on success)
2208  * This initializes the net2280 as well as the PCI registers
2209  * of the graphics board.
2210  */
2211
2212 static int sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
2213 {
2214         int ret = 0, test = 0;
2215         u32 tmp32;
2216
2217         if (sisusb->devinit == 1) {
2218                 /* Read PCI BARs and see if they have been set up */
2219                 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2220                 if (ret)
2221                         return ret;
2222
2223                 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE)
2224                         test++;
2225
2226                 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2227                 if (ret)
2228                         return ret;
2229
2230                 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE)
2231                         test++;
2232
2233                 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2234                 if (ret)
2235                         return ret;
2236
2237                 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE)
2238                         test++;
2239         }
2240
2241         /* No? So reset the device */
2242         if ((sisusb->devinit == 0) || (test != 3)) {
2243
2244                 ret |= sisusb_do_init_gfxdevice(sisusb);
2245
2246                 if (ret == 0)
2247                         sisusb->devinit = 1;
2248
2249         }
2250
2251         if (sisusb->devinit) {
2252                 /* Initialize the graphics core */
2253                 if (sisusb_init_gfxcore(sisusb) == 0) {
2254                         sisusb->gfxinit = 1;
2255                         sisusb_get_ramconfig(sisusb);
2256                         ret |= sisusb_set_default_mode(sisusb, 1);
2257                         ret |= sisusb_setup_screen(sisusb, 1, initscreen);
2258                 }
2259         }
2260
2261         return ret;
2262 }
2263
2264
2265 #ifdef INCL_SISUSB_CON
2266
2267 /* Set up default text mode:
2268  * - Set text mode (0x03)
2269  * - Upload default font
2270  * - Upload user font (if available)
2271  */
2272
2273 int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
2274 {
2275         int ret = 0, slot = sisusb->font_slot, i;
2276         const struct font_desc *myfont;
2277         u8 *tempbuf;
2278         u16 *tempbufb;
2279         size_t written;
2280         static const char bootstring[] =
2281                 "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2282         static const char bootlogo[] = "(o_ //\\ V_/_";
2283
2284         /* sisusb->lock is down */
2285
2286         if (!sisusb->SiS_Pr)
2287                 return 1;
2288
2289         sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2290         sisusb->SiS_Pr->sisusb = (void *)sisusb;
2291
2292         /* Set mode 0x03 */
2293         SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
2294
2295         myfont = find_font("VGA8x16");
2296         if (!myfont)
2297                 return 1;
2298
2299         tempbuf = vmalloc(8192);
2300         if (!tempbuf)
2301                 return 1;
2302
2303         for (i = 0; i < 256; i++)
2304                 memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
2305
2306         /* Upload default font */
2307         ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192,
2308                         0, 1, NULL, 16, 0);
2309
2310         vfree(tempbuf);
2311
2312         /* Upload user font (and reset current slot) */
2313         if (sisusb->font_backup) {
2314                 ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
2315                                 8192, sisusb->font_backup_512, 1, NULL,
2316                                 sisusb->font_backup_height, 0);
2317                 if (slot != 2)
2318                         sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
2319                                         NULL, 16, 0);
2320         }
2321
2322         if (init && !sisusb->scrbuf) {
2323
2324                 tempbuf = vmalloc(8192);
2325                 if (tempbuf) {
2326
2327                         i = 4096;
2328                         tempbufb = (u16 *)tempbuf;
2329                         while (i--)
2330                                 *(tempbufb++) = 0x0720;
2331
2332                         i = 0;
2333                         tempbufb = (u16 *)tempbuf;
2334                         while (bootlogo[i]) {
2335                                 *(tempbufb++) = 0x0700 | bootlogo[i++];
2336                                 if (!(i % 4))
2337                                         tempbufb += 76;
2338                         }
2339
2340                         i = 0;
2341                         tempbufb = (u16 *)tempbuf + 6;
2342                         while (bootstring[i])
2343                                 *(tempbufb++) = 0x0700 | bootstring[i++];
2344
2345                         ret |= sisusb_copy_memory(sisusb, tempbuf,
2346                                         sisusb->vrambase, 8192, &written);
2347
2348                         vfree(tempbuf);
2349
2350                 }
2351
2352         } else if (sisusb->scrbuf) {
2353
2354                 ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
2355                                 sisusb->vrambase, sisusb->scrbuf_size,
2356                                 &written);
2357
2358         }
2359
2360         if (sisusb->sisusb_cursor_size_from >= 0 &&
2361                         sisusb->sisusb_cursor_size_to >= 0) {
2362                 sisusb_setidxreg(sisusb, SISCR, 0x0a,
2363                                 sisusb->sisusb_cursor_size_from);
2364                 sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
2365                                 sisusb->sisusb_cursor_size_to);
2366         } else {
2367                 sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
2368                 sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
2369                 sisusb->sisusb_cursor_size_to = -1;
2370         }
2371
2372         slot = sisusb->sisusb_cursor_loc;
2373         if (slot < 0)
2374                 slot = 0;
2375
2376         sisusb->sisusb_cursor_loc = -1;
2377         sisusb->bad_cursor_pos = 1;
2378
2379         sisusb_set_cursor(sisusb, slot);
2380
2381         sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
2382         sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
2383
2384         sisusb->textmodedestroyed = 0;
2385
2386         /* sisusb->lock is down */
2387
2388         return ret;
2389 }
2390
2391 #endif
2392
2393 /* fops */
2394
2395 static int sisusb_open(struct inode *inode, struct file *file)
2396 {
2397         struct sisusb_usb_data *sisusb;
2398         struct usb_interface *interface;
2399         int subminor = iminor(inode);
2400
2401         interface = usb_find_interface(&sisusb_driver, subminor);
2402         if (!interface)
2403                 return -ENODEV;
2404
2405         sisusb = usb_get_intfdata(interface);
2406         if (!sisusb)
2407                 return -ENODEV;
2408
2409         mutex_lock(&sisusb->lock);
2410
2411         if (!sisusb->present || !sisusb->ready) {
2412                 mutex_unlock(&sisusb->lock);
2413                 return -ENODEV;
2414         }
2415
2416         if (sisusb->isopen) {
2417                 mutex_unlock(&sisusb->lock);
2418                 return -EBUSY;
2419         }
2420
2421         if (!sisusb->devinit) {
2422                 if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH ||
2423                                 sisusb->sisusb_dev->speed == USB_SPEED_SUPER) {
2424                         if (sisusb_init_gfxdevice(sisusb, 0)) {
2425                                 mutex_unlock(&sisusb->lock);
2426                                 dev_err(&sisusb->sisusb_dev->dev,
2427                                                 "Failed to initialize device\n");
2428                                 return -EIO;
2429                         }
2430                 } else {
2431                         mutex_unlock(&sisusb->lock);
2432                         dev_err(&sisusb->sisusb_dev->dev,
2433                                         "Device not attached to USB 2.0 hub\n");
2434                         return -EIO;
2435                 }
2436         }
2437
2438         /* Increment usage count for our sisusb */
2439         kref_get(&sisusb->kref);
2440
2441         sisusb->isopen = 1;
2442
2443         file->private_data = sisusb;
2444
2445         mutex_unlock(&sisusb->lock);
2446
2447         return 0;
2448 }
2449
2450 void sisusb_delete(struct kref *kref)
2451 {
2452         struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
2453
2454         if (!sisusb)
2455                 return;
2456
2457         usb_put_dev(sisusb->sisusb_dev);
2458
2459         sisusb->sisusb_dev = NULL;
2460         sisusb_free_buffers(sisusb);
2461         sisusb_free_urbs(sisusb);
2462 #ifdef INCL_SISUSB_CON
2463         kfree(sisusb->SiS_Pr);
2464 #endif
2465         kfree(sisusb);
2466 }
2467
2468 static int sisusb_release(struct inode *inode, struct file *file)
2469 {
2470         struct sisusb_usb_data *sisusb;
2471
2472         sisusb = file->private_data;
2473         if (!sisusb)
2474                 return -ENODEV;
2475
2476         mutex_lock(&sisusb->lock);
2477
2478         if (sisusb->present) {
2479                 /* Wait for all URBs to finish if device still present */
2480                 if (!sisusb_wait_all_out_complete(sisusb))
2481                         sisusb_kill_all_busy(sisusb);
2482         }
2483
2484         sisusb->isopen = 0;
2485         file->private_data = NULL;
2486
2487         mutex_unlock(&sisusb->lock);
2488
2489         /* decrement the usage count on our device */
2490         kref_put(&sisusb->kref, sisusb_delete);
2491
2492         return 0;
2493 }
2494
2495 static ssize_t sisusb_read(struct file *file, char __user *buffer,
2496                 size_t count, loff_t *ppos)
2497 {
2498         struct sisusb_usb_data *sisusb;
2499         ssize_t bytes_read = 0;
2500         int errno = 0;
2501         u8 buf8;
2502         u16 buf16;
2503         u32 buf32, address;
2504
2505         sisusb = file->private_data;
2506         if (!sisusb)
2507                 return -ENODEV;
2508
2509         mutex_lock(&sisusb->lock);
2510
2511         /* Sanity check */
2512         if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2513                 mutex_unlock(&sisusb->lock);
2514                 return -ENODEV;
2515         }
2516
2517         if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2518                         (*ppos) <  SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2519
2520                 address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE +
2521                                 SISUSB_PCI_IOPORTBASE;
2522
2523                 /* Read i/o ports
2524                  * Byte, word and long(32) can be read. As this
2525                  * emulates inX instructions, the data returned is
2526                  * in machine-endianness.
2527                  */
2528                 switch (count) {
2529                 case 1:
2530                         if (sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO,
2531                                         address, &buf8))
2532                                 errno = -EIO;
2533                         else if (put_user(buf8, (u8 __user *)buffer))
2534                                 errno = -EFAULT;
2535                         else
2536                                 bytes_read = 1;
2537
2538                         break;
2539
2540                 case 2:
2541                         if (sisusb_read_memio_word(sisusb, SISUSB_TYPE_IO,
2542                                         address, &buf16))
2543                                 errno = -EIO;
2544                         else if (put_user(buf16, (u16 __user *)buffer))
2545                                 errno = -EFAULT;
2546                         else
2547                                 bytes_read = 2;
2548
2549                         break;
2550
2551                 case 4:
2552                         if (sisusb_read_memio_long(sisusb, SISUSB_TYPE_IO,
2553                                         address, &buf32))
2554                                 errno = -EIO;
2555                         else if (put_user(buf32, (u32 __user *)buffer))
2556                                 errno = -EFAULT;
2557                         else
2558                                 bytes_read = 4;
2559
2560                         break;
2561
2562                 default:
2563                         errno = -EIO;
2564
2565                 }
2566
2567         } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && (*ppos) <
2568                         SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2569
2570                 address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE +
2571                                 SISUSB_PCI_MEMBASE;
2572
2573                 /* Read video ram
2574                  * Remember: Data delivered is never endian-corrected
2575                  */
2576                 errno = sisusb_read_mem_bulk(sisusb, address,
2577                                 NULL, count, buffer, &bytes_read);
2578
2579                 if (bytes_read)
2580                         errno = bytes_read;
2581
2582         } else  if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2583                                 (*ppos) <  SISUSB_PCI_PSEUDO_MMIOBASE +
2584                                 SISUSB_PCI_MMIOSIZE) {
2585
2586                 address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE +
2587                                 SISUSB_PCI_MMIOBASE;
2588
2589                 /* Read MMIO
2590                  * Remember: Data delivered is never endian-corrected
2591                  */
2592                 errno = sisusb_read_mem_bulk(sisusb, address,
2593                                 NULL, count, buffer, &bytes_read);
2594
2595                 if (bytes_read)
2596                         errno = bytes_read;
2597
2598         } else  if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2599                         (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
2600
2601                 if (count != 4) {
2602                         mutex_unlock(&sisusb->lock);
2603                         return -EINVAL;
2604                 }
2605
2606                 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2607
2608                 /* Read PCI config register
2609                  * Return value delivered in machine endianness.
2610                  */
2611                 if (sisusb_read_pci_config(sisusb, address, &buf32))
2612                         errno = -EIO;
2613                 else if (put_user(buf32, (u32 __user *)buffer))
2614                         errno = -EFAULT;
2615                 else
2616                         bytes_read = 4;
2617
2618         } else {
2619
2620                 errno = -EBADFD;
2621
2622         }
2623
2624         (*ppos) += bytes_read;
2625
2626         mutex_unlock(&sisusb->lock);
2627
2628         return errno ? errno : bytes_read;
2629 }
2630
2631 static ssize_t sisusb_write(struct file *file, const char __user *buffer,
2632                 size_t count, loff_t *ppos)
2633 {
2634         struct sisusb_usb_data *sisusb;
2635         int errno = 0;
2636         ssize_t bytes_written = 0;
2637         u8 buf8;
2638         u16 buf16;
2639         u32 buf32, address;
2640
2641         sisusb = file->private_data;
2642         if (!sisusb)
2643                 return -ENODEV;
2644
2645         mutex_lock(&sisusb->lock);
2646
2647         /* Sanity check */
2648         if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2649                 mutex_unlock(&sisusb->lock);
2650                 return -ENODEV;
2651         }
2652
2653         if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2654                         (*ppos) <  SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2655
2656                 address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE +
2657                                 SISUSB_PCI_IOPORTBASE;
2658
2659                 /* Write i/o ports
2660                  * Byte, word and long(32) can be written. As this
2661                  * emulates outX instructions, the data is expected
2662                  * in machine-endianness.
2663                  */
2664                 switch (count) {
2665                 case 1:
2666                         if (get_user(buf8, (u8 __user *)buffer))
2667                                 errno = -EFAULT;
2668                         else if (sisusb_write_memio_byte(sisusb,
2669                                         SISUSB_TYPE_IO, address, buf8))
2670                                 errno = -EIO;
2671                         else
2672                                 bytes_written = 1;
2673
2674                         break;
2675
2676                 case 2:
2677                         if (get_user(buf16, (u16 __user *)buffer))
2678                                 errno = -EFAULT;
2679                         else if (sisusb_write_memio_word(sisusb,
2680                                         SISUSB_TYPE_IO, address, buf16))
2681                                 errno = -EIO;
2682                         else
2683                                 bytes_written = 2;
2684
2685                         break;
2686
2687                 case 4:
2688                         if (get_user(buf32, (u32 __user *)buffer))
2689                                 errno = -EFAULT;
2690                         else if (sisusb_write_memio_long(sisusb,
2691                                         SISUSB_TYPE_IO, address, buf32))
2692                                 errno = -EIO;
2693                         else
2694                                 bytes_written = 4;
2695
2696                         break;
2697
2698                 default:
2699                         errno = -EIO;
2700                 }
2701
2702         } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2703                         (*ppos) <  SISUSB_PCI_PSEUDO_MEMBASE +
2704                         sisusb->vramsize) {
2705
2706                 address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE +
2707                                 SISUSB_PCI_MEMBASE;
2708
2709                 /* Write video ram.
2710                  * Buffer is copied 1:1, therefore, on big-endian
2711                  * machines, the data must be swapped by userland
2712                  * in advance (if applicable; no swapping in 8bpp
2713                  * mode or if YUV data is being transferred).
2714                  */
2715                 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2716                                 count, buffer, 0, &bytes_written);
2717
2718                 if (bytes_written)
2719                         errno = bytes_written;
2720
2721         } else  if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2722                         (*ppos) <  SISUSB_PCI_PSEUDO_MMIOBASE +
2723                         SISUSB_PCI_MMIOSIZE) {
2724
2725                 address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE +
2726                                 SISUSB_PCI_MMIOBASE;
2727
2728                 /* Write MMIO.
2729                  * Buffer is copied 1:1, therefore, on big-endian
2730                  * machines, the data must be swapped by userland
2731                  * in advance.
2732                  */
2733                 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2734                                 count, buffer, 0, &bytes_written);
2735
2736                 if (bytes_written)
2737                         errno = bytes_written;
2738
2739         } else  if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2740                                 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE +
2741                                 SISUSB_PCI_PCONFSIZE) {
2742
2743                 if (count != 4) {
2744                         mutex_unlock(&sisusb->lock);
2745                         return -EINVAL;
2746                 }
2747
2748                 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2749
2750                 /* Write PCI config register.
2751                  * Given value expected in machine endianness.
2752                  */
2753                 if (get_user(buf32, (u32 __user *)buffer))
2754                         errno = -EFAULT;
2755                 else if (sisusb_write_pci_config(sisusb, address, buf32))
2756                         errno = -EIO;
2757                 else
2758                         bytes_written = 4;
2759
2760
2761         } else {
2762
2763                 /* Error */
2764                 errno = -EBADFD;
2765
2766         }
2767
2768         (*ppos) += bytes_written;
2769
2770         mutex_unlock(&sisusb->lock);
2771
2772         return errno ? errno : bytes_written;
2773 }
2774
2775 static loff_t sisusb_lseek(struct file *file, loff_t offset, int orig)
2776 {
2777         struct sisusb_usb_data *sisusb;
2778         loff_t ret;
2779
2780         sisusb = file->private_data;
2781         if (!sisusb)
2782                 return -ENODEV;
2783
2784         mutex_lock(&sisusb->lock);
2785
2786         /* Sanity check */
2787         if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2788                 mutex_unlock(&sisusb->lock);
2789                 return -ENODEV;
2790         }
2791
2792         ret = no_seek_end_llseek(file, offset, orig);
2793
2794         mutex_unlock(&sisusb->lock);
2795         return ret;
2796 }
2797
2798 static int sisusb_handle_command(struct sisusb_usb_data *sisusb,
2799                 struct sisusb_command *y, unsigned long arg)
2800 {
2801         int     retval, port, length;
2802         u32     address;
2803
2804         /* All our commands require the device
2805          * to be initialized.
2806          */
2807         if (!sisusb->devinit)
2808                 return -ENODEV;
2809
2810         port = y->data3 -
2811                 SISUSB_PCI_PSEUDO_IOPORTBASE +
2812                 SISUSB_PCI_IOPORTBASE;
2813
2814         switch (y->operation) {
2815         case SUCMD_GET:
2816                 retval = sisusb_getidxreg(sisusb, port, y->data0, &y->data1);
2817                 if (!retval) {
2818                         if (copy_to_user((void __user *)arg, y, sizeof(*y)))
2819                                 retval = -EFAULT;
2820                 }
2821                 break;
2822
2823         case SUCMD_SET:
2824                 retval = sisusb_setidxreg(sisusb, port, y->data0, y->data1);
2825                 break;
2826
2827         case SUCMD_SETOR:
2828                 retval = sisusb_setidxregor(sisusb, port, y->data0, y->data1);
2829                 break;
2830
2831         case SUCMD_SETAND:
2832                 retval = sisusb_setidxregand(sisusb, port, y->data0, y->data1);
2833                 break;
2834
2835         case SUCMD_SETANDOR:
2836                 retval = sisusb_setidxregandor(sisusb, port, y->data0,
2837                                 y->data1, y->data2);
2838                 break;
2839
2840         case SUCMD_SETMASK:
2841                 retval = sisusb_setidxregmask(sisusb, port, y->data0,
2842                                 y->data1, y->data2);
2843                 break;
2844
2845         case SUCMD_CLRSCR:
2846                 /* Gfx core must be initialized */
2847                 if (!sisusb->gfxinit)
2848                         return -ENODEV;
2849
2850                 length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
2851                 address = y->data3 - SISUSB_PCI_PSEUDO_MEMBASE +
2852                                 SISUSB_PCI_MEMBASE;
2853                 retval = sisusb_clear_vram(sisusb, address, length);
2854                 break;
2855
2856         case SUCMD_HANDLETEXTMODE:
2857                 retval = 0;
2858 #ifdef INCL_SISUSB_CON
2859                 /* Gfx core must be initialized, SiS_Pr must exist */
2860                 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2861                         return -ENODEV;
2862
2863                 switch (y->data0) {
2864                 case 0:
2865                         retval = sisusb_reset_text_mode(sisusb, 0);
2866                         break;
2867                 case 1:
2868                         sisusb->textmodedestroyed = 1;
2869                         break;
2870                 }
2871 #endif
2872                 break;
2873
2874 #ifdef INCL_SISUSB_CON
2875         case SUCMD_SETMODE:
2876                 /* Gfx core must be initialized, SiS_Pr must exist */
2877                 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2878                         return -ENODEV;
2879
2880                 retval = 0;
2881
2882                 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2883                 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2884
2885                 if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
2886                         retval = -EINVAL;
2887
2888                 break;
2889
2890         case SUCMD_SETVESAMODE:
2891                 /* Gfx core must be initialized, SiS_Pr must exist */
2892                 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2893                         return -ENODEV;
2894
2895                 retval = 0;
2896
2897                 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2898                 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2899
2900                 if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
2901                         retval = -EINVAL;
2902
2903                 break;
2904 #endif
2905
2906         default:
2907                 retval = -EINVAL;
2908         }
2909
2910         if (retval > 0)
2911                 retval = -EIO;
2912
2913         return retval;
2914 }
2915
2916 static long sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2917 {
2918         struct sisusb_usb_data *sisusb;
2919         struct sisusb_info x;
2920         struct sisusb_command y;
2921         long retval = 0;
2922         u32 __user *argp = (u32 __user *)arg;
2923
2924         sisusb = file->private_data;
2925         if (!sisusb)
2926                 return -ENODEV;
2927
2928         mutex_lock(&sisusb->lock);
2929
2930         /* Sanity check */
2931         if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2932                 retval = -ENODEV;
2933                 goto err_out;
2934         }
2935
2936         switch (cmd) {
2937         case SISUSB_GET_CONFIG_SIZE:
2938
2939                 if (put_user(sizeof(x), argp))
2940                         retval = -EFAULT;
2941
2942                 break;
2943
2944         case SISUSB_GET_CONFIG:
2945
2946                 x.sisusb_id = SISUSB_ID;
2947                 x.sisusb_version = SISUSB_VERSION;
2948                 x.sisusb_revision = SISUSB_REVISION;
2949                 x.sisusb_patchlevel = SISUSB_PATCHLEVEL;
2950                 x.sisusb_gfxinit = sisusb->gfxinit;
2951                 x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE;
2952                 x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE;
2953                 x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE;
2954                 x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE;
2955                 x.sisusb_vramsize = sisusb->vramsize;
2956                 x.sisusb_minor = sisusb->minor;
2957                 x.sisusb_fbdevactive = 0;
2958 #ifdef INCL_SISUSB_CON
2959                 x.sisusb_conactive  = sisusb->haveconsole ? 1 : 0;
2960 #else
2961                 x.sisusb_conactive  = 0;
2962 #endif
2963                 memset(x.sisusb_reserved, 0, sizeof(x.sisusb_reserved));
2964
2965                 if (copy_to_user((void __user *)arg, &x, sizeof(x)))
2966                         retval = -EFAULT;
2967
2968                 break;
2969
2970         case SISUSB_COMMAND:
2971
2972                 if (copy_from_user(&y, (void __user *)arg, sizeof(y)))
2973                         retval = -EFAULT;
2974                 else
2975                         retval = sisusb_handle_command(sisusb, &y, arg);
2976
2977                 break;
2978
2979         default:
2980                 retval = -ENOTTY;
2981                 break;
2982         }
2983
2984 err_out:
2985         mutex_unlock(&sisusb->lock);
2986         return retval;
2987 }
2988
2989 #ifdef SISUSB_NEW_CONFIG_COMPAT
2990 static long sisusb_compat_ioctl(struct file *f, unsigned int cmd,
2991                 unsigned long arg)
2992 {
2993         long retval;
2994
2995         switch (cmd) {
2996         case SISUSB_GET_CONFIG_SIZE:
2997         case SISUSB_GET_CONFIG:
2998         case SISUSB_COMMAND:
2999                 retval = sisusb_ioctl(f, cmd, arg);
3000                 return retval;
3001
3002         default:
3003                 return -ENOIOCTLCMD;
3004         }
3005 }
3006 #endif
3007
3008 static const struct file_operations usb_sisusb_fops = {
3009         .owner =        THIS_MODULE,
3010         .open =         sisusb_open,
3011         .release =      sisusb_release,
3012         .read =         sisusb_read,
3013         .write =        sisusb_write,
3014         .llseek =       sisusb_lseek,
3015 #ifdef SISUSB_NEW_CONFIG_COMPAT
3016         .compat_ioctl = sisusb_compat_ioctl,
3017 #endif
3018         .unlocked_ioctl = sisusb_ioctl
3019 };
3020
3021 static struct usb_class_driver usb_sisusb_class = {
3022         .name =         "sisusbvga%d",
3023         .fops =         &usb_sisusb_fops,
3024         .minor_base =   SISUSB_MINOR
3025 };
3026
3027 static int sisusb_probe(struct usb_interface *intf,
3028                 const struct usb_device_id *id)
3029 {
3030         struct usb_device *dev = interface_to_usbdev(intf);
3031         struct sisusb_usb_data *sisusb;
3032         int retval = 0, i;
3033
3034         dev_info(&dev->dev, "USB2VGA dongle found at address %d\n",
3035                         dev->devnum);
3036
3037         /* Allocate memory for our private */
3038         sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL);
3039         if (!sisusb)
3040                 return -ENOMEM;
3041
3042         kref_init(&sisusb->kref);
3043
3044         mutex_init(&(sisusb->lock));
3045
3046         /* Register device */
3047         retval = usb_register_dev(intf, &usb_sisusb_class);
3048         if (retval) {
3049                 dev_err(&sisusb->sisusb_dev->dev,
3050                                 "Failed to get a minor for device %d\n",
3051                                 dev->devnum);
3052                 retval = -ENODEV;
3053                 goto error_1;
3054         }
3055
3056         sisusb->sisusb_dev = dev;
3057         sisusb->minor      = intf->minor;
3058         sisusb->vrambase   = SISUSB_PCI_MEMBASE;
3059         sisusb->mmiobase   = SISUSB_PCI_MMIOBASE;
3060         sisusb->mmiosize   = SISUSB_PCI_MMIOSIZE;
3061         sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
3062         /* Everything else is zero */
3063
3064         /* Allocate buffers */
3065         sisusb->ibufsize = SISUSB_IBUF_SIZE;
3066         sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL);
3067         if (!sisusb->ibuf) {
3068                 retval = -ENOMEM;
3069                 goto error_2;
3070         }
3071
3072         sisusb->numobufs = 0;
3073         sisusb->obufsize = SISUSB_OBUF_SIZE;
3074         for (i = 0; i < NUMOBUFS; i++) {
3075                 sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL);
3076                 if (!sisusb->obuf[i]) {
3077                         if (i == 0) {
3078                                 retval = -ENOMEM;
3079                                 goto error_3;
3080                         }
3081                         break;
3082                 }
3083                 sisusb->numobufs++;
3084         }
3085
3086         /* Allocate URBs */
3087         sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL);
3088         if (!sisusb->sisurbin) {
3089                 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n");
3090                 retval = -ENOMEM;
3091                 goto error_3;
3092         }
3093         sisusb->completein = 1;
3094
3095         for (i = 0; i < sisusb->numobufs; i++) {
3096                 sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL);
3097                 if (!sisusb->sisurbout[i]) {
3098                         dev_err(&sisusb->sisusb_dev->dev,
3099                                         "Failed to allocate URBs\n");
3100                         retval = -ENOMEM;
3101                         goto error_4;
3102                 }
3103                 sisusb->urbout_context[i].sisusb = (void *)sisusb;
3104                 sisusb->urbout_context[i].urbindex = i;
3105                 sisusb->urbstatus[i] = 0;
3106         }
3107
3108         dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n",
3109                         sisusb->numobufs);
3110
3111 #ifdef INCL_SISUSB_CON
3112         /* Allocate our SiS_Pr */
3113         sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL);
3114         if (!sisusb->SiS_Pr) {
3115                 retval = -ENOMEM;
3116                 goto error_4;
3117         }
3118 #endif
3119
3120         /* Do remaining init stuff */
3121
3122         init_waitqueue_head(&sisusb->wait_q);
3123
3124         usb_set_intfdata(intf, sisusb);
3125
3126         usb_get_dev(sisusb->sisusb_dev);
3127
3128         sisusb->present = 1;
3129
3130         if (dev->speed == USB_SPEED_HIGH || dev->speed == USB_SPEED_SUPER) {
3131                 int initscreen = 1;
3132 #ifdef INCL_SISUSB_CON
3133                 if (sisusb_first_vc > 0 && sisusb_last_vc > 0 &&
3134                                 sisusb_first_vc <= sisusb_last_vc &&
3135                                 sisusb_last_vc <= MAX_NR_CONSOLES)
3136                         initscreen = 0;
3137 #endif
3138                 if (sisusb_init_gfxdevice(sisusb, initscreen))
3139                         dev_err(&sisusb->sisusb_dev->dev,
3140                                         "Failed to early initialize device\n");
3141
3142         } else
3143                 dev_info(&sisusb->sisusb_dev->dev,
3144                                 "Not attached to USB 2.0 hub, deferring init\n");
3145
3146         sisusb->ready = 1;
3147
3148 #ifdef SISUSBENDIANTEST
3149         dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST ***\n");
3150         sisusb_testreadwrite(sisusb);
3151         dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST END ***\n");
3152 #endif
3153
3154 #ifdef INCL_SISUSB_CON
3155         sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
3156 #endif
3157
3158         return 0;
3159
3160 error_4:
3161         sisusb_free_urbs(sisusb);
3162 error_3:
3163         sisusb_free_buffers(sisusb);
3164 error_2:
3165         usb_deregister_dev(intf, &usb_sisusb_class);
3166 error_1:
3167         kfree(sisusb);
3168         return retval;
3169 }
3170
3171 static void sisusb_disconnect(struct usb_interface *intf)
3172 {
3173         struct sisusb_usb_data *sisusb;
3174
3175         /* This should *not* happen */
3176         sisusb = usb_get_intfdata(intf);
3177         if (!sisusb)
3178                 return;
3179
3180 #ifdef INCL_SISUSB_CON
3181         sisusb_console_exit(sisusb);
3182 #endif
3183
3184         usb_deregister_dev(intf, &usb_sisusb_class);
3185
3186         mutex_lock(&sisusb->lock);
3187
3188         /* Wait for all URBs to complete and kill them in case (MUST do) */
3189         if (!sisusb_wait_all_out_complete(sisusb))
3190                 sisusb_kill_all_busy(sisusb);
3191
3192         usb_set_intfdata(intf, NULL);
3193
3194         sisusb->present = 0;
3195         sisusb->ready = 0;
3196
3197         mutex_unlock(&sisusb->lock);
3198
3199         /* decrement our usage count */
3200         kref_put(&sisusb->kref, sisusb_delete);
3201 }
3202
3203 static const struct usb_device_id sisusb_table[] = {
3204         { USB_DEVICE(0x0711, 0x0550) },
3205         { USB_DEVICE(0x0711, 0x0900) },
3206         { USB_DEVICE(0x0711, 0x0901) },
3207         { USB_DEVICE(0x0711, 0x0902) },
3208         { USB_DEVICE(0x0711, 0x0903) },
3209         { USB_DEVICE(0x0711, 0x0918) },
3210         { USB_DEVICE(0x0711, 0x0920) },
3211         { USB_DEVICE(0x0711, 0x0950) },
3212         { USB_DEVICE(0x0711, 0x5200) },
3213         { USB_DEVICE(0x182d, 0x021c) },
3214         { USB_DEVICE(0x182d, 0x0269) },
3215         { }
3216 };
3217
3218 MODULE_DEVICE_TABLE(usb, sisusb_table);
3219
3220 static struct usb_driver sisusb_driver = {
3221         .name =         "sisusb",
3222         .probe =        sisusb_probe,
3223         .disconnect =   sisusb_disconnect,
3224         .id_table =     sisusb_table,
3225 };
3226
3227 static int __init usb_sisusb_init(void)
3228 {
3229
3230 #ifdef INCL_SISUSB_CON
3231         sisusb_init_concode();
3232 #endif
3233
3234         return usb_register(&sisusb_driver);
3235 }
3236
3237 static void __exit usb_sisusb_exit(void)
3238 {
3239         usb_deregister(&sisusb_driver);
3240 }
3241
3242 module_init(usb_sisusb_init);
3243 module_exit(usb_sisusb_exit);
3244
3245 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3246 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3247 MODULE_LICENSE("GPL");
3248