Version:  2.0.40 2.2.26 2.4.37 3.10 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

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, size_t *bytes_written)
1289 {
1290         return sisusb_write_mem_bulk(sisusb, dest, src, length,
1291                         NULL, 0, bytes_written);
1292 }
1293 
1294 #ifdef SISUSBENDIANTEST
1295 int sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
1296                 u32 src, int length, size_t *bytes_written)
1297 {
1298         return sisusb_read_mem_bulk(sisusb, src, dest, length,
1299                         NULL, bytes_written);
1300 }
1301 #endif
1302 #endif
1303 
1304 #ifdef SISUSBENDIANTEST
1305 static void sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
1306 {
1307         static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1308         char destbuffer[10];
1309         size_t dummy;
1310         int i, j;
1311 
1312         sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy);
1313 
1314         for (i = 1; i <= 7; i++) {
1315                 dev_dbg(&sisusb->sisusb_dev->dev,
1316                                 "sisusb: rwtest %d bytes\n", i);
1317                 sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase,
1318                                 i, &dummy);
1319                 for (j = 0; j < i; j++) {
1320                         dev_dbg(&sisusb->sisusb_dev->dev,
1321                                         "rwtest read[%d] = %x\n",
1322                                         j, destbuffer[j]);
1323                 }
1324         }
1325 }
1326 #endif
1327 
1328 /* access pci config registers (reg numbers 0, 4, 8, etc) */
1329 
1330 static int sisusb_write_pci_config(struct sisusb_usb_data *sisusb,
1331                 int regnum, u32 data)
1332 {
1333         struct sisusb_packet packet;
1334         int ret;
1335 
1336         packet.header = 0x008f;
1337         packet.address = regnum | 0x10000;
1338         packet.data = data;
1339         ret = sisusb_send_packet(sisusb, 10, &packet);
1340         return ret;
1341 }
1342 
1343 static int sisusb_read_pci_config(struct sisusb_usb_data *sisusb,
1344                 int regnum, u32 *data)
1345 {
1346         struct sisusb_packet packet;
1347         int ret;
1348 
1349         packet.header = 0x008f;
1350         packet.address = (u32)regnum | 0x10000;
1351         ret = sisusb_send_packet(sisusb, 6, &packet);
1352         *data = packet.data;
1353         return ret;
1354 }
1355 
1356 /* Clear video RAM */
1357 
1358 static int sisusb_clear_vram(struct sisusb_usb_data *sisusb,
1359                 u32 address, int length)
1360 {
1361         int ret, i;
1362         ssize_t j;
1363 
1364         if (address < sisusb->vrambase)
1365                 return 1;
1366 
1367         if (address >= sisusb->vrambase + sisusb->vramsize)
1368                 return 1;
1369 
1370         if (address + length > sisusb->vrambase + sisusb->vramsize)
1371                 length = sisusb->vrambase + sisusb->vramsize - address;
1372 
1373         if (length <= 0)
1374                 return 0;
1375 
1376         /* allocate free buffer/urb and clear the buffer */
1377         i = sisusb_alloc_outbuf(sisusb);
1378         if (i < 0)
1379                 return -EBUSY;
1380 
1381         memset(sisusb->obuf[i], 0, sisusb->obufsize);
1382 
1383         /* We can write a length > buffer size here. The buffer
1384          * data will simply be re-used (like a ring-buffer).
1385          */
1386         ret = sisusb_write_mem_bulk(sisusb, address, NULL, length, NULL, i, &j);
1387 
1388         /* Free the buffer/urb */
1389         sisusb_free_outbuf(sisusb, i);
1390 
1391         return ret;
1392 }
1393 
1394 /* Initialize the graphics core (return 0 on success)
1395  * This resets the graphics hardware and puts it into
1396  * a defined mode (640x480@60Hz)
1397  */
1398 
1399 #define GETREG(r, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1400 #define SETREG(r, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1401 #define SETIREG(r, i, d) sisusb_setidxreg(sisusb, r, i, d)
1402 #define GETIREG(r, i, d) sisusb_getidxreg(sisusb, r, i, d)
1403 #define SETIREGOR(r, i, o) sisusb_setidxregor(sisusb, r, i, o)
1404 #define SETIREGAND(r, i, a) sisusb_setidxregand(sisusb, r, i, a)
1405 #define SETIREGANDOR(r, i, a, o) sisusb_setidxregandor(sisusb, r, i, a, o)
1406 #define READL(a, d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1407 #define WRITEL(a, d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1408 #define READB(a, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1409 #define WRITEB(a, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1410 
1411 static int sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype)
1412 {
1413         int ret;
1414         u8 tmp8;
1415 
1416         ret = GETIREG(SISSR, 0x16, &tmp8);
1417         if (ramtype <= 1) {
1418                 tmp8 &= 0x3f;
1419                 ret |= SETIREG(SISSR, 0x16, tmp8);
1420                 tmp8 |= 0x80;
1421                 ret |= SETIREG(SISSR, 0x16, tmp8);
1422         } else {
1423                 tmp8 |= 0xc0;
1424                 ret |= SETIREG(SISSR, 0x16, tmp8);
1425                 tmp8 &= 0x0f;
1426                 ret |= SETIREG(SISSR, 0x16, tmp8);
1427                 tmp8 |= 0x80;
1428                 ret |= SETIREG(SISSR, 0x16, tmp8);
1429                 tmp8 &= 0x0f;
1430                 ret |= SETIREG(SISSR, 0x16, tmp8);
1431                 tmp8 |= 0xd0;
1432                 ret |= SETIREG(SISSR, 0x16, tmp8);
1433                 tmp8 &= 0x0f;
1434                 ret |= SETIREG(SISSR, 0x16, tmp8);
1435                 tmp8 |= 0xa0;
1436                 ret |= SETIREG(SISSR, 0x16, tmp8);
1437         }
1438         return ret;
1439 }
1440 
1441 static int sisusb_getbuswidth(struct sisusb_usb_data *sisusb,
1442                 int *bw, int *chab)
1443 {
1444         int ret;
1445         u8  ramtype, done = 0;
1446         u32 t0, t1, t2, t3;
1447         u32 ramptr = SISUSB_PCI_MEMBASE;
1448 
1449         ret = GETIREG(SISSR, 0x3a, &ramtype);
1450         ramtype &= 3;
1451 
1452         ret |= SETIREG(SISSR, 0x13, 0x00);
1453 
1454         if (ramtype <= 1) {
1455                 ret |= SETIREG(SISSR, 0x14, 0x12);
1456                 ret |= SETIREGAND(SISSR, 0x15, 0xef);
1457         } else {
1458                 ret |= SETIREG(SISSR, 0x14, 0x02);
1459         }
1460 
1461         ret |= sisusb_triggersr16(sisusb, ramtype);
1462         ret |= WRITEL(ramptr +  0, 0x01234567);
1463         ret |= WRITEL(ramptr +  4, 0x456789ab);
1464         ret |= WRITEL(ramptr +  8, 0x89abcdef);
1465         ret |= WRITEL(ramptr + 12, 0xcdef0123);
1466         ret |= WRITEL(ramptr + 16, 0x55555555);
1467         ret |= WRITEL(ramptr + 20, 0x55555555);
1468         ret |= WRITEL(ramptr + 24, 0xffffffff);
1469         ret |= WRITEL(ramptr + 28, 0xffffffff);
1470         ret |= READL(ramptr +  0, &t0);
1471         ret |= READL(ramptr +  4, &t1);
1472         ret |= READL(ramptr +  8, &t2);
1473         ret |= READL(ramptr + 12, &t3);
1474 
1475         if (ramtype <= 1) {
1476 
1477                 *chab = 0; *bw = 64;
1478 
1479                 if ((t3 != 0xcdef0123) || (t2 != 0x89abcdef)) {
1480                         if ((t1 == 0x456789ab) && (t0 == 0x01234567)) {
1481                                 *chab = 0; *bw = 64;
1482                                 ret |= SETIREGAND(SISSR, 0x14, 0xfd);
1483                         }
1484                 }
1485                 if ((t1 != 0x456789ab) || (t0 != 0x01234567)) {
1486                         *chab = 1; *bw = 64;
1487                         ret |= SETIREGANDOR(SISSR, 0x14, 0xfc, 0x01);
1488 
1489                         ret |= sisusb_triggersr16(sisusb, ramtype);
1490                         ret |= WRITEL(ramptr +  0, 0x89abcdef);
1491                         ret |= WRITEL(ramptr +  4, 0xcdef0123);
1492                         ret |= WRITEL(ramptr +  8, 0x55555555);
1493                         ret |= WRITEL(ramptr + 12, 0x55555555);
1494                         ret |= WRITEL(ramptr + 16, 0xaaaaaaaa);
1495                         ret |= WRITEL(ramptr + 20, 0xaaaaaaaa);
1496                         ret |= READL(ramptr +  4, &t1);
1497 
1498                         if (t1 != 0xcdef0123) {
1499                                 *bw = 32;
1500                                 ret |= SETIREGOR(SISSR, 0x15, 0x10);
1501                         }
1502                 }
1503 
1504         } else {
1505 
1506                 *chab = 0; *bw = 64;    /* default: cha, bw = 64 */
1507 
1508                 done = 0;
1509 
1510                 if (t1 == 0x456789ab) {
1511                         if (t0 == 0x01234567) {
1512                                 *chab = 0; *bw = 64;
1513                                 done = 1;
1514                         }
1515                 } else {
1516                         if (t0 == 0x01234567) {
1517                                 *chab = 0; *bw = 32;
1518                                 ret |= SETIREG(SISSR, 0x14, 0x00);
1519                                 done = 1;
1520                         }
1521                 }
1522 
1523                 if (!done) {
1524                         ret |= SETIREG(SISSR, 0x14, 0x03);
1525                         ret |= sisusb_triggersr16(sisusb, ramtype);
1526 
1527                         ret |= WRITEL(ramptr +  0, 0x01234567);
1528                         ret |= WRITEL(ramptr +  4, 0x456789ab);
1529                         ret |= WRITEL(ramptr +  8, 0x89abcdef);
1530                         ret |= WRITEL(ramptr + 12, 0xcdef0123);
1531                         ret |= WRITEL(ramptr + 16, 0x55555555);
1532                         ret |= WRITEL(ramptr + 20, 0x55555555);
1533                         ret |= WRITEL(ramptr + 24, 0xffffffff);
1534                         ret |= WRITEL(ramptr + 28, 0xffffffff);
1535                         ret |= READL(ramptr +  0, &t0);
1536                         ret |= READL(ramptr +  4, &t1);
1537 
1538                         if (t1 == 0x456789ab) {
1539                                 if (t0 == 0x01234567) {
1540                                         *chab = 1; *bw = 64;
1541                                         return ret;
1542                                 } /* else error */
1543                         } else {
1544                                 if (t0 == 0x01234567) {
1545                                         *chab = 1; *bw = 32;
1546                                         ret |= SETIREG(SISSR, 0x14, 0x01);
1547                                 } /* else error */
1548                         }
1549                 }
1550         }
1551         return ret;
1552 }
1553 
1554 static int sisusb_verify_mclk(struct sisusb_usb_data *sisusb)
1555 {
1556         int ret = 0;
1557         u32 ramptr = SISUSB_PCI_MEMBASE;
1558         u8 tmp1, tmp2, i, j;
1559 
1560         ret |= WRITEB(ramptr, 0xaa);
1561         ret |= WRITEB(ramptr + 16, 0x55);
1562         ret |= READB(ramptr, &tmp1);
1563         ret |= READB(ramptr + 16, &tmp2);
1564         if ((tmp1 != 0xaa) || (tmp2 != 0x55)) {
1565                 for (i = 0, j = 16; i < 2; i++, j += 16) {
1566                         ret |= GETIREG(SISSR, 0x21, &tmp1);
1567                         ret |= SETIREGAND(SISSR, 0x21, (tmp1 & 0xfb));
1568                         ret |= SETIREGOR(SISSR, 0x3c, 0x01);  /* not on 330 */
1569                         ret |= SETIREGAND(SISSR, 0x3c, 0xfe); /* not on 330 */
1570                         ret |= SETIREG(SISSR, 0x21, tmp1);
1571                         ret |= WRITEB(ramptr + 16 + j, j);
1572                         ret |= READB(ramptr + 16 + j, &tmp1);
1573                         if (tmp1 == j) {
1574                                 ret |= WRITEB(ramptr + j, j);
1575                                 break;
1576                         }
1577                 }
1578         }
1579         return ret;
1580 }
1581 
1582 static int sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret,
1583                 int index, u8 rankno, u8 chab, const u8 dramtype[][5], int bw)
1584 {
1585         int ret = 0, ranksize;
1586         u8 tmp;
1587 
1588         *iret = 0;
1589 
1590         if ((rankno == 2) && (dramtype[index][0] == 2))
1591                 return ret;
1592 
1593         ranksize = dramtype[index][3] / 2 * bw / 32;
1594 
1595         if ((ranksize * rankno) > 128)
1596                 return ret;
1597 
1598         tmp = 0;
1599         while ((ranksize >>= 1) > 0)
1600                 tmp += 0x10;
1601 
1602         tmp |= ((rankno - 1) << 2);
1603         tmp |= ((bw / 64) & 0x02);
1604         tmp |= (chab & 0x01);
1605 
1606         ret = SETIREG(SISSR, 0x14, tmp);
1607         ret |= sisusb_triggersr16(sisusb, 0); /* sic! */
1608 
1609         *iret = 1;
1610 
1611         return ret;
1612 }
1613 
1614 static int sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret,
1615                 u32 inc, int testn)
1616 {
1617         int ret = 0, i;
1618         u32 j, tmp;
1619 
1620         *iret = 0;
1621 
1622         for (i = 0, j = 0; i < testn; i++) {
1623                 ret |= WRITEL(sisusb->vrambase + j, j);
1624                 j += inc;
1625         }
1626 
1627         for (i = 0, j = 0; i < testn; i++) {
1628                 ret |= READL(sisusb->vrambase + j, &tmp);
1629                 if (tmp != j)
1630                         return ret;
1631 
1632                 j += inc;
1633         }
1634 
1635         *iret = 1;
1636         return ret;
1637 }
1638 
1639 static int sisusb_check_ranks(struct sisusb_usb_data *sisusb,
1640                 int *iret, int rankno, int idx, int bw, const u8 rtype[][5])
1641 {
1642         int ret = 0, i, i2ret;
1643         u32 inc;
1644 
1645         *iret = 0;
1646 
1647         for (i = rankno; i >= 1; i--) {
1648                 inc = 1 << (rtype[idx][2] + rtype[idx][1] + rtype[idx][0] +
1649                                 bw / 64 + i);
1650                 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1651                 if (!i2ret)
1652                         return ret;
1653         }
1654 
1655         inc = 1 << (rtype[idx][2] + bw / 64 + 2);
1656         ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 4);
1657         if (!i2ret)
1658                 return ret;
1659 
1660         inc = 1 << (10 + bw / 64);
1661         ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1662         if (!i2ret)
1663                 return ret;
1664 
1665         *iret = 1;
1666         return ret;
1667 }
1668 
1669 static int sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret,
1670                 int bw, int chab)
1671 {
1672         int ret = 0, i2ret = 0, i, j;
1673         static const u8 sdramtype[13][5] = {
1674                 { 2, 12, 9, 64, 0x35 },
1675                 { 1, 13, 9, 64, 0x44 },
1676                 { 2, 12, 8, 32, 0x31 },
1677                 { 2, 11, 9, 32, 0x25 },
1678                 { 1, 12, 9, 32, 0x34 },
1679                 { 1, 13, 8, 32, 0x40 },
1680                 { 2, 11, 8, 16, 0x21 },
1681                 { 1, 12, 8, 16, 0x30 },
1682                 { 1, 11, 9, 16, 0x24 },
1683                 { 1, 11, 8,  8, 0x20 },
1684                 { 2,  9, 8,  4, 0x01 },
1685                 { 1, 10, 8,  4, 0x10 },
1686                 { 1,  9, 8,  2, 0x00 }
1687         };
1688 
1689         *iret = 1; /* error */
1690 
1691         for (i = 0; i < 13; i++) {
1692                 ret |= SETIREGANDOR(SISSR, 0x13, 0x80, sdramtype[i][4]);
1693                 for (j = 2; j > 0; j--) {
1694                         ret |= sisusb_set_rank(sisusb, &i2ret, i, j, chab,
1695                                         sdramtype, bw);
1696                         if (!i2ret)
1697                                 continue;
1698 
1699                         ret |= sisusb_check_ranks(sisusb, &i2ret, j, i, bw,
1700                                         sdramtype);
1701                         if (i2ret) {
1702                                 *iret = 0;      /* ram size found */
1703                                 return ret;
1704                         }
1705                 }
1706         }
1707 
1708         return ret;
1709 }
1710 
1711 static int sisusb_setup_screen(struct sisusb_usb_data *sisusb,
1712                 int clrall, int drwfr)
1713 {
1714         int ret = 0;
1715         u32 address;
1716         int i, length, modex, modey, bpp;
1717 
1718         modex = 640; modey = 480; bpp = 2;
1719 
1720         address = sisusb->vrambase;     /* Clear video ram */
1721 
1722         if (clrall)
1723                 length = sisusb->vramsize;
1724         else
1725                 length = modex * bpp * modey;
1726 
1727         ret = sisusb_clear_vram(sisusb, address, length);
1728 
1729         if (!ret && drwfr) {
1730                 for (i = 0; i < modex; i++) {
1731                         address = sisusb->vrambase + (i * bpp);
1732                         ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1733                                         address, 0xf100);
1734                         address += (modex * (modey-1) * bpp);
1735                         ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1736                                         address, 0xf100);
1737                 }
1738                 for (i = 0; i < modey; i++) {
1739                         address = sisusb->vrambase + ((i * modex) * bpp);
1740                         ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1741                                         address, 0xf100);
1742                         address += ((modex - 1) * bpp);
1743                         ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1744                                         address, 0xf100);
1745                 }
1746         }
1747 
1748         return ret;
1749 }
1750 
1751 static int sisusb_set_default_mode(struct sisusb_usb_data *sisusb,
1752                 int touchengines)
1753 {
1754         int ret = 0, i, j, modex, modey, bpp, du;
1755         u8 sr31, cr63, tmp8;
1756         static const char attrdata[] = {
1757                 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1758                 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1759                 0x01, 0x00, 0x00, 0x00
1760         };
1761         static const char crtcrdata[] = {
1762                 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
1763                 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1764                 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3,
1765                 0xff
1766         };
1767         static const char grcdata[] = {
1768                 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
1769                 0xff
1770         };
1771         static const char crtcdata[] = {
1772                 0x5f, 0x4f, 0x4f, 0x83, 0x55, 0x81, 0x0b, 0x3e,
1773                 0xe9, 0x8b, 0xdf, 0xe8, 0x0c, 0x00, 0x00, 0x05,
1774                 0x00
1775         };
1776 
1777         modex = 640; modey = 480; bpp = 2;
1778 
1779         GETIREG(SISSR, 0x31, &sr31);
1780         GETIREG(SISCR, 0x63, &cr63);
1781         SETIREGOR(SISSR, 0x01, 0x20);
1782         SETIREG(SISCR, 0x63, cr63 & 0xbf);
1783         SETIREGOR(SISCR, 0x17, 0x80);
1784         SETIREGOR(SISSR, 0x1f, 0x04);
1785         SETIREGAND(SISSR, 0x07, 0xfb);
1786         SETIREG(SISSR, 0x00, 0x03);     /* seq */
1787         SETIREG(SISSR, 0x01, 0x21);
1788         SETIREG(SISSR, 0x02, 0x0f);
1789         SETIREG(SISSR, 0x03, 0x00);
1790         SETIREG(SISSR, 0x04, 0x0e);
1791         SETREG(SISMISCW, 0x23);         /* misc */
1792         for (i = 0; i <= 0x18; i++) {   /* crtc */
1793                 SETIREG(SISCR, i, crtcrdata[i]);
1794         }
1795         for (i = 0; i <= 0x13; i++) {   /* att */
1796                 GETREG(SISINPSTAT, &tmp8);
1797                 SETREG(SISAR, i);
1798                 SETREG(SISAR, attrdata[i]);
1799         }
1800         GETREG(SISINPSTAT, &tmp8);
1801         SETREG(SISAR, 0x14);
1802         SETREG(SISAR, 0x00);
1803         GETREG(SISINPSTAT, &tmp8);
1804         SETREG(SISAR, 0x20);
1805         GETREG(SISINPSTAT, &tmp8);
1806         for (i = 0; i <= 0x08; i++) {   /* grc */
1807                 SETIREG(SISGR, i, grcdata[i]);
1808         }
1809         SETIREGAND(SISGR, 0x05, 0xbf);
1810         for (i = 0x0A; i <= 0x0E; i++) {        /* clr ext */
1811                 SETIREG(SISSR, i, 0x00);
1812         }
1813         SETIREGAND(SISSR, 0x37, 0xfe);
1814         SETREG(SISMISCW, 0xef);         /* sync */
1815         SETIREG(SISCR, 0x11, 0x00);     /* crtc */
1816         for (j = 0x00, i = 0; i <= 7; i++, j++)
1817                 SETIREG(SISCR, j, crtcdata[i]);
1818 
1819         for (j = 0x10; i <= 10; i++, j++)
1820                 SETIREG(SISCR, j, crtcdata[i]);
1821 
1822         for (j = 0x15; i <= 12; i++, j++)
1823                 SETIREG(SISCR, j, crtcdata[i]);
1824 
1825         for (j = 0x0A; i <= 15; i++, j++)
1826                 SETIREG(SISSR, j, crtcdata[i]);
1827 
1828         SETIREG(SISSR, 0x0E, (crtcdata[16] & 0xE0));
1829         SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5));
1830         SETIREG(SISCR, 0x14, 0x4f);
1831         du = (modex / 16) * (bpp * 2);  /* offset/pitch */
1832         if (modex % 16)
1833                 du += bpp;
1834 
1835         SETIREGANDOR(SISSR, 0x0e, 0xf0, ((du >> 8) & 0x0f));
1836         SETIREG(SISCR, 0x13, (du & 0xff));
1837         du <<= 5;
1838         tmp8 = du >> 8;
1839         if (du & 0xff)
1840                 tmp8++;
1841 
1842         SETIREG(SISSR, 0x10, tmp8);
1843         SETIREG(SISSR, 0x31, 0x00);     /* VCLK */
1844         SETIREG(SISSR, 0x2b, 0x1b);
1845         SETIREG(SISSR, 0x2c, 0xe1);
1846         SETIREG(SISSR, 0x2d, 0x01);
1847         SETIREGAND(SISSR, 0x3d, 0xfe);  /* FIFO */
1848         SETIREG(SISSR, 0x08, 0xae);
1849         SETIREGAND(SISSR, 0x09, 0xf0);
1850         SETIREG(SISSR, 0x08, 0x34);
1851         SETIREGOR(SISSR, 0x3d, 0x01);
1852         SETIREGAND(SISSR, 0x1f, 0x3f);  /* mode regs */
1853         SETIREGANDOR(SISSR, 0x06, 0xc0, 0x0a);
1854         SETIREG(SISCR, 0x19, 0x00);
1855         SETIREGAND(SISCR, 0x1a, 0xfc);
1856         SETIREGAND(SISSR, 0x0f, 0xb7);
1857         SETIREGAND(SISSR, 0x31, 0xfb);
1858         SETIREGANDOR(SISSR, 0x21, 0x1f, 0xa0);
1859         SETIREGAND(SISSR, 0x32, 0xf3);
1860         SETIREGANDOR(SISSR, 0x07, 0xf8, 0x03);
1861         SETIREG(SISCR, 0x52, 0x6c);
1862 
1863         SETIREG(SISCR, 0x0d, 0x00);     /* adjust frame */
1864         SETIREG(SISCR, 0x0c, 0x00);
1865         SETIREG(SISSR, 0x0d, 0x00);
1866         SETIREGAND(SISSR, 0x37, 0xfe);
1867 
1868         SETIREG(SISCR, 0x32, 0x20);
1869         SETIREGAND(SISSR, 0x01, 0xdf);  /* enable display */
1870         SETIREG(SISCR, 0x63, (cr63 & 0xbf));
1871         SETIREG(SISSR, 0x31, (sr31 & 0xfb));
1872 
1873         if (touchengines) {
1874                 SETIREG(SISSR, 0x20, 0xa1);     /* enable engines */
1875                 SETIREGOR(SISSR, 0x1e, 0x5a);
1876 
1877                 SETIREG(SISSR, 0x26, 0x01);     /* disable cmdqueue */
1878                 SETIREG(SISSR, 0x27, 0x1f);
1879                 SETIREG(SISSR, 0x26, 0x00);
1880         }
1881 
1882         SETIREG(SISCR, 0x34, 0x44);     /* we just set std mode #44 */
1883 
1884         return ret;
1885 }
1886 
1887 static int sisusb_init_gfxcore(struct sisusb_usb_data *sisusb)
1888 {
1889         int ret = 0, i, j, bw, chab, iret, retry = 3;
1890         u8 tmp8, ramtype;
1891         u32 tmp32;
1892         static const char mclktable[] = {
1893                 0x3b, 0x22, 0x01, 143,
1894                 0x3b, 0x22, 0x01, 143,
1895                 0x3b, 0x22, 0x01, 143,
1896                 0x3b, 0x22, 0x01, 143
1897         };
1898         static const char eclktable[] = {
1899                 0x3b, 0x22, 0x01, 143,
1900                 0x3b, 0x22, 0x01, 143,
1901                 0x3b, 0x22, 0x01, 143,
1902                 0x3b, 0x22, 0x01, 143
1903         };
1904         static const char ramtypetable1[] = {
1905                 0x00, 0x04, 0x60, 0x60,
1906                 0x0f, 0x0f, 0x1f, 0x1f,
1907                 0xba, 0xba, 0xba, 0xba,
1908                 0xa9, 0xa9, 0xac, 0xac,
1909                 0xa0, 0xa0, 0xa0, 0xa8,
1910                 0x00, 0x00, 0x02, 0x02,
1911                 0x30, 0x30, 0x40, 0x40
1912         };
1913         static const char ramtypetable2[] = {
1914                 0x77, 0x77, 0x44, 0x44,
1915                 0x77, 0x77, 0x44, 0x44,
1916                 0x00, 0x00, 0x00, 0x00,
1917                 0x5b, 0x5b, 0xab, 0xab,
1918                 0x00, 0x00, 0xf0, 0xf8
1919         };
1920 
1921         while (retry--) {
1922 
1923                 /* Enable VGA */
1924                 ret = GETREG(SISVGAEN, &tmp8);
1925                 ret |= SETREG(SISVGAEN, (tmp8 | 0x01));
1926 
1927                 /* Enable GPU access to VRAM */
1928                 ret |= GETREG(SISMISCR, &tmp8);
1929                 ret |= SETREG(SISMISCW, (tmp8 | 0x01));
1930 
1931                 if (ret)
1932                         continue;
1933 
1934                 /* Reset registers */
1935                 ret |= SETIREGAND(SISCR, 0x5b, 0xdf);
1936                 ret |= SETIREG(SISSR, 0x05, 0x86);
1937                 ret |= SETIREGOR(SISSR, 0x20, 0x01);
1938 
1939                 ret |= SETREG(SISMISCW, 0x67);
1940 
1941                 for (i = 0x06; i <= 0x1f; i++)
1942                         ret |= SETIREG(SISSR, i, 0x00);
1943 
1944                 for (i = 0x21; i <= 0x27; i++)
1945                         ret |= SETIREG(SISSR, i, 0x00);
1946 
1947                 for (i = 0x31; i <= 0x3d; i++)
1948                         ret |= SETIREG(SISSR, i, 0x00);
1949 
1950                 for (i = 0x12; i <= 0x1b; i++)
1951                         ret |= SETIREG(SISSR, i, 0x00);
1952 
1953                 for (i = 0x79; i <= 0x7c; i++)
1954                         ret |= SETIREG(SISCR, i, 0x00);
1955 
1956                 if (ret)
1957                         continue;
1958 
1959                 ret |= SETIREG(SISCR, 0x63, 0x80);
1960 
1961                 ret |= GETIREG(SISSR, 0x3a, &ramtype);
1962                 ramtype &= 0x03;
1963 
1964                 ret |= SETIREG(SISSR, 0x28, mclktable[ramtype * 4]);
1965                 ret |= SETIREG(SISSR, 0x29, mclktable[(ramtype * 4) + 1]);
1966                 ret |= SETIREG(SISSR, 0x2a, mclktable[(ramtype * 4) + 2]);
1967 
1968                 ret |= SETIREG(SISSR, 0x2e, eclktable[ramtype * 4]);
1969                 ret |= SETIREG(SISSR, 0x2f, eclktable[(ramtype * 4) + 1]);
1970                 ret |= SETIREG(SISSR, 0x30, eclktable[(ramtype * 4) + 2]);
1971 
1972                 ret |= SETIREG(SISSR, 0x07, 0x18);
1973                 ret |= SETIREG(SISSR, 0x11, 0x0f);
1974 
1975                 if (ret)
1976                         continue;
1977 
1978                 for (i = 0x15, j = 0; i <= 0x1b; i++, j++) {
1979                         ret |= SETIREG(SISSR, i,
1980                                         ramtypetable1[(j*4) + ramtype]);
1981                 }
1982                 for (i = 0x40, j = 0; i <= 0x44; i++, j++) {
1983                         ret |= SETIREG(SISCR, i,
1984                                         ramtypetable2[(j*4) + ramtype]);
1985                 }
1986 
1987                 ret |= SETIREG(SISCR, 0x49, 0xaa);
1988 
1989                 ret |= SETIREG(SISSR, 0x1f, 0x00);
1990                 ret |= SETIREG(SISSR, 0x20, 0xa0);
1991                 ret |= SETIREG(SISSR, 0x23, 0xf6);
1992                 ret |= SETIREG(SISSR, 0x24, 0x0d);
1993                 ret |= SETIREG(SISSR, 0x25, 0x33);
1994 
1995                 ret |= SETIREG(SISSR, 0x11, 0x0f);
1996 
1997                 ret |= SETIREGOR(SISPART1, 0x2f, 0x01);
1998 
1999                 ret |= SETIREGAND(SISCAP, 0x3f, 0xef);
2000 
2001                 if (ret)
2002                         continue;
2003 
2004                 ret |= SETIREG(SISPART1, 0x00, 0x00);
2005 
2006                 ret |= GETIREG(SISSR, 0x13, &tmp8);
2007                 tmp8 >>= 4;
2008 
2009                 ret |= SETIREG(SISPART1, 0x02, 0x00);
2010                 ret |= SETIREG(SISPART1, 0x2e, 0x08);
2011 
2012                 ret |= sisusb_read_pci_config(sisusb, 0x50, &tmp32);
2013                 tmp32 &= 0x00f00000;
2014                 tmp8 = (tmp32 == 0x100000) ? 0x33 : 0x03;
2015                 ret |= SETIREG(SISSR, 0x25, tmp8);
2016                 tmp8 = (tmp32 == 0x100000) ? 0xaa : 0x88;
2017                 ret |= SETIREG(SISCR, 0x49, tmp8);
2018 
2019                 ret |= SETIREG(SISSR, 0x27, 0x1f);
2020                 ret |= SETIREG(SISSR, 0x31, 0x00);
2021                 ret |= SETIREG(SISSR, 0x32, 0x11);
2022                 ret |= SETIREG(SISSR, 0x33, 0x00);
2023 
2024                 if (ret)
2025                         continue;
2026 
2027                 ret |= SETIREG(SISCR, 0x83, 0x00);
2028 
2029                 ret |= sisusb_set_default_mode(sisusb, 0);
2030 
2031                 ret |= SETIREGAND(SISSR, 0x21, 0xdf);
2032                 ret |= SETIREGOR(SISSR, 0x01, 0x20);
2033                 ret |= SETIREGOR(SISSR, 0x16, 0x0f);
2034 
2035                 ret |= sisusb_triggersr16(sisusb, ramtype);
2036 
2037                 /* Disable refresh */
2038                 ret |= SETIREGAND(SISSR, 0x17, 0xf8);
2039                 ret |= SETIREGOR(SISSR, 0x19, 0x03);
2040 
2041                 ret |= sisusb_getbuswidth(sisusb, &bw, &chab);
2042                 ret |= sisusb_verify_mclk(sisusb);
2043 
2044                 if (ramtype <= 1) {
2045                         ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab);
2046                         if (iret) {
2047                                 dev_err(&sisusb->sisusb_dev->dev,
2048                                                 "RAM size detection failed, assuming 8MB video RAM\n");
2049                                 ret |= SETIREG(SISSR, 0x14, 0x31);
2050                                 /* TODO */
2051                         }
2052                 } else {
2053                         dev_err(&sisusb->sisusb_dev->dev,
2054                                         "DDR RAM device found, assuming 8MB video RAM\n");
2055                         ret |= SETIREG(SISSR, 0x14, 0x31);
2056                         /* *** TODO *** */
2057                 }
2058 
2059                 /* Enable refresh */
2060                 ret |= SETIREG(SISSR, 0x16, ramtypetable1[4 + ramtype]);
2061                 ret |= SETIREG(SISSR, 0x17, ramtypetable1[8 + ramtype]);
2062                 ret |= SETIREG(SISSR, 0x19, ramtypetable1[16 + ramtype]);
2063 
2064                 ret |= SETIREGOR(SISSR, 0x21, 0x20);
2065 
2066                 ret |= SETIREG(SISSR, 0x22, 0xfb);
2067                 ret |= SETIREG(SISSR, 0x21, 0xa5);
2068 
2069                 if (ret == 0)
2070                         break;
2071         }
2072 
2073         return ret;
2074 }
2075 
2076 #undef SETREG
2077 #undef GETREG
2078 #undef SETIREG
2079 #undef GETIREG
2080 #undef SETIREGOR
2081 #undef SETIREGAND
2082 #undef SETIREGANDOR
2083 #undef READL
2084 #undef WRITEL
2085 
2086 static void sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
2087 {
2088         u8 tmp8, tmp82, ramtype;
2089         int bw = 0;
2090         char *ramtypetext1 = NULL;
2091         static const char ram_datarate[4] = {'S', 'S', 'D', 'D'};
2092         static const char ram_dynamictype[4] = {'D', 'G', 'D', 'G'};
2093         static const int busSDR[4]  = {64, 64, 128, 128};
2094         static const int busDDR[4]  = {32, 32,  64,  64};
2095         static const int busDDRA[4] = {64+32, 64+32, (64+32)*2, (64+32)*2};
2096 
2097         sisusb_getidxreg(sisusb, SISSR, 0x14, &tmp8);
2098         sisusb_getidxreg(sisusb, SISSR, 0x15, &tmp82);
2099         sisusb_getidxreg(sisusb, SISSR, 0x3a, &ramtype);
2100         sisusb->vramsize = (1 << ((tmp8 & 0xf0) >> 4)) * 1024 * 1024;
2101         ramtype &= 0x03;
2102         switch ((tmp8 >> 2) & 0x03) {
2103         case 0:
2104                 ramtypetext1 = "1 ch/1 r";
2105                 if (tmp82 & 0x10)
2106                         bw = 32;
2107                 else
2108                         bw = busSDR[(tmp8 & 0x03)];
2109 
2110                 break;
2111         case 1:
2112                 ramtypetext1 = "1 ch/2 r";
2113                 sisusb->vramsize <<= 1;
2114                 bw = busSDR[(tmp8 & 0x03)];
2115                 break;
2116         case 2:
2117                 ramtypetext1 = "asymmeric";
2118                 sisusb->vramsize += sisusb->vramsize/2;
2119                 bw = busDDRA[(tmp8 & 0x03)];
2120                 break;
2121         case 3:
2122                 ramtypetext1 = "2 channel";
2123                 sisusb->vramsize <<= 1;
2124                 bw = busDDR[(tmp8 & 0x03)];
2125                 break;
2126         }
2127 
2128         dev_info(&sisusb->sisusb_dev->dev,
2129                         "%dMB %s %cDR S%cRAM, bus width %d\n",
2130                         sisusb->vramsize >> 20, ramtypetext1,
2131                         ram_datarate[ramtype], ram_dynamictype[ramtype], bw);
2132 }
2133 
2134 static int sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb)
2135 {
2136         struct sisusb_packet packet;
2137         int ret;
2138         u32 tmp32;
2139 
2140         /* Do some magic */
2141         packet.header  = 0x001f;
2142         packet.address = 0x00000324;
2143         packet.data    = 0x00000004;
2144         ret = sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2145 
2146         packet.header  = 0x001f;
2147         packet.address = 0x00000364;
2148         packet.data    = 0x00000004;
2149         ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2150 
2151         packet.header  = 0x001f;
2152         packet.address = 0x00000384;
2153         packet.data    = 0x00000004;
2154         ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2155 
2156         packet.header  = 0x001f;
2157         packet.address = 0x00000100;
2158         packet.data    = 0x00000700;
2159         ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2160 
2161         packet.header  = 0x000f;
2162         packet.address = 0x00000004;
2163         ret |= sisusb_send_bridge_packet(sisusb, 6, &packet, 0);
2164         packet.data |= 0x17;
2165         ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2166 
2167         /* Init BAR 0 (VRAM) */
2168         ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2169         ret |= sisusb_write_pci_config(sisusb, 0x10, 0xfffffff0);
2170         ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2171         tmp32 &= 0x0f;
2172         tmp32 |= SISUSB_PCI_MEMBASE;
2173         ret |= sisusb_write_pci_config(sisusb, 0x10, tmp32);
2174 
2175         /* Init BAR 1 (MMIO) */
2176         ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2177         ret |= sisusb_write_pci_config(sisusb, 0x14, 0xfffffff0);
2178         ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2179         tmp32 &= 0x0f;
2180         tmp32 |= SISUSB_PCI_MMIOBASE;
2181         ret |= sisusb_write_pci_config(sisusb, 0x14, tmp32);
2182 
2183         /* Init BAR 2 (i/o ports) */
2184         ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2185         ret |= sisusb_write_pci_config(sisusb, 0x18, 0xfffffff0);
2186         ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2187         tmp32 &= 0x0f;
2188         tmp32 |= SISUSB_PCI_IOPORTBASE;
2189         ret |= sisusb_write_pci_config(sisusb, 0x18, tmp32);
2190 
2191         /* Enable memory and i/o access */
2192         ret |= sisusb_read_pci_config(sisusb, 0x04, &tmp32);
2193         tmp32 |= 0x3;
2194         ret |= sisusb_write_pci_config(sisusb, 0x04, tmp32);
2195 
2196         if (ret == 0) {
2197                 /* Some further magic */
2198                 packet.header  = 0x001f;
2199                 packet.address = 0x00000050;
2200                 packet.data    = 0x000000ff;
2201                 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2202         }
2203 
2204         return ret;
2205 }
2206 
2207 /* Initialize the graphics device (return 0 on success)
2208  * This initializes the net2280 as well as the PCI registers
2209  * of the graphics board.
2210  */
2211 
2212 static int sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
2213 {
2214         int ret = 0, test = 0;
2215         u32 tmp32;
2216 
2217         if (sisusb->devinit == 1) {
2218                 /* Read PCI BARs and see if they have been set up */
2219                 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2220                 if (ret)
2221                         return ret;
2222 
2223                 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE)
2224                         test++;
2225 
2226                 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2227                 if (ret)
2228                         return ret;
2229 
2230                 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE)
2231                         test++;
2232 
2233                 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2234                 if (ret)
2235                         return ret;
2236 
2237                 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE)
2238                         test++;
2239         }
2240 
2241         /* No? So reset the device */
2242         if ((sisusb->devinit == 0) || (test != 3)) {
2243 
2244                 ret |= sisusb_do_init_gfxdevice(sisusb);
2245 
2246                 if (ret == 0)
2247                         sisusb->devinit = 1;
2248 
2249         }
2250 
2251         if (sisusb->devinit) {
2252                 /* Initialize the graphics core */
2253                 if (sisusb_init_gfxcore(sisusb) == 0) {
2254                         sisusb->gfxinit = 1;
2255                         sisusb_get_ramconfig(sisusb);
2256                         ret |= sisusb_set_default_mode(sisusb, 1);
2257                         ret |= sisusb_setup_screen(sisusb, 1, initscreen);
2258                 }
2259         }
2260 
2261         return ret;
2262 }
2263 
2264 
2265 #ifdef INCL_SISUSB_CON
2266 
2267 /* Set up default text mode:
2268  * - Set text mode (0x03)
2269  * - Upload default font
2270  * - Upload user font (if available)
2271  */
2272 
2273 int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
2274 {
2275         int ret = 0, slot = sisusb->font_slot, i;
2276         const struct font_desc *myfont;
2277         u8 *tempbuf;
2278         u16 *tempbufb;
2279         size_t written;
2280         static const char bootstring[] =
2281                 "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2282         static const char bootlogo[] = "(o_ //\\ V_/_";
2283 
2284         /* sisusb->lock is down */
2285 
2286         if (!sisusb->SiS_Pr)
2287                 return 1;
2288 
2289         sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2290         sisusb->SiS_Pr->sisusb = (void *)sisusb;
2291 
2292         /* Set mode 0x03 */
2293         SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
2294 
2295         myfont = find_font("VGA8x16");
2296         if (!myfont)
2297                 return 1;
2298 
2299         tempbuf = vmalloc(8192);
2300         if (!tempbuf)
2301                 return 1;
2302 
2303         for (i = 0; i < 256; i++)
2304                 memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
2305 
2306         /* Upload default font */
2307         ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192,
2308                         0, 1, NULL, 16, 0);
2309 
2310         vfree(tempbuf);
2311 
2312         /* Upload user font (and reset current slot) */
2313         if (sisusb->font_backup) {
2314                 ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
2315                                 8192, sisusb->font_backup_512, 1, NULL,
2316                                 sisusb->font_backup_height, 0);
2317                 if (slot != 2)
2318                         sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
2319                                         NULL, 16, 0);
2320         }
2321 
2322         if (init && !sisusb->scrbuf) {
2323 
2324                 tempbuf = vmalloc(8192);
2325                 if (tempbuf) {
2326 
2327                         i = 4096;
2328                         tempbufb = (u16 *)tempbuf;
2329                         while (i--)
2330                                 *(tempbufb++) = 0x0720;
2331 
2332                         i = 0;
2333                         tempbufb = (u16 *)tempbuf;
2334                         while (bootlogo[i]) {
2335                                 *(tempbufb++) = 0x0700 | bootlogo[i++];
2336                                 if (!(i % 4))
2337                                         tempbufb += 76;
2338                         }
2339 
2340                         i = 0;
2341                         tempbufb = (u16 *)tempbuf + 6;
2342                         while (bootstring[i])
2343                                 *(tempbufb++) = 0x0700 | bootstring[i++];
2344 
2345                         ret |= sisusb_copy_memory(sisusb, tempbuf,
2346                                         sisusb->vrambase, 8192, &written);
2347 
2348                         vfree(tempbuf);
2349 
2350                 }
2351 
2352         } else if (sisusb->scrbuf) {
2353 
2354                 ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
2355                                 sisusb->vrambase, sisusb->scrbuf_size,
2356                                 &written);
2357 
2358         }
2359 
2360         if (sisusb->sisusb_cursor_size_from >= 0 &&
2361                         sisusb->sisusb_cursor_size_to >= 0) {
2362                 sisusb_setidxreg(sisusb, SISCR, 0x0a,
2363                                 sisusb->sisusb_cursor_size_from);
2364                 sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
2365                                 sisusb->sisusb_cursor_size_to);
2366         } else {
2367                 sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
2368                 sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
2369                 sisusb->sisusb_cursor_size_to = -1;
2370         }
2371 
2372         slot = sisusb->sisusb_cursor_loc;
2373         if (slot < 0)
2374                 slot = 0;
2375 
2376         sisusb->sisusb_cursor_loc = -1;
2377         sisusb->bad_cursor_pos = 1;
2378 
2379         sisusb_set_cursor(sisusb, slot);
2380 
2381         sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
2382         sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
2383 
2384         sisusb->textmodedestroyed = 0;
2385 
2386         /* sisusb->lock is down */
2387 
2388         return ret;
2389 }
2390 
2391 #endif
2392 
2393 /* fops */
2394 
2395 static int sisusb_open(struct inode *inode, struct file *file)
2396 {
2397         struct sisusb_usb_data *sisusb;
2398         struct usb_interface *interface;
2399         int subminor = iminor(inode);
2400 
2401         interface = usb_find_interface(&sisusb_driver, subminor);
2402         if (!interface)
2403                 return -ENODEV;
2404 
2405         sisusb = usb_get_intfdata(interface);
2406         if (!sisusb)
2407                 return -ENODEV;
2408 
2409         mutex_lock(&sisusb->lock);
2410 
2411         if (!sisusb->present || !sisusb->ready) {
2412                 mutex_unlock(&sisusb->lock);
2413                 return -ENODEV;
2414         }
2415 
2416         if (sisusb->isopen) {
2417                 mutex_unlock(&sisusb->lock);
2418                 return -EBUSY;
2419         }
2420 
2421         if (!sisusb->devinit) {
2422                 if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH ||
2423                                 sisusb->sisusb_dev->speed >= USB_SPEED_SUPER) {
2424                         if (sisusb_init_gfxdevice(sisusb, 0)) {
2425                                 mutex_unlock(&sisusb->lock);
2426                                 dev_err(&sisusb->sisusb_dev->dev,
2427                                                 "Failed to initialize device\n");
2428                                 return -EIO;
2429                         }
2430                 } else {
2431                         mutex_unlock(&sisusb->lock);
2432                         dev_err(&sisusb->sisusb_dev->dev,
2433                                         "Device not attached to USB 2.0 hub\n");
2434                         return -EIO;
2435                 }
2436         }
2437 
2438         /* Increment usage count for our sisusb */
2439         kref_get(&sisusb->kref);
2440 
2441         sisusb->isopen = 1;
2442 
2443         file->private_data = sisusb;
2444 
2445         mutex_unlock(&sisusb->lock);
2446 
2447         return 0;
2448 }
2449 
2450 void sisusb_delete(struct kref *kref)
2451 {
2452         struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
2453 
2454         if (!sisusb)
2455                 return;
2456 
2457         usb_put_dev(sisusb->sisusb_dev);
2458 
2459         sisusb->sisusb_dev = NULL;
2460         sisusb_free_buffers(sisusb);
2461         sisusb_free_urbs(sisusb);
2462 #ifdef INCL_SISUSB_CON
2463         kfree(sisusb->SiS_Pr);
2464 #endif
2465         kfree(sisusb);
2466 }
2467 
2468 static int sisusb_release(struct inode *inode, struct file *file)
2469 {
2470         struct sisusb_usb_data *sisusb;
2471 
2472         sisusb = file->private_data;
2473         if (!sisusb)
2474                 return -ENODEV;
2475 
2476         mutex_lock(&sisusb->lock);
2477 
2478         if (sisusb->present) {
2479                 /* Wait for all URBs to finish if device still present */
2480                 if (!sisusb_wait_all_out_complete(sisusb))
2481                         sisusb_kill_all_busy(sisusb);
2482         }
2483 
2484         sisusb->isopen = 0;
2485         file->private_data = NULL;
2486 
2487         mutex_unlock(&sisusb->lock);
2488 
2489         /* decrement the usage count on our device */
2490         kref_put(&sisusb->kref, sisusb_delete);
2491 
2492         return 0;
2493 }
2494 
2495 static ssize_t sisusb_read(struct file *file, char __user *buffer,
2496                 size_t count, loff_t *ppos)
2497 {
2498         struct sisusb_usb_data *sisusb;
2499         ssize_t bytes_read = 0;
2500         int errno = 0;
2501         u8 buf8;
2502         u16 buf16;
2503         u32 buf32, address;
2504 
2505         sisusb = file->private_data;
2506         if (!sisusb)
2507                 return -ENODEV;
2508 
2509         mutex_lock(&sisusb->lock);
2510 
2511         /* Sanity check */
2512         if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2513                 mutex_unlock(&sisusb->lock);
2514                 return -ENODEV;
2515         }
2516 
2517         if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2518                         (*ppos) <  SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2519 
2520                 address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE +
2521                                 SISUSB_PCI_IOPORTBASE;
2522 
2523                 /* Read i/o ports
2524                  * Byte, word and long(32) can be read. As this
2525                  * emulates inX instructions, the data returned is
2526                  * in machine-endianness.
2527                  */
2528                 switch (count) {
2529                 case 1:
2530                         if (sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO,
2531                                         address, &buf8))
2532                                 errno = -EIO;
2533                         else if (put_user(buf8, (u8 __user *)buffer))
2534                                 errno = -EFAULT;
2535                         else
2536                                 bytes_read = 1;
2537 
2538                         break;
2539 
2540                 case 2:
2541                         if (sisusb_read_memio_word(sisusb, SISUSB_TYPE_IO,
2542                                         address, &buf16))
2543                                 errno = -EIO;
2544                         else if (put_user(buf16, (u16 __user *)buffer))
2545                                 errno = -EFAULT;
2546                         else
2547                                 bytes_read = 2;
2548 
2549                         break;
2550 
2551                 case 4:
2552                         if (sisusb_read_memio_long(sisusb, SISUSB_TYPE_IO,
2553                                         address, &buf32))
2554                                 errno = -EIO;
2555                         else if (put_user(buf32, (u32 __user *)buffer))
2556                                 errno = -EFAULT;
2557                         else
2558                                 bytes_read = 4;
2559 
2560                         break;
2561 
2562                 default:
2563                         errno = -EIO;
2564 
2565                 }
2566 
2567         } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && (*ppos) <
2568                         SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2569 
2570                 address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE +
2571                                 SISUSB_PCI_MEMBASE;
2572 
2573                 /* Read video ram
2574                  * Remember: Data delivered is never endian-corrected
2575                  */
2576                 errno = sisusb_read_mem_bulk(sisusb, address,
2577                                 NULL, count, buffer, &bytes_read);
2578 
2579                 if (bytes_read)
2580                         errno = bytes_read;
2581 
2582         } else  if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2583                                 (*ppos) <  SISUSB_PCI_PSEUDO_MMIOBASE +
2584                                 SISUSB_PCI_MMIOSIZE) {
2585 
2586                 address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE +
2587                                 SISUSB_PCI_MMIOBASE;
2588 
2589                 /* Read MMIO
2590                  * Remember: Data delivered is never endian-corrected
2591                  */
2592                 errno = sisusb_read_mem_bulk(sisusb, address,
2593                                 NULL, count, buffer, &bytes_read);
2594 
2595                 if (bytes_read)
2596                         errno = bytes_read;
2597 
2598         } else  if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2599                         (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
2600 
2601                 if (count != 4) {
2602                         mutex_unlock(&sisusb->lock);
2603                         return -EINVAL;
2604                 }
2605 
2606                 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2607 
2608                 /* Read PCI config register
2609                  * Return value delivered in machine endianness.
2610                  */
2611                 if (sisusb_read_pci_config(sisusb, address, &buf32))
2612                         errno = -EIO;
2613                 else if (put_user(buf32, (u32 __user *)buffer))
2614                         errno = -EFAULT;
2615                 else
2616                         bytes_read = 4;
2617 
2618         } else {
2619 
2620                 errno = -EBADFD;
2621 
2622         }
2623 
2624         (*ppos) += bytes_read;
2625 
2626         mutex_unlock(&sisusb->lock);
2627 
2628         return errno ? errno : bytes_read;
2629 }
2630 
2631 static ssize_t sisusb_write(struct file *file, const char __user *buffer,
2632                 size_t count, loff_t *ppos)
2633 {
2634         struct sisusb_usb_data *sisusb;
2635         int errno = 0;
2636         ssize_t bytes_written = 0;
2637         u8 buf8;
2638         u16 buf16;
2639         u32 buf32, address;
2640 
2641         sisusb = file->private_data;
2642         if (!sisusb)
2643                 return -ENODEV;
2644 
2645         mutex_lock(&sisusb->lock);
2646 
2647         /* Sanity check */
2648         if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2649                 mutex_unlock(&sisusb->lock);
2650                 return -ENODEV;
2651         }
2652 
2653         if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2654                         (*ppos) <  SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2655 
2656                 address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE +
2657                                 SISUSB_PCI_IOPORTBASE;
2658 
2659                 /* Write i/o ports
2660                  * Byte, word and long(32) can be written. As this
2661                  * emulates outX instructions, the data is expected
2662                  * in machine-endianness.
2663                  */
2664                 switch (count) {
2665                 case 1:
2666                         if (get_user(buf8, (u8 __user *)buffer))
2667                                 errno = -EFAULT;
2668                         else if (sisusb_write_memio_byte(sisusb,
2669                                         SISUSB_TYPE_IO, address, buf8))
2670                                 errno = -EIO;
2671                         else
2672                                 bytes_written = 1;
2673 
2674                         break;
2675 
2676                 case 2:
2677                         if (get_user(buf16, (u16 __user *)buffer))
2678                                 errno = -EFAULT;
2679                         else if (sisusb_write_memio_word(sisusb,
2680                                         SISUSB_TYPE_IO, address, buf16))
2681                                 errno = -EIO;
2682                         else
2683                                 bytes_written = 2;
2684 
2685                         break;
2686 
2687                 case 4:
2688                         if (get_user(buf32, (u32 __user *)buffer))
2689                                 errno = -EFAULT;
2690                         else if (sisusb_write_memio_long(sisusb,
2691                                         SISUSB_TYPE_IO, address, buf32))
2692                                 errno = -EIO;
2693                         else
2694                                 bytes_written = 4;
2695 
2696                         break;
2697 
2698                 default:
2699                         errno = -EIO;
2700                 }
2701 
2702         } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2703                         (*ppos) <  SISUSB_PCI_PSEUDO_MEMBASE +
2704                         sisusb->vramsize) {
2705 
2706                 address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE +
2707                                 SISUSB_PCI_MEMBASE;
2708 
2709                 /* Write video ram.
2710                  * Buffer is copied 1:1, therefore, on big-endian
2711                  * machines, the data must be swapped by userland
2712                  * in advance (if applicable; no swapping in 8bpp
2713                  * mode or if YUV data is being transferred).
2714                  */
2715                 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2716                                 count, buffer, 0, &bytes_written);
2717 
2718                 if (bytes_written)
2719                         errno = bytes_written;
2720 
2721         } else  if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2722                         (*ppos) <  SISUSB_PCI_PSEUDO_MMIOBASE +
2723                         SISUSB_PCI_MMIOSIZE) {
2724 
2725                 address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE +
2726                                 SISUSB_PCI_MMIOBASE;
2727 
2728                 /* Write MMIO.
2729                  * Buffer is copied 1:1, therefore, on big-endian
2730                  * machines, the data must be swapped by userland
2731                  * in advance.
2732                  */
2733                 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2734                                 count, buffer, 0, &bytes_written);
2735 
2736                 if (bytes_written)
2737                         errno = bytes_written;
2738 
2739         } else  if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2740                                 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE +
2741                                 SISUSB_PCI_PCONFSIZE) {
2742 
2743                 if (count != 4) {
2744                         mutex_unlock(&sisusb->lock);
2745                         return -EINVAL;
2746                 }
2747 
2748                 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2749 
2750                 /* Write PCI config register.
2751                  * Given value expected in machine endianness.
2752                  */
2753                 if (get_user(buf32, (u32 __user *)buffer))
2754                         errno = -EFAULT;
2755                 else if (sisusb_write_pci_config(sisusb, address, buf32))
2756                         errno = -EIO;
2757                 else
2758                         bytes_written = 4;
2759 
2760 
2761         } else {
2762 
2763                 /* Error */
2764                 errno = -EBADFD;
2765 
2766         }
2767 
2768         (*ppos) += bytes_written;
2769 
2770         mutex_unlock(&sisusb->lock);
2771 
2772         return errno ? errno : bytes_written;
2773 }
2774 
2775 static loff_t sisusb_lseek(struct file *file, loff_t offset, int orig)
2776 {
2777         struct sisusb_usb_data *sisusb;
2778         loff_t ret;
2779 
2780         sisusb = file->private_data;
2781         if (!sisusb)
2782                 return -ENODEV;
2783 
2784         mutex_lock(&sisusb->lock);
2785 
2786         /* Sanity check */
2787         if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2788                 mutex_unlock(&sisusb->lock);
2789                 return -ENODEV;
2790         }
2791 
2792         ret = no_seek_end_llseek(file, offset, orig);
2793 
2794         mutex_unlock(&sisusb->lock);
2795         return ret;
2796 }
2797 
2798 static int sisusb_handle_command(struct sisusb_usb_data *sisusb,
2799                 struct sisusb_command *y, unsigned long arg)
2800 {
2801         int     retval, port, length;
2802         u32     address;
2803 
2804         /* All our commands require the device
2805          * to be initialized.
2806          */
2807         if (!sisusb->devinit)
2808                 return -ENODEV;
2809 
2810         port = y->data3 -
2811                 SISUSB_PCI_PSEUDO_IOPORTBASE +
2812                 SISUSB_PCI_IOPORTBASE;
2813 
2814         switch (y->operation) {
2815         case SUCMD_GET:
2816                 retval = sisusb_getidxreg(sisusb, port, y->data0, &y->data1);
2817                 if (!retval) {
2818                         if (copy_to_user((void __user *)arg, y, sizeof(*y)))
2819                                 retval = -EFAULT;
2820                 }
2821                 break;
2822 
2823         case SUCMD_SET:
2824                 retval = sisusb_setidxreg(sisusb, port, y->data0, y->data1);
2825                 break;
2826 
2827         case SUCMD_SETOR:
2828                 retval = sisusb_setidxregor(sisusb, port, y->data0, y->data1);
2829                 break;
2830 
2831         case SUCMD_SETAND:
2832                 retval = sisusb_setidxregand(sisusb, port, y->data0, y->data1);
2833                 break;
2834 
2835         case SUCMD_SETANDOR:
2836                 retval = sisusb_setidxregandor(sisusb, port, y->data0,
2837                                 y->data1, y->data2);
2838                 break;
2839 
2840         case SUCMD_SETMASK:
2841                 retval = sisusb_setidxregmask(sisusb, port, y->data0,
2842                                 y->data1, y->data2);
2843                 break;
2844 
2845         case SUCMD_CLRSCR:
2846                 /* Gfx core must be initialized */
2847                 if (!sisusb->gfxinit)
2848                         return -ENODEV;
2849 
2850                 length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
2851                 address = y->data3 - SISUSB_PCI_PSEUDO_MEMBASE +
2852                                 SISUSB_PCI_MEMBASE;
2853                 retval = sisusb_clear_vram(sisusb, address, length);
2854                 break;
2855 
2856         case SUCMD_HANDLETEXTMODE:
2857                 retval = 0;
2858 #ifdef INCL_SISUSB_CON
2859                 /* Gfx core must be initialized, SiS_Pr must exist */
2860                 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2861                         return -ENODEV;
2862 
2863                 switch (y->data0) {
2864                 case 0:
2865                         retval = sisusb_reset_text_mode(sisusb, 0);
2866                         break;
2867                 case 1:
2868                         sisusb->textmodedestroyed = 1;
2869                         break;
2870                 }
2871 #endif
2872                 break;
2873 
2874 #ifdef INCL_SISUSB_CON
2875         case SUCMD_SETMODE:
2876                 /* Gfx core must be initialized, SiS_Pr must exist */
2877                 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2878                         return -ENODEV;
2879 
2880                 retval = 0;
2881 
2882                 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2883                 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2884 
2885                 if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
2886                         retval = -EINVAL;
2887 
2888                 break;
2889 
2890         case SUCMD_SETVESAMODE:
2891                 /* Gfx core must be initialized, SiS_Pr must exist */
2892                 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2893                         return -ENODEV;
2894 
2895                 retval = 0;
2896 
2897                 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2898                 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2899 
2900                 if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
2901                         retval = -EINVAL;
2902 
2903                 break;
2904 #endif
2905 
2906         default:
2907                 retval = -EINVAL;
2908         }
2909 
2910         if (retval > 0)
2911                 retval = -EIO;
2912 
2913         return retval;
2914 }
2915 
2916 static long sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2917 {
2918         struct sisusb_usb_data *sisusb;
2919         struct sisusb_info x;
2920         struct sisusb_command y;
2921         long retval = 0;
2922         u32 __user *argp = (u32 __user *)arg;
2923 
2924         sisusb = file->private_data;
2925         if (!sisusb)
2926                 return -ENODEV;
2927 
2928         mutex_lock(&sisusb->lock);
2929 
2930         /* Sanity check */
2931         if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2932                 retval = -ENODEV;
2933                 goto err_out;
2934         }
2935 
2936         switch (cmd) {
2937         case SISUSB_GET_CONFIG_SIZE:
2938 
2939                 if (put_user(sizeof(x), argp))
2940                         retval = -EFAULT;
2941 
2942                 break;
2943 
2944         case SISUSB_GET_CONFIG:
2945 
2946                 x.sisusb_id = SISUSB_ID;
2947                 x.sisusb_version = SISUSB_VERSION;
2948                 x.sisusb_revision = SISUSB_REVISION;
2949                 x.sisusb_patchlevel = SISUSB_PATCHLEVEL;
2950                 x.sisusb_gfxinit = sisusb->gfxinit;
2951                 x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE;
2952                 x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE;
2953                 x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE;
2954                 x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE;
2955                 x.sisusb_vramsize = sisusb->vramsize;
2956                 x.sisusb_minor = sisusb->minor;
2957                 x.sisusb_fbdevactive = 0;
2958 #ifdef INCL_SISUSB_CON
2959                 x.sisusb_conactive  = sisusb->haveconsole ? 1 : 0;
2960 #else
2961                 x.sisusb_conactive  = 0;
2962 #endif
2963                 memset(x.sisusb_reserved, 0, sizeof(x.sisusb_reserved));
2964 
2965                 if (copy_to_user((void __user *)arg, &x, sizeof(x)))
2966                         retval = -EFAULT;
2967 
2968                 break;
2969 
2970         case SISUSB_COMMAND:
2971 
2972                 if (copy_from_user(&y, (void __user *)arg, sizeof(y)))
2973                         retval = -EFAULT;
2974                 else
2975                         retval = sisusb_handle_command(sisusb, &y, arg);
2976 
2977                 break;
2978 
2979         default:
2980                 retval = -ENOTTY;
2981                 break;
2982         }
2983 
2984 err_out:
2985         mutex_unlock(&sisusb->lock);
2986         return retval;
2987 }
2988 
2989 #ifdef SISUSB_NEW_CONFIG_COMPAT
2990 static long sisusb_compat_ioctl(struct file *f, unsigned int cmd,
2991                 unsigned long arg)
2992 {
2993         long retval;
2994 
2995         switch (cmd) {
2996         case SISUSB_GET_CONFIG_SIZE:
2997         case SISUSB_GET_CONFIG:
2998         case SISUSB_COMMAND:
2999                 retval = sisusb_ioctl(f, cmd, arg);
3000                 return retval;
3001 
3002         default:
3003                 return -ENOIOCTLCMD;
3004         }
3005 }
3006 #endif
3007 
3008 static const struct file_operations usb_sisusb_fops = {
3009         .owner =        THIS_MODULE,
3010         .open =         sisusb_open,
3011         .release =      sisusb_release,
3012         .read =         sisusb_read,
3013         .write =        sisusb_write,
3014         .llseek =       sisusb_lseek,
3015 #ifdef SISUSB_NEW_CONFIG_COMPAT
3016         .compat_ioctl = sisusb_compat_ioctl,
3017 #endif
3018         .unlocked_ioctl = sisusb_ioctl
3019 };
3020 
3021 static struct usb_class_driver usb_sisusb_class = {
3022         .name =         "sisusbvga%d",
3023         .fops =         &usb_sisusb_fops,
3024         .minor_base =   SISUSB_MINOR
3025 };
3026 
3027 static int sisusb_probe(struct usb_interface *intf,
3028                 const struct usb_device_id *id)
3029 {
3030         struct usb_device *dev = interface_to_usbdev(intf);
3031         struct sisusb_usb_data *sisusb;
3032         int retval = 0, i;
3033 
3034         dev_info(&dev->dev, "USB2VGA dongle found at address %d\n",
3035                         dev->devnum);
3036 
3037         /* Allocate memory for our private */
3038         sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL);
3039         if (!sisusb)
3040                 return -ENOMEM;
3041 
3042         kref_init(&sisusb->kref);
3043 
3044         mutex_init(&(sisusb->lock));
3045 
3046         /* Register device */
3047         retval = usb_register_dev(intf, &usb_sisusb_class);
3048         if (retval) {
3049                 dev_err(&sisusb->sisusb_dev->dev,
3050                                 "Failed to get a minor for device %d\n",
3051                                 dev->devnum);
3052                 retval = -ENODEV;
3053                 goto error_1;
3054         }
3055 
3056         sisusb->sisusb_dev = dev;
3057         sisusb->minor      = intf->minor;
3058         sisusb->vrambase   = SISUSB_PCI_MEMBASE;
3059         sisusb->mmiobase   = SISUSB_PCI_MMIOBASE;
3060         sisusb->mmiosize   = SISUSB_PCI_MMIOSIZE;
3061         sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
3062         /* Everything else is zero */
3063 
3064         /* Allocate buffers */
3065         sisusb->ibufsize = SISUSB_IBUF_SIZE;
3066         sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL);
3067         if (!sisusb->ibuf) {
3068                 retval = -ENOMEM;
3069                 goto error_2;
3070         }
3071 
3072         sisusb->numobufs = 0;
3073         sisusb->obufsize = SISUSB_OBUF_SIZE;
3074         for (i = 0; i < NUMOBUFS; i++) {
3075                 sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL);
3076                 if (!sisusb->obuf[i]) {
3077                         if (i == 0) {
3078                                 retval = -ENOMEM;
3079                                 goto error_3;
3080                         }
3081                         break;
3082                 }
3083                 sisusb->numobufs++;
3084         }
3085 
3086         /* Allocate URBs */
3087         sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL);
3088         if (!sisusb->sisurbin) {
3089                 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n");
3090                 retval = -ENOMEM;
3091                 goto error_3;
3092         }
3093         sisusb->completein = 1;
3094 
3095         for (i = 0; i < sisusb->numobufs; i++) {
3096                 sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL);
3097                 if (!sisusb->sisurbout[i]) {
3098                         dev_err(&sisusb->sisusb_dev->dev,
3099                                         "Failed to allocate URBs\n");
3100                         retval = -ENOMEM;
3101                         goto error_4;
3102                 }
3103                 sisusb->urbout_context[i].sisusb = (void *)sisusb;
3104                 sisusb->urbout_context[i].urbindex = i;
3105                 sisusb->urbstatus[i] = 0;
3106         }
3107 
3108         dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n",
3109                         sisusb->numobufs);
3110 
3111 #ifdef INCL_SISUSB_CON
3112         /* Allocate our SiS_Pr */
3113         sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL);
3114         if (!sisusb->SiS_Pr) {
3115                 retval = -ENOMEM;
3116                 goto error_4;
3117         }
3118 #endif
3119 
3120         /* Do remaining init stuff */
3121 
3122         init_waitqueue_head(&sisusb->wait_q);
3123 
3124         usb_set_intfdata(intf, sisusb);
3125 
3126         usb_get_dev(sisusb->sisusb_dev);
3127 
3128         sisusb->present = 1;
3129 
3130         if (dev->speed == USB_SPEED_HIGH || dev->speed >= USB_SPEED_SUPER) {
3131                 int initscreen = 1;
3132 #ifdef INCL_SISUSB_CON
3133                 if (sisusb_first_vc > 0 && sisusb_last_vc > 0 &&
3134                                 sisusb_first_vc <= sisusb_last_vc &&
3135                                 sisusb_last_vc <= MAX_NR_CONSOLES)
3136                         initscreen = 0;
3137 #endif
3138                 if (sisusb_init_gfxdevice(sisusb, initscreen))
3139                         dev_err(&sisusb->sisusb_dev->dev,
3140                                         "Failed to early initialize device\n");
3141 
3142         } else
3143                 dev_info(&sisusb->sisusb_dev->dev,
3144                                 "Not attached to USB 2.0 hub, deferring init\n");
3145 
3146         sisusb->ready = 1;
3147 
3148 #ifdef SISUSBENDIANTEST
3149         dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST ***\n");
3150         sisusb_testreadwrite(sisusb);
3151         dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST END ***\n");
3152 #endif
3153 
3154 #ifdef INCL_SISUSB_CON
3155         sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
3156 #endif
3157 
3158         return 0;
3159 
3160 error_4:
3161         sisusb_free_urbs(sisusb);
3162 error_3:
3163         sisusb_free_buffers(sisusb);
3164 error_2:
3165         usb_deregister_dev(intf, &usb_sisusb_class);
3166 error_1:
3167         kfree(sisusb);
3168         return retval;
3169 }
3170 
3171 static void sisusb_disconnect(struct usb_interface *intf)
3172 {
3173         struct sisusb_usb_data *sisusb;
3174 
3175         /* This should *not* happen */
3176         sisusb = usb_get_intfdata(intf);
3177         if (!sisusb)
3178                 return;
3179 
3180 #ifdef INCL_SISUSB_CON
3181         sisusb_console_exit(sisusb);
3182 #endif
3183 
3184         usb_deregister_dev(intf, &usb_sisusb_class);
3185 
3186         mutex_lock(&sisusb->lock);
3187 
3188         /* Wait for all URBs to complete and kill them in case (MUST do) */
3189         if (!sisusb_wait_all_out_complete(sisusb))
3190                 sisusb_kill_all_busy(sisusb);
3191 
3192         usb_set_intfdata(intf, NULL);
3193 
3194         sisusb->present = 0;
3195         sisusb->ready = 0;
3196 
3197         mutex_unlock(&sisusb->lock);
3198 
3199         /* decrement our usage count */
3200         kref_put(&sisusb->kref, sisusb_delete);
3201 }
3202 
3203 static const struct usb_device_id sisusb_table[] = {
3204         { USB_DEVICE(0x0711, 0x0550) },
3205         { USB_DEVICE(0x0711, 0x0900) },
3206         { USB_DEVICE(0x0711, 0x0901) },
3207         { USB_DEVICE(0x0711, 0x0902) },
3208         { USB_DEVICE(0x0711, 0x0903) },
3209         { USB_DEVICE(0x0711, 0x0918) },
3210         { USB_DEVICE(0x0711, 0x0920) },
3211         { USB_DEVICE(0x0711, 0x0950) },
3212         { USB_DEVICE(0x0711, 0x5200) },
3213         { USB_DEVICE(0x182d, 0x021c) },
3214         { USB_DEVICE(0x182d, 0x0269) },
3215         { }
3216 };
3217 
3218 MODULE_DEVICE_TABLE(usb, sisusb_table);
3219 
3220 static struct usb_driver sisusb_driver = {
3221         .name =         "sisusb",
3222         .probe =        sisusb_probe,
3223         .disconnect =   sisusb_disconnect,
3224         .id_table =     sisusb_table,
3225 };
3226 
3227 static int __init usb_sisusb_init(void)
3228 {
3229 
3230 #ifdef INCL_SISUSB_CON
3231         sisusb_init_concode();
3232 #endif
3233 
3234         return usb_register(&sisusb_driver);
3235 }
3236 
3237 static void __exit usb_sisusb_exit(void)
3238 {
3239         usb_deregister(&sisusb_driver);
3240 }
3241 
3242 module_init(usb_sisusb_init);
3243 module_exit(usb_sisusb_exit);
3244 
3245 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3246 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3247 MODULE_LICENSE("GPL");
3248 
3249 

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