Showing error 1650

User: Jiri Slaby
Error type: Invalid Pointer Dereference
Error type description: A pointer which is invalid is being dereferenced
File location: drivers/usb/misc/sisusbvga/sisusb.c
Line in file: 3110
Project: Linux Kernel
Project version: 2.6.28
Confirmation: Fixed by a1645eefc8358d0a9dbeba254e51aa89de4d80a4
Tools: Smatch (1.59)
Entered: 2013-09-10 07:54:05 UTC


Source:

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