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