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