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