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