root/drivers/usb/misc/sisusbvga/sisusb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sisusb_free_buffers
  2. sisusb_free_urbs
  3. sisusb_all_free
  4. sisusb_kill_all_busy
  5. sisusb_wait_all_out_complete
  6. sisusb_outurb_available
  7. sisusb_get_free_outbuf
  8. sisusb_alloc_outbuf
  9. sisusb_free_outbuf
  10. sisusb_bulk_completeout
  11. sisusb_bulkout_msg
  12. sisusb_bulk_completein
  13. sisusb_bulkin_msg
  14. sisusb_send_bulk_msg
  15. sisusb_recv_bulk_msg
  16. sisusb_send_packet
  17. sisusb_send_bridge_packet
  18. sisusb_write_memio_byte
  19. sisusb_write_memio_word
  20. sisusb_write_memio_24bit
  21. sisusb_write_memio_long
  22. sisusb_write_mem_bulk
  23. sisusb_read_memio_byte
  24. sisusb_read_memio_word
  25. sisusb_read_memio_24bit
  26. sisusb_read_memio_long
  27. sisusb_read_mem_bulk
  28. sisusb_setreg
  29. sisusb_getreg
  30. sisusb_setidxreg
  31. sisusb_getidxreg
  32. sisusb_setidxregandor
  33. sisusb_setidxregmask
  34. sisusb_setidxregor
  35. sisusb_setidxregand
  36. sisusb_writeb
  37. sisusb_readb
  38. sisusb_copy_memory
  39. sisusb_read_memory
  40. sisusb_testreadwrite
  41. sisusb_write_pci_config
  42. sisusb_read_pci_config
  43. sisusb_clear_vram
  44. sisusb_triggersr16
  45. sisusb_getbuswidth
  46. sisusb_verify_mclk
  47. sisusb_set_rank
  48. sisusb_check_rbc
  49. sisusb_check_ranks
  50. sisusb_get_sdram_size
  51. sisusb_setup_screen
  52. sisusb_set_default_mode
  53. sisusb_init_gfxcore
  54. sisusb_get_ramconfig
  55. sisusb_do_init_gfxdevice
  56. sisusb_init_gfxdevice
  57. sisusb_reset_text_mode
  58. sisusb_open
  59. sisusb_delete
  60. sisusb_release
  61. sisusb_read
  62. sisusb_write
  63. sisusb_lseek
  64. sisusb_handle_command
  65. sisusb_ioctl
  66. sisusb_compat_ioctl
  67. sisusb_probe
  68. sisusb_disconnect
  69. usb_sisusb_init
  70. usb_sisusb_exit

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

/* [<][>][^][v][top][bottom][index][help] */