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