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