USB: SisUSB2VGA: Convert printk to dev_* macros
[firefly-linux-kernel-4.4.55.git] / drivers / usb / misc / sisusbvga / sisusb.c
1 /*
2  * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
3  *
4  * Main part
5  *
6  * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
7  *
8  * If distributed as part of the Linux kernel, this code is licensed under the
9  * terms of the GPL v2.
10  *
11  * Otherwise, the following license terms apply:
12  *
13  * * Redistribution and use in source and binary forms, with or without
14  * * modification, are permitted provided that the following conditions
15  * * are met:
16  * * 1) Redistributions of source code must retain the above copyright
17  * *    notice, this list of conditions and the following disclaimer.
18  * * 2) Redistributions in binary form must reproduce the above copyright
19  * *    notice, this list of conditions and the following disclaimer in the
20  * *    documentation and/or other materials provided with the distribution.
21  * * 3) The name of the author may not be used to endorse or promote products
22  * *    derived from this software without specific psisusbr written permission.
23  * *
24  * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
25  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29  * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33  * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  *
35  * Author:      Thomas Winischhofer <thomas@winischhofer.net>
36  *
37  */
38
39 #include <linux/mutex.h>
40 #include <linux/module.h>
41 #include <linux/kernel.h>
42 #include <linux/signal.h>
43 #include <linux/errno.h>
44 #include <linux/poll.h>
45 #include <linux/init.h>
46 #include <linux/slab.h>
47 #include <linux/spinlock.h>
48 #include <linux/kref.h>
49 #include <linux/usb.h>
50 #include <linux/smp_lock.h>
51 #include <linux/vmalloc.h>
52
53 #include "sisusb.h"
54 #include "sisusb_init.h"
55
56 #ifdef INCL_SISUSB_CON
57 #include <linux/font.h>
58 #endif
59
60 #define SISUSB_DONTSYNC
61
62 /* Forward declarations / clean-up routines */
63
64 #ifdef INCL_SISUSB_CON
65 static int sisusb_first_vc = 0;
66 static int sisusb_last_vc = 0;
67 module_param_named(first, sisusb_first_vc, int, 0);
68 module_param_named(last, sisusb_last_vc, int, 0);
69 MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
70 MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
71 #endif
72
73 static struct usb_driver sisusb_driver;
74
75 static void
76 sisusb_free_buffers(struct sisusb_usb_data *sisusb)
77 {
78         int i;
79
80         for (i = 0; i < NUMOBUFS; i++) {
81                 if (sisusb->obuf[i]) {
82                         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 timout */
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                 dev_err(&sisusb->sisusb_dev->dev, "Failed to find interface\n");
2445                 return -ENODEV;
2446         }
2447
2448         if (!(sisusb = usb_get_intfdata(interface)))
2449                 return -ENODEV;
2450
2451         mutex_lock(&sisusb->lock);
2452
2453         if (!sisusb->present || !sisusb->ready) {
2454                 mutex_unlock(&sisusb->lock);
2455                 return -ENODEV;
2456         }
2457
2458         if (sisusb->isopen) {
2459                 mutex_unlock(&sisusb->lock);
2460                 return -EBUSY;
2461         }
2462
2463         if (!sisusb->devinit) {
2464                 if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) {
2465                         if (sisusb_init_gfxdevice(sisusb, 0)) {
2466                                 mutex_unlock(&sisusb->lock);
2467                                 dev_err(&sisusb->sisusb_dev->dev, "Failed to initialize device\n");
2468                                 return -EIO;
2469                         }
2470                 } else {
2471                         mutex_unlock(&sisusb->lock);
2472                         dev_err(&sisusb->sisusb_dev->dev, "Device not attached to USB 2.0 hub\n");
2473                         return -EIO;
2474                 }
2475         }
2476
2477         /* Increment usage count for our sisusb */
2478         kref_get(&sisusb->kref);
2479
2480         sisusb->isopen = 1;
2481
2482         file->private_data = sisusb;
2483
2484         mutex_unlock(&sisusb->lock);
2485
2486         return 0;
2487 }
2488
2489 void
2490 sisusb_delete(struct kref *kref)
2491 {
2492         struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
2493
2494         if (!sisusb)
2495                 return;
2496
2497         if (sisusb->sisusb_dev)
2498                 usb_put_dev(sisusb->sisusb_dev);
2499
2500         sisusb->sisusb_dev = NULL;
2501         sisusb_free_buffers(sisusb);
2502         sisusb_free_urbs(sisusb);
2503 #ifdef INCL_SISUSB_CON
2504         kfree(sisusb->SiS_Pr);
2505 #endif
2506         kfree(sisusb);
2507 }
2508
2509 static int
2510 sisusb_release(struct inode *inode, struct file *file)
2511 {
2512         struct sisusb_usb_data *sisusb;
2513
2514         if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2515                 return -ENODEV;
2516
2517         mutex_lock(&sisusb->lock);
2518
2519         if (sisusb->present) {
2520                 /* Wait for all URBs to finish if device still present */
2521                 if (!sisusb_wait_all_out_complete(sisusb))
2522                         sisusb_kill_all_busy(sisusb);
2523         }
2524
2525         sisusb->isopen = 0;
2526         file->private_data = NULL;
2527
2528         mutex_unlock(&sisusb->lock);
2529
2530         /* decrement the usage count on our device */
2531         kref_put(&sisusb->kref, sisusb_delete);
2532
2533         return 0;
2534 }
2535
2536 static ssize_t
2537 sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
2538 {
2539         struct sisusb_usb_data *sisusb;
2540         ssize_t bytes_read = 0;
2541         int errno = 0;
2542         u8 buf8;
2543         u16 buf16;
2544         u32 buf32, address;
2545
2546         if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2547                 return -ENODEV;
2548
2549         mutex_lock(&sisusb->lock);
2550
2551         /* Sanity check */
2552         if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2553                 mutex_unlock(&sisusb->lock);
2554                 return -ENODEV;
2555         }
2556
2557         if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2558             (*ppos) <  SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2559
2560                 address = (*ppos) -
2561                         SISUSB_PCI_PSEUDO_IOPORTBASE +
2562                         SISUSB_PCI_IOPORTBASE;
2563
2564                 /* Read i/o ports
2565                  * Byte, word and long(32) can be read. As this
2566                  * emulates inX instructions, the data returned is
2567                  * in machine-endianness.
2568                  */
2569                 switch (count) {
2570
2571                         case 1:
2572                                 if (sisusb_read_memio_byte(sisusb,
2573                                                         SISUSB_TYPE_IO,
2574                                                         address, &buf8))
2575                                         errno = -EIO;
2576                                 else if (put_user(buf8, (u8 __user *)buffer))
2577                                         errno = -EFAULT;
2578                                 else
2579                                         bytes_read = 1;
2580
2581                                 break;
2582
2583                         case 2:
2584                                 if (sisusb_read_memio_word(sisusb,
2585                                                         SISUSB_TYPE_IO,
2586                                                         address, &buf16))
2587                                         errno = -EIO;
2588                                 else if (put_user(buf16, (u16 __user *)buffer))
2589                                         errno = -EFAULT;
2590                                 else
2591                                         bytes_read = 2;
2592
2593                                 break;
2594
2595                         case 4:
2596                                 if (sisusb_read_memio_long(sisusb,
2597                                                         SISUSB_TYPE_IO,
2598                                                         address, &buf32))
2599                                         errno = -EIO;
2600                                 else if (put_user(buf32, (u32 __user *)buffer))
2601                                         errno = -EFAULT;
2602                                 else
2603                                         bytes_read = 4;
2604
2605                                 break;
2606
2607                         default:
2608                                 errno = -EIO;
2609
2610                 }
2611
2612         } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2613                    (*ppos) <  SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2614
2615                 address = (*ppos) -
2616                         SISUSB_PCI_PSEUDO_MEMBASE +
2617                         SISUSB_PCI_MEMBASE;
2618
2619                 /* Read video ram
2620                  * Remember: Data delivered is never endian-corrected
2621                  */
2622                 errno = sisusb_read_mem_bulk(sisusb, address,
2623                                         NULL, count, buffer, &bytes_read);
2624
2625                 if (bytes_read)
2626                         errno = bytes_read;
2627
2628         } else  if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2629                     (*ppos) <  SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) {
2630
2631                 address = (*ppos) -
2632                         SISUSB_PCI_PSEUDO_MMIOBASE +
2633                         SISUSB_PCI_MMIOBASE;
2634
2635                 /* Read MMIO
2636                  * Remember: Data delivered is never endian-corrected
2637                  */
2638                 errno = sisusb_read_mem_bulk(sisusb, address,
2639                                         NULL, count, buffer, &bytes_read);
2640
2641                 if (bytes_read)
2642                         errno = bytes_read;
2643
2644         } else  if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2645                     (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
2646
2647                 if (count != 4) {
2648                         mutex_unlock(&sisusb->lock);
2649                         return -EINVAL;
2650                 }
2651
2652                 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2653
2654                 /* Read PCI config register
2655                  * Return value delivered in machine endianness.
2656                  */
2657                 if (sisusb_read_pci_config(sisusb, address, &buf32))
2658                         errno = -EIO;
2659                 else if (put_user(buf32, (u32 __user *)buffer))
2660                         errno = -EFAULT;
2661                 else
2662                         bytes_read = 4;
2663
2664         } else {
2665
2666                 errno = -EBADFD;
2667
2668         }
2669
2670         (*ppos) += bytes_read;
2671
2672         mutex_unlock(&sisusb->lock);
2673
2674         return errno ? errno : bytes_read;
2675 }
2676
2677 static ssize_t
2678 sisusb_write(struct file *file, const char __user *buffer, size_t count,
2679                                                                 loff_t *ppos)
2680 {
2681         struct sisusb_usb_data *sisusb;
2682         int errno = 0;
2683         ssize_t bytes_written = 0;
2684         u8 buf8;
2685         u16 buf16;
2686         u32 buf32, address;
2687
2688         if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2689                 return -ENODEV;
2690
2691         mutex_lock(&sisusb->lock);
2692
2693         /* Sanity check */
2694         if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2695                 mutex_unlock(&sisusb->lock);
2696                 return -ENODEV;
2697         }
2698
2699         if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2700             (*ppos) <  SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2701
2702                 address = (*ppos) -
2703                         SISUSB_PCI_PSEUDO_IOPORTBASE +
2704                         SISUSB_PCI_IOPORTBASE;
2705
2706                 /* Write i/o ports
2707                  * Byte, word and long(32) can be written. As this
2708                  * emulates outX instructions, the data is expected
2709                  * in machine-endianness.
2710                  */
2711                 switch (count) {
2712
2713                         case 1:
2714                                 if (get_user(buf8, (u8 __user *)buffer))
2715                                         errno = -EFAULT;
2716                                 else if (sisusb_write_memio_byte(sisusb,
2717                                                         SISUSB_TYPE_IO,
2718                                                         address, buf8))
2719                                         errno = -EIO;
2720                                 else
2721                                         bytes_written = 1;
2722
2723                                 break;
2724
2725                         case 2:
2726                                 if (get_user(buf16, (u16 __user *)buffer))
2727                                         errno = -EFAULT;
2728                                 else if (sisusb_write_memio_word(sisusb,
2729                                                         SISUSB_TYPE_IO,
2730                                                         address, buf16))
2731                                         errno = -EIO;
2732                                 else
2733                                         bytes_written = 2;
2734
2735                                 break;
2736
2737                         case 4:
2738                                 if (get_user(buf32, (u32 __user *)buffer))
2739                                         errno = -EFAULT;
2740                                 else if (sisusb_write_memio_long(sisusb,
2741                                                         SISUSB_TYPE_IO,
2742                                                         address, buf32))
2743                                         errno = -EIO;
2744                                 else
2745                                         bytes_written = 4;
2746
2747                                 break;
2748
2749                         default:
2750                                 errno = -EIO;
2751                 }
2752
2753         } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2754                    (*ppos) <  SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2755
2756                 address = (*ppos) -
2757                         SISUSB_PCI_PSEUDO_MEMBASE +
2758                         SISUSB_PCI_MEMBASE;
2759
2760                 /* Write video ram.
2761                  * Buffer is copied 1:1, therefore, on big-endian
2762                  * machines, the data must be swapped by userland
2763                  * in advance (if applicable; no swapping in 8bpp
2764                  * mode or if YUV data is being transferred).
2765                  */
2766                 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2767                                         count, buffer, 0, &bytes_written);
2768
2769                 if (bytes_written)
2770                         errno = bytes_written;
2771
2772         } else  if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2773                     (*ppos) <  SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) {
2774
2775                 address = (*ppos) -
2776                         SISUSB_PCI_PSEUDO_MMIOBASE +
2777                         SISUSB_PCI_MMIOBASE;
2778
2779                 /* Write MMIO.
2780                  * Buffer is copied 1:1, therefore, on big-endian
2781                  * machines, the data must be swapped by userland
2782                  * in advance.
2783                  */
2784                 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2785                                         count, buffer, 0, &bytes_written);
2786
2787                 if (bytes_written)
2788                         errno = bytes_written;
2789
2790         } else  if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2791                     (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + SISUSB_PCI_PCONFSIZE) {
2792
2793                 if (count != 4) {
2794                         mutex_unlock(&sisusb->lock);
2795                         return -EINVAL;
2796                 }
2797
2798                 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2799
2800                 /* Write PCI config register.
2801                  * Given value expected in machine endianness.
2802                  */
2803                 if (get_user(buf32, (u32 __user *)buffer))
2804                         errno = -EFAULT;
2805                 else if (sisusb_write_pci_config(sisusb, address, buf32))
2806                         errno = -EIO;
2807                 else
2808                         bytes_written = 4;
2809
2810
2811         } else {
2812
2813                 /* Error */
2814                 errno = -EBADFD;
2815
2816         }
2817
2818         (*ppos) += bytes_written;
2819
2820         mutex_unlock(&sisusb->lock);
2821
2822         return errno ? errno : bytes_written;
2823 }
2824
2825 static loff_t
2826 sisusb_lseek(struct file *file, loff_t offset, int orig)
2827 {
2828         struct sisusb_usb_data *sisusb;
2829         loff_t ret;
2830
2831         if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2832                 return -ENODEV;
2833
2834         mutex_lock(&sisusb->lock);
2835
2836         /* Sanity check */
2837         if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2838                 mutex_unlock(&sisusb->lock);
2839                 return -ENODEV;
2840         }
2841
2842         switch (orig) {
2843                 case 0:
2844                         file->f_pos = offset;
2845                         ret = file->f_pos;
2846                         /* never negative, no force_successful_syscall needed */
2847                         break;
2848                 case 1:
2849                         file->f_pos += offset;
2850                         ret = file->f_pos;
2851                         /* never negative, no force_successful_syscall needed */
2852                         break;
2853                 default:
2854                         /* seeking relative to "end of file" is not supported */
2855                         ret = -EINVAL;
2856         }
2857
2858         mutex_unlock(&sisusb->lock);
2859         return ret;
2860 }
2861
2862 static int
2863 sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
2864                                                         unsigned long arg)
2865 {
2866         int     retval, port, length;
2867         u32     address;
2868
2869         /* All our commands require the device
2870          * to be initialized.
2871          */
2872         if (!sisusb->devinit)
2873                 return -ENODEV;
2874
2875         port = y->data3 -
2876                 SISUSB_PCI_PSEUDO_IOPORTBASE +
2877                 SISUSB_PCI_IOPORTBASE;
2878
2879         switch (y->operation) {
2880                 case SUCMD_GET:
2881                         retval = sisusb_getidxreg(sisusb, port,
2882                                                          y->data0, &y->data1);
2883                         if (!retval) {
2884                                 if (copy_to_user((void __user *)arg, y,
2885                                                         sizeof(*y)))
2886                                         retval = -EFAULT;
2887                         }
2888                         break;
2889
2890                 case SUCMD_SET:
2891                         retval = sisusb_setidxreg(sisusb, port,
2892                                                 y->data0, y->data1);
2893                         break;
2894
2895                 case SUCMD_SETOR:
2896                         retval = sisusb_setidxregor(sisusb, port,
2897                                                 y->data0, y->data1);
2898                         break;
2899
2900                 case SUCMD_SETAND:
2901                         retval = sisusb_setidxregand(sisusb, port,
2902                                                 y->data0, y->data1);
2903                         break;
2904
2905                 case SUCMD_SETANDOR:
2906                         retval = sisusb_setidxregandor(sisusb, port,
2907                                                 y->data0, y->data1, y->data2);
2908                         break;
2909
2910                 case SUCMD_SETMASK:
2911                         retval = sisusb_setidxregmask(sisusb, port,
2912                                                 y->data0, y->data1, y->data2);
2913                         break;
2914
2915                 case SUCMD_CLRSCR:
2916                         /* Gfx core must be initialized */
2917                         if (!sisusb->gfxinit)
2918                                 return -ENODEV;
2919
2920                         length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
2921                         address = y->data3 -
2922                                 SISUSB_PCI_PSEUDO_MEMBASE +
2923                                 SISUSB_PCI_MEMBASE;
2924                         retval = sisusb_clear_vram(sisusb, address, length);
2925                         break;
2926
2927                 case SUCMD_HANDLETEXTMODE:
2928                         retval = 0;
2929 #ifdef INCL_SISUSB_CON
2930                         /* Gfx core must be initialized, SiS_Pr must exist */
2931                         if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2932                                 return -ENODEV;
2933
2934                         switch (y->data0) {
2935                         case 0:
2936                                 retval = sisusb_reset_text_mode(sisusb, 0);
2937                                 break;
2938                         case 1:
2939                                 sisusb->textmodedestroyed = 1;
2940                                 break;
2941                         }
2942 #endif
2943                         break;
2944
2945 #ifdef INCL_SISUSB_CON
2946                 case SUCMD_SETMODE:
2947                         /* Gfx core must be initialized, SiS_Pr must exist */
2948                         if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2949                                 return -ENODEV;
2950
2951                         retval = 0;
2952
2953                         sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2954                         sisusb->SiS_Pr->sisusb = (void *)sisusb;
2955
2956                         if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
2957                                 retval = -EINVAL;
2958
2959                         break;
2960
2961                 case SUCMD_SETVESAMODE:
2962                         /* Gfx core must be initialized, SiS_Pr must exist */
2963                         if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2964                                 return -ENODEV;
2965
2966                         retval = 0;
2967
2968                         sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2969                         sisusb->SiS_Pr->sisusb = (void *)sisusb;
2970
2971                         if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
2972                                 retval = -EINVAL;
2973
2974                         break;
2975 #endif
2976
2977                 default:
2978                         retval = -EINVAL;
2979         }
2980
2981         if (retval > 0)
2982                 retval = -EIO;
2983
2984         return retval;
2985 }
2986
2987 static int
2988 sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
2989                                                         unsigned long arg)
2990 {
2991         struct sisusb_usb_data *sisusb;
2992         struct sisusb_info x;
2993         struct sisusb_command y;
2994         int     retval = 0;
2995         u32 __user *argp = (u32 __user *)arg;
2996
2997         if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2998                 return -ENODEV;
2999
3000         mutex_lock(&sisusb->lock);
3001
3002         /* Sanity check */
3003         if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
3004                 retval = -ENODEV;
3005                 goto err_out;
3006         }
3007
3008         switch (cmd) {
3009
3010                 case SISUSB_GET_CONFIG_SIZE:
3011
3012                         if (put_user(sizeof(x), argp))
3013                                 retval = -EFAULT;
3014
3015                         break;
3016
3017                 case SISUSB_GET_CONFIG:
3018
3019                         x.sisusb_id         = SISUSB_ID;
3020                         x.sisusb_version    = SISUSB_VERSION;
3021                         x.sisusb_revision   = SISUSB_REVISION;
3022                         x.sisusb_patchlevel = SISUSB_PATCHLEVEL;
3023                         x.sisusb_gfxinit    = sisusb->gfxinit;
3024                         x.sisusb_vrambase   = SISUSB_PCI_PSEUDO_MEMBASE;
3025                         x.sisusb_mmiobase   = SISUSB_PCI_PSEUDO_MMIOBASE;
3026                         x.sisusb_iobase     = SISUSB_PCI_PSEUDO_IOPORTBASE;
3027                         x.sisusb_pcibase    = SISUSB_PCI_PSEUDO_PCIBASE;
3028                         x.sisusb_vramsize   = sisusb->vramsize;
3029                         x.sisusb_minor      = sisusb->minor;
3030                         x.sisusb_fbdevactive= 0;
3031 #ifdef INCL_SISUSB_CON
3032                         x.sisusb_conactive  = sisusb->haveconsole ? 1 : 0;
3033 #else
3034                         x.sisusb_conactive  = 0;
3035 #endif
3036
3037                         if (copy_to_user((void __user *)arg, &x, sizeof(x)))
3038                                 retval = -EFAULT;
3039
3040                         break;
3041
3042                 case SISUSB_COMMAND:
3043
3044                         if (copy_from_user(&y, (void __user *)arg, sizeof(y)))
3045                                 retval = -EFAULT;
3046                         else
3047                                 retval = sisusb_handle_command(sisusb, &y, arg);
3048
3049                         break;
3050
3051                 default:
3052                         retval = -ENOTTY;
3053                         break;
3054         }
3055
3056 err_out:
3057         mutex_unlock(&sisusb->lock);
3058         return retval;
3059 }
3060
3061 #ifdef SISUSB_NEW_CONFIG_COMPAT
3062 static long
3063 sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
3064 {
3065         long retval;
3066
3067         switch (cmd) {
3068                 case SISUSB_GET_CONFIG_SIZE:
3069                 case SISUSB_GET_CONFIG:
3070                 case SISUSB_COMMAND:
3071                         lock_kernel();
3072                         retval = sisusb_ioctl(f->f_path.dentry->d_inode, f, cmd, arg);
3073                         unlock_kernel();
3074                         return retval;
3075
3076                 default:
3077                         return -ENOIOCTLCMD;
3078         }
3079 }
3080 #endif
3081
3082 static const struct file_operations usb_sisusb_fops = {
3083         .owner =        THIS_MODULE,
3084         .open =         sisusb_open,
3085         .release =      sisusb_release,
3086         .read =         sisusb_read,
3087         .write =        sisusb_write,
3088         .llseek =       sisusb_lseek,
3089 #ifdef SISUSB_NEW_CONFIG_COMPAT
3090         .compat_ioctl = sisusb_compat_ioctl,
3091 #endif
3092         .ioctl =        sisusb_ioctl
3093 };
3094
3095 static struct usb_class_driver usb_sisusb_class = {
3096         .name =         "sisusbvga%d",
3097         .fops =         &usb_sisusb_fops,
3098         .minor_base =   SISUSB_MINOR
3099 };
3100
3101 static int sisusb_probe(struct usb_interface *intf,
3102                         const struct usb_device_id *id)
3103 {
3104         struct usb_device *dev = interface_to_usbdev(intf);
3105         struct sisusb_usb_data *sisusb;
3106         int retval = 0, i;
3107
3108         dev_info(&dev->dev, "USB2VGA dongle found at address %d\n",
3109                 dev->devnum);
3110
3111         /* Allocate memory for our private */
3112         if (!(sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL))) {
3113                 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for private data\n");
3114                 return -ENOMEM;
3115         }
3116         kref_init(&sisusb->kref);
3117
3118         mutex_init(&(sisusb->lock));
3119
3120         /* Register device */
3121         if ((retval = usb_register_dev(intf, &usb_sisusb_class))) {
3122                 dev_err(&sisusb->sisusb_dev->dev, "Failed to get a minor for device %d\n",
3123                         dev->devnum);
3124                 retval = -ENODEV;
3125                 goto error_1;
3126         }
3127
3128         sisusb->sisusb_dev = dev;
3129         sisusb->minor      = intf->minor;
3130         sisusb->vrambase   = SISUSB_PCI_MEMBASE;
3131         sisusb->mmiobase   = SISUSB_PCI_MMIOBASE;
3132         sisusb->mmiosize   = SISUSB_PCI_MMIOSIZE;
3133         sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
3134         /* Everything else is zero */
3135
3136         /* Allocate buffers */
3137         sisusb->ibufsize = SISUSB_IBUF_SIZE;
3138         if (!(sisusb->ibuf = usb_buffer_alloc(dev, SISUSB_IBUF_SIZE,
3139                                         GFP_KERNEL, &sisusb->transfer_dma_in))) {
3140                 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for input buffer");
3141                 retval = -ENOMEM;
3142                 goto error_2;
3143         }
3144
3145         sisusb->numobufs = 0;
3146         sisusb->obufsize = SISUSB_OBUF_SIZE;
3147         for (i = 0; i < NUMOBUFS; i++) {
3148                 if (!(sisusb->obuf[i] = usb_buffer_alloc(dev, SISUSB_OBUF_SIZE,
3149                                         GFP_KERNEL,
3150                                         &sisusb->transfer_dma_out[i]))) {
3151                         if (i == 0) {
3152                                 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for output buffer\n");
3153                                 retval = -ENOMEM;
3154                                 goto error_3;
3155                         }
3156                         break;
3157                 } else
3158                         sisusb->numobufs++;
3159
3160         }
3161
3162         /* Allocate URBs */
3163         if (!(sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL))) {
3164                 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n");
3165                 retval = -ENOMEM;
3166                 goto error_3;
3167         }
3168         sisusb->completein = 1;
3169
3170         for (i = 0; i < sisusb->numobufs; i++) {
3171                 if (!(sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL))) {
3172                         dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n");
3173                         retval = -ENOMEM;
3174                         goto error_4;
3175                 }
3176                 sisusb->urbout_context[i].sisusb = (void *)sisusb;
3177                 sisusb->urbout_context[i].urbindex = i;
3178                 sisusb->urbstatus[i] = 0;
3179         }
3180
3181         dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n", sisusb->numobufs);
3182
3183 #ifdef INCL_SISUSB_CON
3184         /* Allocate our SiS_Pr */
3185         if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) {
3186                 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate SiS_Pr\n");
3187         }
3188 #endif
3189
3190         /* Do remaining init stuff */
3191
3192         init_waitqueue_head(&sisusb->wait_q);
3193
3194         usb_set_intfdata(intf, sisusb);
3195
3196         usb_get_dev(sisusb->sisusb_dev);
3197
3198         sisusb->present = 1;
3199
3200 #ifdef SISUSB_OLD_CONFIG_COMPAT
3201         {
3202         int ret;
3203         /* Our ioctls are all "32/64bit compatible" */
3204         ret =  register_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE, NULL);
3205         ret |= register_ioctl32_conversion(SISUSB_GET_CONFIG,      NULL);
3206         ret |= register_ioctl32_conversion(SISUSB_COMMAND,         NULL);
3207         if (ret)
3208                 dev_err(&sisusb->sisusb_dev->dev, "Error registering ioctl32 translations\n");
3209         else
3210                 sisusb->ioctl32registered = 1;
3211         }
3212 #endif
3213
3214         if (dev->speed == USB_SPEED_HIGH) {
3215                 int initscreen = 1;
3216 #ifdef INCL_SISUSB_CON
3217                 if (sisusb_first_vc > 0 &&
3218                     sisusb_last_vc > 0 &&
3219                     sisusb_first_vc <= sisusb_last_vc &&
3220                     sisusb_last_vc <= MAX_NR_CONSOLES)
3221                         initscreen = 0;
3222 #endif
3223                 if (sisusb_init_gfxdevice(sisusb, initscreen))
3224                         dev_err(&sisusb->sisusb_dev->dev, "Failed to early initialize device\n");
3225
3226         } else
3227                 dev_info(&sisusb->sisusb_dev->dev, "Not attached to USB 2.0 hub, deferring init\n");
3228
3229         sisusb->ready = 1;
3230
3231 #ifdef SISUSBENDIANTEST
3232         dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST ***\n");
3233         sisusb_testreadwrite(sisusb);
3234         dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST END ***\n");
3235 #endif
3236
3237 #ifdef INCL_SISUSB_CON
3238         sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
3239 #endif
3240
3241         return 0;
3242
3243 error_4:
3244         sisusb_free_urbs(sisusb);
3245 error_3:
3246         sisusb_free_buffers(sisusb);
3247 error_2:
3248         usb_deregister_dev(intf, &usb_sisusb_class);
3249 error_1:
3250         kfree(sisusb);
3251         return retval;
3252 }
3253
3254 static void sisusb_disconnect(struct usb_interface *intf)
3255 {
3256         struct sisusb_usb_data *sisusb;
3257
3258         /* This should *not* happen */
3259         if (!(sisusb = usb_get_intfdata(intf)))
3260                 return;
3261
3262 #ifdef INCL_SISUSB_CON
3263         sisusb_console_exit(sisusb);
3264 #endif
3265
3266         usb_deregister_dev(intf, &usb_sisusb_class);
3267
3268         mutex_lock(&sisusb->lock);
3269
3270         /* Wait for all URBs to complete and kill them in case (MUST do) */
3271         if (!sisusb_wait_all_out_complete(sisusb))
3272                 sisusb_kill_all_busy(sisusb);
3273
3274         usb_set_intfdata(intf, NULL);
3275
3276 #ifdef SISUSB_OLD_CONFIG_COMPAT
3277         if (sisusb->ioctl32registered) {
3278                 int ret;
3279                 sisusb->ioctl32registered = 0;
3280                 ret =  unregister_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE);
3281                 ret |= unregister_ioctl32_conversion(SISUSB_GET_CONFIG);
3282                 ret |= unregister_ioctl32_conversion(SISUSB_COMMAND);
3283                 if (ret) {
3284                         dev_err(&sisusb->sisusb_dev->dev, "Error unregistering ioctl32 translations\n");
3285                 }
3286         }
3287 #endif
3288
3289         sisusb->present = 0;
3290         sisusb->ready = 0;
3291
3292         mutex_unlock(&sisusb->lock);
3293
3294         /* decrement our usage count */
3295         kref_put(&sisusb->kref, sisusb_delete);
3296
3297         dev_info(&sisusb->sisusb_dev->dev, "Disconnected\n");
3298 }
3299
3300 static struct usb_device_id sisusb_table [] = {
3301         { USB_DEVICE(0x0711, 0x0550) },
3302         { USB_DEVICE(0x0711, 0x0900) },
3303         { USB_DEVICE(0x0711, 0x0901) },
3304         { USB_DEVICE(0x0711, 0x0902) },
3305         { USB_DEVICE(0x182d, 0x021c) },
3306         { USB_DEVICE(0x182d, 0x0269) },
3307         { }
3308 };
3309
3310 MODULE_DEVICE_TABLE (usb, sisusb_table);
3311
3312 static struct usb_driver sisusb_driver = {
3313         .name =         "sisusb",
3314         .probe =        sisusb_probe,
3315         .disconnect =   sisusb_disconnect,
3316         .id_table =     sisusb_table,
3317 };
3318
3319 static int __init usb_sisusb_init(void)
3320 {
3321         int retval;
3322         struct sisusb_usb_data *sisusb;
3323
3324 #ifdef INCL_SISUSB_CON
3325         sisusb_init_concode();
3326 #endif
3327
3328         if (!(retval = usb_register(&sisusb_driver))) {
3329
3330                 dev_info(&sisusb->sisusb_dev->dev, "Driver version %d.%d.%d\n", SISUSB_VERSION,
3331                                 SISUSB_REVISION, SISUSB_PATCHLEVEL);
3332                 dev_info(&sisusb->sisusb_dev->dev, "sisusb: Copyright (C) 2005 Thomas Winischhofer\n");
3333
3334         }
3335
3336         return retval;
3337 }
3338
3339 static void __exit usb_sisusb_exit(void)
3340 {
3341         usb_deregister(&sisusb_driver);
3342 }
3343
3344 module_init(usb_sisusb_init);
3345 module_exit(usb_sisusb_exit);
3346
3347 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3348 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3349 MODULE_LICENSE("GPL");
3350