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