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