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