Version:  2.0.40 2.2.26 2.4.37 2.6.39 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15

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

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