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