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