Version:  2.0.40 2.2.26 2.4.37 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8

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

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us