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