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