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        const char *ramtypetext2[] = {  "SDR SDRAM", "SDR SGRAM",
2127                                        "DDR SDRAM", "DDR SGRAM" };
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        dev_info(&sisusb->sisusb_dev->dev, "%dMB %s %s, bus width %d\n", (sisusb->vramsize >> 20), ramtypetext1,
2160                        ramtypetext2[ramtype], bw);
2161}
2162
2163static int
2164sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb)
2165{
2166        struct sisusb_packet packet;
2167        int ret;
2168        u32 tmp32;
2169
2170        /* Do some magic */
2171        packet.header  = 0x001f;
2172        packet.address = 0x00000324;
2173        packet.data    = 0x00000004;
2174        ret = sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2175
2176        packet.header  = 0x001f;
2177        packet.address = 0x00000364;
2178        packet.data    = 0x00000004;
2179        ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2180
2181        packet.header  = 0x001f;
2182        packet.address = 0x00000384;
2183        packet.data    = 0x00000004;
2184        ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2185
2186        packet.header  = 0x001f;
2187        packet.address = 0x00000100;
2188        packet.data    = 0x00000700;
2189        ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2190
2191        packet.header  = 0x000f;
2192        packet.address = 0x00000004;
2193        ret |= sisusb_send_bridge_packet(sisusb, 6, &packet, 0);
2194        packet.data |= 0x17;
2195        ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2196
2197        /* Init BAR 0 (VRAM) */
2198        ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2199        ret |= sisusb_write_pci_config(sisusb, 0x10, 0xfffffff0);
2200        ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2201        tmp32 &= 0x0f;
2202        tmp32 |= SISUSB_PCI_MEMBASE;
2203        ret |= sisusb_write_pci_config(sisusb, 0x10, tmp32);
2204
2205        /* Init BAR 1 (MMIO) */
2206        ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2207        ret |= sisusb_write_pci_config(sisusb, 0x14, 0xfffffff0);
2208        ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2209        tmp32 &= 0x0f;
2210        tmp32 |= SISUSB_PCI_MMIOBASE;
2211        ret |= sisusb_write_pci_config(sisusb, 0x14, tmp32);
2212
2213        /* Init BAR 2 (i/o ports) */
2214        ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2215        ret |= sisusb_write_pci_config(sisusb, 0x18, 0xfffffff0);
2216        ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2217        tmp32 &= 0x0f;
2218        tmp32 |= SISUSB_PCI_IOPORTBASE;
2219        ret |= sisusb_write_pci_config(sisusb, 0x18, tmp32);
2220
2221        /* Enable memory and i/o access */
2222        ret |= sisusb_read_pci_config(sisusb, 0x04, &tmp32);
2223        tmp32 |= 0x3;
2224        ret |= sisusb_write_pci_config(sisusb, 0x04, tmp32);
2225
2226        if (ret == 0) {
2227                /* Some further magic */
2228                packet.header  = 0x001f;
2229                packet.address = 0x00000050;
2230                packet.data    = 0x000000ff;
2231                ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2232        }
2233
2234        return ret;
2235}
2236
2237/* Initialize the graphics device (return 0 on success)
2238 * This initializes the net2280 as well as the PCI registers
2239 * of the graphics board.
2240 */
2241
2242static int
2243sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
2244{
2245        int ret = 0, test = 0;
2246        u32 tmp32;
2247
2248        if (sisusb->devinit == 1) {
2249                /* Read PCI BARs and see if they have been set up */
2250                ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2251                if (ret) return ret;
2252                if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE) test++;
2253
2254                ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2255                if (ret) return ret;
2256                if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE) test++;
2257
2258                ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2259                if (ret) return ret;
2260                if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE) test++;
2261        }
2262
2263        /* No? So reset the device */
2264        if ((sisusb->devinit == 0) || (test != 3)) {
2265
2266                ret |= sisusb_do_init_gfxdevice(sisusb);
2267
2268                if (ret == 0)
2269                        sisusb->devinit = 1;
2270
2271        }
2272
2273        if (sisusb->devinit) {
2274                /* Initialize the graphics core */
2275                if (sisusb_init_gfxcore(sisusb) == 0) {
2276                        sisusb->gfxinit = 1;
2277                        sisusb_get_ramconfig(sisusb);
2278                        ret |= sisusb_set_default_mode(sisusb, 1);
2279                        ret |= sisusb_setup_screen(sisusb, 1, initscreen);
2280                }
2281        }
2282
2283        return ret;
2284}
2285
2286
2287#ifdef INCL_SISUSB_CON
2288
2289/* Set up default text mode:
2290   - Set text mode (0x03)
2291   - Upload default font
2292   - Upload user font (if available)
2293*/
2294
2295int
2296sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
2297{
2298        int ret = 0, slot = sisusb->font_slot, i;
2299        const struct font_desc *myfont;
2300        u8 *tempbuf;
2301        u16 *tempbufb;
2302        size_t written;
2303        static const char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2304        static const char bootlogo[] = "(o_ //\\ V_/_";
2305
2306        /* sisusb->lock is down */
2307
2308        if (!sisusb->SiS_Pr)
2309                return 1;
2310
2311        sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2312        sisusb->SiS_Pr->sisusb = (void *)sisusb;
2313
2314        /* Set mode 0x03 */
2315        SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
2316
2317        if (!(myfont = find_font("VGA8x16")))
2318                return 1;
2319
2320        if (!(tempbuf = vmalloc(8192)))
2321                return 1;
2322
2323        for (i = 0; i < 256; i++)
2324                memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
2325
2326        /* Upload default font */
2327        ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, 0, 1, NULL, 16, 0);
2328
2329        vfree(tempbuf);
2330
2331        /* Upload user font (and reset current slot) */
2332        if (sisusb->font_backup) {
2333                ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
2334                                8192, sisusb->font_backup_512, 1, NULL,
2335                                sisusb->font_backup_height, 0);
2336                if (slot != 2)
2337                        sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
2338                                        NULL, 16, 0);
2339        }
2340
2341        if (init && !sisusb->scrbuf) {
2342
2343                if ((tempbuf = vmalloc(8192))) {
2344
2345                        i = 4096;
2346                        tempbufb = (u16 *)tempbuf;
2347                        while (i--)
2348                                *(tempbufb++) = 0x0720;
2349
2350                        i = 0;
2351                        tempbufb = (u16 *)tempbuf;
2352                        while (bootlogo[i]) {
2353                                *(tempbufb++) = 0x0700 | bootlogo[i++];
2354                                if (!(i % 4))
2355                                        tempbufb += 76;
2356                        }
2357
2358                        i = 0;
2359                        tempbufb = (u16 *)tempbuf + 6;
2360                        while (bootstring[i])
2361                                *(tempbufb++) = 0x0700 | bootstring[i++];
2362
2363                        ret |= sisusb_copy_memory(sisusb, tempbuf,
2364                                sisusb->vrambase, 8192, &written);
2365
2366                        vfree(tempbuf);
2367
2368                }
2369
2370        } else if (sisusb->scrbuf) {
2371
2372                ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
2373                                sisusb->vrambase, sisusb->scrbuf_size, &written);
2374
2375        }
2376
2377        if (sisusb->sisusb_cursor_size_from >= 0 &&
2378            sisusb->sisusb_cursor_size_to >= 0) {
2379                sisusb_setidxreg(sisusb, SISCR, 0x0a,
2380                                sisusb->sisusb_cursor_size_from);
2381                sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
2382                                sisusb->sisusb_cursor_size_to);
2383        } else {
2384                sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
2385                sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
2386                sisusb->sisusb_cursor_size_to = -1;
2387        }
2388
2389        slot = sisusb->sisusb_cursor_loc;
2390        if(slot < 0) slot = 0;
2391
2392        sisusb->sisusb_cursor_loc = -1;
2393        sisusb->bad_cursor_pos = 1;
2394
2395        sisusb_set_cursor(sisusb, slot);
2396
2397        sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
2398        sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
2399
2400        sisusb->textmodedestroyed = 0;
2401
2402        /* sisusb->lock is down */
2403
2404        return ret;
2405}
2406
2407#endif
2408
2409/* fops */
2410
2411static int
2412sisusb_open(struct inode *inode, struct file *file)
2413{
2414        struct sisusb_usb_data *sisusb;
2415        struct usb_interface *interface;
2416        int subminor = iminor(inode);
2417
2418        if (!(interface = usb_find_interface(&sisusb_driver, subminor))) {
2419                return -ENODEV;
2420        }
2421
2422        if (!(sisusb = usb_get_intfdata(interface))) {
2423                return -ENODEV;
2424        }
2425
2426        mutex_lock(&sisusb->lock);
2427
2428        if (!sisusb->present || !sisusb->ready) {
2429                mutex_unlock(&sisusb->lock);
2430                return -ENODEV;
2431        }
2432
2433        if (sisusb->isopen) {
2434                mutex_unlock(&sisusb->lock);
2435                return -EBUSY;
2436        }
2437
2438        if (!sisusb->devinit) {
2439                if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH ||
2440                    sisusb->sisusb_dev->speed == USB_SPEED_SUPER) {
2441                        if (sisusb_init_gfxdevice(sisusb, 0)) {
2442                                mutex_unlock(&sisusb->lock);
2443                                dev_err(&sisusb->sisusb_dev->dev, "Failed to initialize device\n");
2444                                return -EIO;
2445                        }
2446                } else {
2447                        mutex_unlock(&sisusb->lock);
2448                        dev_err(&sisusb->sisusb_dev->dev, "Device not attached to USB 2.0 hub\n");
2449                        return -EIO;
2450                }
2451        }
2452
2453        /* Increment usage count for our sisusb */
2454        kref_get(&sisusb->kref);
2455
2456        sisusb->isopen = 1;
2457
2458        file->private_data = sisusb;
2459
2460        mutex_unlock(&sisusb->lock);
2461
2462        return 0;
2463}
2464
2465void
2466sisusb_delete(struct kref *kref)
2467{
2468        struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
2469
2470        if (!sisusb)
2471                return;
2472
2473        if (sisusb->sisusb_dev)
2474                usb_put_dev(sisusb->sisusb_dev);
2475
2476        sisusb->sisusb_dev = NULL;
2477        sisusb_free_buffers(sisusb);
2478        sisusb_free_urbs(sisusb);
2479#ifdef INCL_SISUSB_CON
2480        kfree(sisusb->SiS_Pr);
2481#endif
2482        kfree(sisusb);
2483}
2484
2485static int
2486sisusb_release(struct inode *inode, struct file *file)
2487{
2488        struct sisusb_usb_data *sisusb;
2489
2490        if (!(sisusb = file->private_data))
2491                return -ENODEV;
2492
2493        mutex_lock(&sisusb->lock);
2494
2495        if (sisusb->present) {
2496                /* Wait for all URBs to finish if device still present */
2497                if (!sisusb_wait_all_out_complete(sisusb))
2498                        sisusb_kill_all_busy(sisusb);
2499        }
2500
2501        sisusb->isopen = 0;
2502        file->private_data = NULL;
2503
2504        mutex_unlock(&sisusb->lock);
2505
2506        /* decrement the usage count on our device */
2507        kref_put(&sisusb->kref, sisusb_delete);
2508
2509        return 0;
2510}
2511
2512static ssize_t
2513sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
2514{
2515        struct sisusb_usb_data *sisusb;
2516        ssize_t bytes_read = 0;
2517        int errno = 0;
2518        u8 buf8;
2519        u16 buf16;
2520        u32 buf32, address;
2521
2522        if (!(sisusb = file->private_data))
2523                return -ENODEV;
2524
2525        mutex_lock(&sisusb->lock);
2526
2527        /* Sanity check */
2528        if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2529                mutex_unlock(&sisusb->lock);
2530                return -ENODEV;
2531        }
2532
2533        if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2534            (*ppos) <  SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2535
2536                address = (*ppos) -
2537                        SISUSB_PCI_PSEUDO_IOPORTBASE +
2538                        SISUSB_PCI_IOPORTBASE;
2539
2540                /* Read i/o ports
2541                 * Byte, word and long(32) can be read. As this
2542                 * emulates inX instructions, the data returned is
2543                 * in machine-endianness.
2544                 */
2545                switch (count) {
2546
2547                        case 1:
2548                                if (sisusb_read_memio_byte(sisusb,
2549                                                        SISUSB_TYPE_IO,
2550                                                        address, &buf8))
2551                                        errno = -EIO;
2552                                else if (put_user(buf8, (u8 __user *)buffer))
2553                                        errno = -EFAULT;
2554                                else
2555                                        bytes_read = 1;
2556
2557                                break;
2558
2559                        case 2:
2560                                if (sisusb_read_memio_word(sisusb,
2561                                                        SISUSB_TYPE_IO,
2562                                                        address, &buf16))
2563                                        errno = -EIO;
2564                                else if (put_user(buf16, (u16 __user *)buffer))
2565                                        errno = -EFAULT;
2566                                else
2567                                        bytes_read = 2;
2568
2569                                break;
2570
2571                        case 4:
2572                                if (sisusb_read_memio_long(sisusb,
2573                                                        SISUSB_TYPE_IO,
2574                                                        address, &buf32))
2575                                        errno = -EIO;
2576                                else if (put_user(buf32, (u32 __user *)buffer))
2577                                        errno = -EFAULT;
2578                                else
2579                                        bytes_read = 4;
2580
2581                                break;
2582
2583                        default:
2584                                errno = -EIO;
2585
2586                }
2587
2588        } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2589                   (*ppos) <  SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2590
2591                address = (*ppos) -
2592                        SISUSB_PCI_PSEUDO_MEMBASE +
2593                        SISUSB_PCI_MEMBASE;
2594
2595                /* Read video ram
2596                 * Remember: Data delivered is never endian-corrected
2597                 */
2598                errno = sisusb_read_mem_bulk(sisusb, address,
2599                                        NULL, count, buffer, &bytes_read);
2600
2601                if (bytes_read)
2602                        errno = bytes_read;
2603
2604        } else  if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2605                    (*ppos) <  SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) {
2606
2607                address = (*ppos) -
2608                        SISUSB_PCI_PSEUDO_MMIOBASE +
2609                        SISUSB_PCI_MMIOBASE;
2610
2611                /* Read MMIO
2612                 * Remember: Data delivered is never endian-corrected
2613                 */
2614                errno = sisusb_read_mem_bulk(sisusb, address,
2615                                        NULL, count, buffer, &bytes_read);
2616
2617                if (bytes_read)
2618                        errno = bytes_read;
2619
2620        } else  if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2621                    (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
2622
2623                if (count != 4) {
2624                        mutex_unlock(&sisusb->lock);
2625                        return -EINVAL;
2626                }
2627
2628                address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2629
2630                /* Read PCI config register
2631                 * Return value delivered in machine endianness.
2632                 */
2633                if (sisusb_read_pci_config(sisusb, address, &buf32))
2634                        errno = -EIO;
2635                else if (put_user(buf32, (u32 __user *)buffer))
2636                        errno = -EFAULT;
2637                else
2638                        bytes_read = 4;
2639
2640        } else {
2641
2642                errno = -EBADFD;
2643
2644        }
2645
2646        (*ppos) += bytes_read;
2647
2648        mutex_unlock(&sisusb->lock);
2649
2650        return errno ? errno : bytes_read;
2651}
2652
2653static ssize_t
2654sisusb_write(struct file *file, const char __user *buffer, size_t count,
2655                                                                loff_t *ppos)
2656{
2657        struct sisusb_usb_data *sisusb;
2658        int errno = 0;
2659        ssize_t bytes_written = 0;
2660        u8 buf8;
2661        u16 buf16;
2662        u32 buf32, address;
2663
2664        if (!(sisusb = file->private_data))
2665                return -ENODEV;
2666
2667        mutex_lock(&sisusb->lock);
2668
2669        /* Sanity check */
2670        if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2671                mutex_unlock(&sisusb->lock);
2672                return -ENODEV;
2673        }
2674
2675        if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2676            (*ppos) <  SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2677
2678                address = (*ppos) -
2679                        SISUSB_PCI_PSEUDO_IOPORTBASE +
2680                        SISUSB_PCI_IOPORTBASE;
2681
2682                /* Write i/o ports
2683                 * Byte, word and long(32) can be written. As this
2684                 * emulates outX instructions, the data is expected
2685                 * in machine-endianness.
2686                 */
2687                switch (count) {
2688
2689                        case 1:
2690                                if (get_user(buf8, (u8 __user *)buffer))
2691                                        errno = -EFAULT;
2692                                else if (sisusb_write_memio_byte(sisusb,
2693                                                        SISUSB_TYPE_IO,
2694                                                        address, buf8))
2695                                        errno = -EIO;
2696                                else
2697                                        bytes_written = 1;
2698
2699                                break;
2700
2701                        case 2:
2702                                if (get_user(buf16, (u16 __user *)buffer))
2703                                        errno = -EFAULT;
2704                                else if (sisusb_write_memio_word(sisusb,
2705                                                        SISUSB_TYPE_IO,
2706                                                        address, buf16))
2707                                        errno = -EIO;
2708                                else
2709                                        bytes_written = 2;
2710
2711                                break;
2712
2713                        case 4:
2714                                if (get_user(buf32, (u32 __user *)buffer))
2715                                        errno = -EFAULT;
2716                                else if (sisusb_write_memio_long(sisusb,
2717                                                        SISUSB_TYPE_IO,
2718                                                        address, buf32))
2719                                        errno = -EIO;
2720                                else
2721                                        bytes_written = 4;
2722
2723                                break;
2724
2725                        default:
2726                                errno = -EIO;
2727                }
2728
2729        } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2730                   (*ppos) <  SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2731
2732                address = (*ppos) -
2733                        SISUSB_PCI_PSEUDO_MEMBASE +
2734                        SISUSB_PCI_MEMBASE;
2735
2736                /* Write video ram.
2737                 * Buffer is copied 1:1, therefore, on big-endian
2738                 * machines, the data must be swapped by userland
2739                 * in advance (if applicable; no swapping in 8bpp
2740                 * mode or if YUV data is being transferred).
2741                 */
2742                errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2743                                        count, buffer, 0, &bytes_written);
2744
2745                if (bytes_written)
2746                        errno = bytes_written;
2747
2748        } else  if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2749                    (*ppos) <  SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) {
2750
2751                address = (*ppos) -
2752                        SISUSB_PCI_PSEUDO_MMIOBASE +
2753                        SISUSB_PCI_MMIOBASE;
2754
2755                /* Write MMIO.
2756                 * Buffer is copied 1:1, therefore, on big-endian
2757                 * machines, the data must be swapped by userland
2758                 * in advance.
2759                 */
2760                errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2761                                        count, buffer, 0, &bytes_written);
2762
2763                if (bytes_written)
2764                        errno = bytes_written;
2765
2766        } else  if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2767                    (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + SISUSB_PCI_PCONFSIZE) {
2768
2769                if (count != 4) {
2770                        mutex_unlock(&sisusb->lock);
2771                        return -EINVAL;
2772                }
2773
2774                address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2775
2776                /* Write PCI config register.
2777                 * Given value expected in machine endianness.
2778                 */
2779                if (get_user(buf32, (u32 __user *)buffer))
2780                        errno = -EFAULT;
2781                else if (sisusb_write_pci_config(sisusb, address, buf32))
2782                        errno = -EIO;
2783                else
2784                        bytes_written = 4;
2785
2786
2787        } else {
2788
2789                /* Error */
2790                errno = -EBADFD;
2791
2792        }
2793
2794        (*ppos) += bytes_written;
2795
2796        mutex_unlock(&sisusb->lock);
2797
2798        return errno ? errno : bytes_written;
2799}
2800
2801static loff_t
2802sisusb_lseek(struct file *file, loff_t offset, int orig)
2803{
2804        struct sisusb_usb_data *sisusb;
2805        loff_t ret;
2806
2807        if (!(sisusb = file->private_data))
2808                return -ENODEV;
2809
2810        mutex_lock(&sisusb->lock);
2811
2812        /* Sanity check */
2813        if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2814                mutex_unlock(&sisusb->lock);
2815                return -ENODEV;
2816        }
2817
2818        switch (orig) {
2819                case 0:
2820                        file->f_pos = offset;
2821                        ret = file->f_pos;
2822                        /* never negative, no force_successful_syscall needed */
2823                        break;
2824                case 1:
2825                        file->f_pos += offset;
2826                        ret = file->f_pos;
2827                        /* never negative, no force_successful_syscall needed */
2828                        break;
2829                default:
2830                        /* seeking relative to "end of file" is not supported */
2831                        ret = -EINVAL;
2832        }
2833
2834        mutex_unlock(&sisusb->lock);
2835        return ret;
2836}
2837
2838static int
2839sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
2840                                                        unsigned long arg)
2841{
2842        int     retval, port, length;
2843        u32     address;
2844
2845        /* All our commands require the device
2846         * to be initialized.
2847         */
2848        if (!sisusb->devinit)
2849                return -ENODEV;
2850
2851        port = y->data3 -
2852                SISUSB_PCI_PSEUDO_IOPORTBASE +
2853                SISUSB_PCI_IOPORTBASE;
2854
2855        switch (y->operation) {
2856                case SUCMD_GET:
2857                        retval = sisusb_getidxreg(sisusb, port,
2858                                                         y->data0, &y->data1);
2859                        if (!retval) {
2860                                if (copy_to_user((void __user *)arg, y,
2861                                                        sizeof(*y)))
2862                                        retval = -EFAULT;
2863                        }
2864                        break;
2865
2866                case SUCMD_SET:
2867                        retval = sisusb_setidxreg(sisusb, port,
2868                                                y->data0, y->data1);
2869                        break;
2870
2871                case SUCMD_SETOR:
2872                        retval = sisusb_setidxregor(sisusb, port,
2873                                                y->data0, y->data1);
2874                        break;
2875
2876                case SUCMD_SETAND:
2877                        retval = sisusb_setidxregand(sisusb, port,
2878                                                y->data0, y->data1);
2879                        break;
2880
2881                case SUCMD_SETANDOR:
2882                        retval = sisusb_setidxregandor(sisusb, port,
2883                                                y->data0, y->data1, y->data2);
2884                        break;
2885
2886                case SUCMD_SETMASK:
2887                        retval = sisusb_setidxregmask(sisusb, port,
2888                                                y->data0, y->data1, y->data2);
2889                        break;
2890
2891                case SUCMD_CLRSCR:
2892                        /* Gfx core must be initialized */
2893                        if (!sisusb->gfxinit)
2894                                return -ENODEV;
2895
2896                        length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
2897                        address = y->data3 -
2898                                SISUSB_PCI_PSEUDO_MEMBASE +
2899                                SISUSB_PCI_MEMBASE;
2900                        retval = sisusb_clear_vram(sisusb, address, length);
2901                        break;
2902
2903                case SUCMD_HANDLETEXTMODE:
2904                        retval = 0;
2905#ifdef INCL_SISUSB_CON
2906                        /* Gfx core must be initialized, SiS_Pr must exist */
2907                        if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2908                                return -ENODEV;
2909
2910                        switch (y->data0) {
2911                        case 0:
2912                                retval = sisusb_reset_text_mode(sisusb, 0);
2913                                break;
2914                        case 1:
2915                                sisusb->textmodedestroyed = 1;
2916                                break;
2917                        }
2918#endif
2919                        break;
2920
2921#ifdef INCL_SISUSB_CON
2922                case SUCMD_SETMODE:
2923                        /* Gfx core must be initialized, SiS_Pr must exist */
2924                        if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2925                                return -ENODEV;
2926
2927                        retval = 0;
2928
2929                        sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2930                        sisusb->SiS_Pr->sisusb = (void *)sisusb;
2931
2932                        if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
2933                                retval = -EINVAL;
2934
2935                        break;
2936
2937                case SUCMD_SETVESAMODE:
2938                        /* Gfx core must be initialized, SiS_Pr must exist */
2939                        if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2940                                return -ENODEV;
2941
2942                        retval = 0;
2943
2944                        sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2945                        sisusb->SiS_Pr->sisusb = (void *)sisusb;
2946
2947                        if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
2948                                retval = -EINVAL;
2949
2950                        break;
2951#endif
2952
2953                default:
2954                        retval = -EINVAL;
2955        }
2956
2957        if (retval > 0)
2958                retval = -EIO;
2959
2960        return retval;
2961}
2962
2963static long
2964sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2965{
2966        struct sisusb_usb_data *sisusb;
2967        struct sisusb_info x;
2968        struct sisusb_command y;
2969        long retval = 0;
2970        u32 __user *argp = (u32 __user *)arg;
2971
2972        if (!(sisusb = file->private_data))
2973                return -ENODEV;
2974
2975        mutex_lock(&sisusb->lock);
2976
2977        /* Sanity check */
2978        if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2979                retval = -ENODEV;
2980                goto err_out;
2981        }
2982
2983        switch (cmd) {
2984
2985                case SISUSB_GET_CONFIG_SIZE:
2986
2987                        if (put_user(sizeof(x), argp))
2988                                retval = -EFAULT;
2989
2990                        break;
2991
2992                case SISUSB_GET_CONFIG:
2993
2994                        x.sisusb_id         = SISUSB_ID;
2995                        x.sisusb_version    = SISUSB_VERSION;
2996                        x.sisusb_revision   = SISUSB_REVISION;
2997                        x.sisusb_patchlevel = SISUSB_PATCHLEVEL;
2998                        x.sisusb_gfxinit    = sisusb->gfxinit;
2999                        x.sisusb_vrambase   = SISUSB_PCI_PSEUDO_MEMBASE;
3000                        x.sisusb_mmiobase   = SISUSB_PCI_PSEUDO_MMIOBASE;
3001                        x.sisusb_iobase     = SISUSB_PCI_PSEUDO_IOPORTBASE;
3002                        x.sisusb_pcibase    = SISUSB_PCI_PSEUDO_PCIBASE;
3003                        x.sisusb_vramsize   = sisusb->vramsize;
3004                        x.sisusb_minor      = sisusb->minor;
3005                        x.sisusb_fbdevactive= 0;
3006#ifdef INCL_SISUSB_CON
3007                        x.sisusb_conactive  = sisusb->haveconsole ? 1 : 0;
3008#else
3009                        x.sisusb_conactive  = 0;
3010#endif
3011                        memset(x.sisusb_reserved, 0, sizeof(x.sisusb_reserved));
3012
3013                        if (copy_to_user((void __user *)arg, &x, sizeof(x)))
3014                                retval = -EFAULT;
3015
3016                        break;
3017
3018                case SISUSB_COMMAND:
3019
3020                        if (copy_from_user(&y, (void __user *)arg, sizeof(y)))
3021                                retval = -EFAULT;
3022                        else
3023                                retval = sisusb_handle_command(sisusb, &y, arg);
3024
3025                        break;
3026
3027                default:
3028                        retval = -ENOTTY;
3029                        break;
3030        }
3031
3032err_out:
3033        mutex_unlock(&sisusb->lock);
3034        return retval;
3035}
3036
3037#ifdef SISUSB_NEW_CONFIG_COMPAT
3038static long
3039sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
3040{
3041        long retval;
3042
3043        switch (cmd) {
3044                case SISUSB_GET_CONFIG_SIZE:
3045                case SISUSB_GET_CONFIG:
3046                case SISUSB_COMMAND:
3047                        retval = sisusb_ioctl(f, cmd, arg);
3048                        return retval;
3049
3050                default:
3051                        return -ENOIOCTLCMD;
3052        }
3053}
3054#endif
3055
3056static const struct file_operations usb_sisusb_fops = {
3057        .owner =        THIS_MODULE,
3058        .open =         sisusb_open,
3059        .release =      sisusb_release,
3060        .read =         sisusb_read,
3061        .write =        sisusb_write,
3062        .llseek =       sisusb_lseek,
3063#ifdef SISUSB_NEW_CONFIG_COMPAT
3064        .compat_ioctl = sisusb_compat_ioctl,
3065#endif
3066        .unlocked_ioctl = sisusb_ioctl
3067};
3068
3069static struct usb_class_driver usb_sisusb_class = {
3070        .name =         "sisusbvga%d",
3071        .fops =         &usb_sisusb_fops,
3072        .minor_base =   SISUSB_MINOR
3073};
3074
3075static int sisusb_probe(struct usb_interface *intf,
3076                        const struct usb_device_id *id)
3077{
3078        struct usb_device *dev = interface_to_usbdev(intf);
3079        struct sisusb_usb_data *sisusb;
3080        int retval = 0, i;
3081
3082        dev_info(&dev->dev, "USB2VGA dongle found at address %d\n",
3083                dev->devnum);
3084
3085        /* Allocate memory for our private */
3086        if (!(sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL))) {
3087                dev_err(&dev->dev, "Failed to allocate memory for private data\n");
3088                return -ENOMEM;
3089        }
3090        kref_init(&sisusb->kref);
3091
3092        mutex_init(&(sisusb->lock));
3093
3094        /* Register device */
3095        if ((retval = usb_register_dev(intf, &usb_sisusb_class))) {
3096                dev_err(&sisusb->sisusb_dev->dev, "Failed to get a minor for device %d\n",
3097                        dev->devnum);
3098                retval = -ENODEV;
3099                goto error_1;
3100        }
3101
3102        sisusb->sisusb_dev = dev;
3103        sisusb->minor      = intf->minor;
3104        sisusb->vrambase   = SISUSB_PCI_MEMBASE;
3105        sisusb->mmiobase   = SISUSB_PCI_MMIOBASE;
3106        sisusb->mmiosize   = SISUSB_PCI_MMIOSIZE;
3107        sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
3108        /* Everything else is zero */
3109
3110        /* Allocate buffers */
3111        sisusb->ibufsize = SISUSB_IBUF_SIZE;
3112        if (!(sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL))) {
3113                dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for input buffer");
3114                retval = -ENOMEM;
3115                goto error_2;
3116        }
3117
3118        sisusb->numobufs = 0;
3119        sisusb->obufsize = SISUSB_OBUF_SIZE;
3120        for (i = 0; i < NUMOBUFS; i++) {
3121                if (!(sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL))) {
3122                        if (i == 0) {
3123                                dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for output buffer\n");
3124                                retval = -ENOMEM;
3125                                goto error_3;
3126                        }
3127                        break;
3128                } else
3129                        sisusb->numobufs++;
3130
3131        }
3132
3133        /* Allocate URBs */
3134        if (!(sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL))) {
3135                dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n");
3136                retval = -ENOMEM;
3137                goto error_3;
3138        }
3139        sisusb->completein = 1;
3140
3141        for (i = 0; i < sisusb->numobufs; i++) {
3142                if (!(sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL))) {
3143                        dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n");
3144                        retval = -ENOMEM;
3145                        goto error_4;
3146                }
3147                sisusb->urbout_context[i].sisusb = (void *)sisusb;
3148                sisusb->urbout_context[i].urbindex = i;
3149                sisusb->urbstatus[i] = 0;
3150        }
3151
3152        dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n", sisusb->numobufs);
3153
3154#ifdef INCL_SISUSB_CON
3155        /* Allocate our SiS_Pr */
3156        if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) {
3157                dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate SiS_Pr\n");
3158        }
3159#endif
3160
3161        /* Do remaining init stuff */
3162
3163        init_waitqueue_head(&sisusb->wait_q);
3164
3165        usb_set_intfdata(intf, sisusb);
3166
3167        usb_get_dev(sisusb->sisusb_dev);
3168
3169        sisusb->present = 1;
3170
3171        if (dev->speed == USB_SPEED_HIGH || dev->speed == USB_SPEED_SUPER) {
3172                int initscreen = 1;
3173#ifdef INCL_SISUSB_CON
3174                if (sisusb_first_vc > 0 &&
3175                    sisusb_last_vc > 0 &&
3176                    sisusb_first_vc <= sisusb_last_vc &&
3177                    sisusb_last_vc <= MAX_NR_CONSOLES)
3178                        initscreen = 0;
3179#endif
3180                if (sisusb_init_gfxdevice(sisusb, initscreen))
3181                        dev_err(&sisusb->sisusb_dev->dev, "Failed to early initialize device\n");
3182
3183        } else
3184                dev_info(&sisusb->sisusb_dev->dev, "Not attached to USB 2.0 hub, deferring init\n");
3185
3186        sisusb->ready = 1;
3187
3188#ifdef SISUSBENDIANTEST
3189        dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST ***\n");
3190        sisusb_testreadwrite(sisusb);
3191        dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST END ***\n");
3192#endif
3193
3194#ifdef INCL_SISUSB_CON
3195        sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
3196#endif
3197
3198        return 0;
3199
3200error_4:
3201        sisusb_free_urbs(sisusb);
3202error_3:
3203        sisusb_free_buffers(sisusb);
3204error_2:
3205        usb_deregister_dev(intf, &usb_sisusb_class);
3206error_1:
3207        kfree(sisusb);
3208        return retval;
3209}
3210
3211static void sisusb_disconnect(struct usb_interface *intf)
3212{
3213        struct sisusb_usb_data *sisusb;
3214
3215        /* This should *not* happen */
3216        if (!(sisusb = usb_get_intfdata(intf)))
3217                return;
3218
3219#ifdef INCL_SISUSB_CON
3220        sisusb_console_exit(sisusb);
3221#endif
3222
3223        usb_deregister_dev(intf, &usb_sisusb_class);
3224
3225        mutex_lock(&sisusb->lock);
3226
3227        /* Wait for all URBs to complete and kill them in case (MUST do) */
3228        if (!sisusb_wait_all_out_complete(sisusb))
3229                sisusb_kill_all_busy(sisusb);
3230
3231        usb_set_intfdata(intf, NULL);
3232
3233        sisusb->present = 0;
3234        sisusb->ready = 0;
3235
3236        mutex_unlock(&sisusb->lock);
3237
3238        /* decrement our usage count */
3239        kref_put(&sisusb->kref, sisusb_delete);
3240}
3241
3242static const struct usb_device_id sisusb_table[] = {
3243        { USB_DEVICE(0x0711, 0x0550) },
3244        { USB_DEVICE(0x0711, 0x0900) },
3245        { USB_DEVICE(0x0711, 0x0901) },
3246        { USB_DEVICE(0x0711, 0x0902) },
3247        { USB_DEVICE(0x0711, 0x0903) },
3248        { USB_DEVICE(0x0711, 0x0918) },
3249        { USB_DEVICE(0x0711, 0x0920) },
3250        { USB_DEVICE(0x0711, 0x0950) },
3251        { USB_DEVICE(0x182d, 0x021c) },
3252        { USB_DEVICE(0x182d, 0x0269) },
3253        { }
3254};
3255
3256MODULE_DEVICE_TABLE (usb, sisusb_table);
3257
3258static struct usb_driver sisusb_driver = {
3259        .name =         "sisusb",
3260        .probe =        sisusb_probe,
3261        .disconnect =   sisusb_disconnect,
3262        .id_table =     sisusb_table,
3263};
3264
3265static int __init usb_sisusb_init(void)
3266{
3267
3268#ifdef INCL_SISUSB_CON
3269        sisusb_init_concode();
3270#endif
3271
3272        return usb_register(&sisusb_driver);
3273}
3274
3275static void __exit usb_sisusb_exit(void)
3276{
3277        usb_deregister(&sisusb_driver);
3278}
3279
3280module_init(usb_sisusb_init);
3281module_exit(usb_sisusb_exit);
3282
3283MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3284MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3285MODULE_LICENSE("GPL");
3286
3287