Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

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