Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
0002 /*
0003  * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
0004  *
0005  * Main part
0006  *
0007  * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
0008  *
0009  * If distributed as part of the Linux kernel, this code is licensed under the
0010  * terms of the GPL v2.
0011  *
0012  * Otherwise, the following license terms apply:
0013  *
0014  * * Redistribution and use in source and binary forms, with or without
0015  * * modification, are permitted provided that the following conditions
0016  * * are met:
0017  * * 1) Redistributions of source code must retain the above copyright
0018  * *    notice, this list of conditions and the following disclaimer.
0019  * * 2) Redistributions in binary form must reproduce the above copyright
0020  * *    notice, this list of conditions and the following disclaimer in the
0021  * *    documentation and/or other materials provided with the distribution.
0022  * * 3) The name of the author may not be used to endorse or promote products
0023  * *    derived from this software without specific psisusbr written permission.
0024  * *
0025  * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
0026  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0027  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
0028  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
0029  * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
0030  * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0031  * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0032  * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0033  * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
0034  * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0035  *
0036  * Author:  Thomas Winischhofer <thomas@winischhofer.net>
0037  *
0038  */
0039 
0040 #include <linux/mutex.h>
0041 #include <linux/module.h>
0042 #include <linux/kernel.h>
0043 #include <linux/signal.h>
0044 #include <linux/errno.h>
0045 #include <linux/poll.h>
0046 #include <linux/init.h>
0047 #include <linux/slab.h>
0048 #include <linux/spinlock.h>
0049 #include <linux/kref.h>
0050 #include <linux/usb.h>
0051 #include <linux/vmalloc.h>
0052 
0053 #include "sisusb.h"
0054 #include "sisusb_init.h"
0055 
0056 #ifdef CONFIG_USB_SISUSBVGA_CON
0057 #include <linux/font.h>
0058 #endif
0059 
0060 #define SISUSB_DONTSYNC
0061 
0062 /* Forward declarations / clean-up routines */
0063 
0064 #ifdef CONFIG_USB_SISUSBVGA_CON
0065 static int sisusb_first_vc;
0066 static int sisusb_last_vc;
0067 module_param_named(first, sisusb_first_vc, int, 0);
0068 module_param_named(last, sisusb_last_vc, int, 0);
0069 MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
0070 MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
0071 #endif
0072 
0073 static struct usb_driver sisusb_driver;
0074 
0075 static void sisusb_free_buffers(struct sisusb_usb_data *sisusb)
0076 {
0077     int i;
0078 
0079     for (i = 0; i < NUMOBUFS; i++) {
0080         kfree(sisusb->obuf[i]);
0081         sisusb->obuf[i] = NULL;
0082     }
0083     kfree(sisusb->ibuf);
0084     sisusb->ibuf = NULL;
0085 }
0086 
0087 static void sisusb_free_urbs(struct sisusb_usb_data *sisusb)
0088 {
0089     int i;
0090 
0091     for (i = 0; i < NUMOBUFS; i++) {
0092         usb_free_urb(sisusb->sisurbout[i]);
0093         sisusb->sisurbout[i] = NULL;
0094     }
0095     usb_free_urb(sisusb->sisurbin);
0096     sisusb->sisurbin = NULL;
0097 }
0098 
0099 /* Level 0: USB transport layer */
0100 
0101 /* 1. out-bulks */
0102 
0103 /* out-urb management */
0104 
0105 /* Return 1 if all free, 0 otherwise */
0106 static int sisusb_all_free(struct sisusb_usb_data *sisusb)
0107 {
0108     int i;
0109 
0110     for (i = 0; i < sisusb->numobufs; i++) {
0111 
0112         if (sisusb->urbstatus[i] & SU_URB_BUSY)
0113             return 0;
0114 
0115     }
0116 
0117     return 1;
0118 }
0119 
0120 /* Kill all busy URBs */
0121 static void sisusb_kill_all_busy(struct sisusb_usb_data *sisusb)
0122 {
0123     int i;
0124 
0125     if (sisusb_all_free(sisusb))
0126         return;
0127 
0128     for (i = 0; i < sisusb->numobufs; i++) {
0129 
0130         if (sisusb->urbstatus[i] & SU_URB_BUSY)
0131             usb_kill_urb(sisusb->sisurbout[i]);
0132 
0133     }
0134 }
0135 
0136 /* Return 1 if ok, 0 if error (not all complete within timeout) */
0137 static int sisusb_wait_all_out_complete(struct sisusb_usb_data *sisusb)
0138 {
0139     int timeout = 5 * HZ, i = 1;
0140 
0141     wait_event_timeout(sisusb->wait_q, (i = sisusb_all_free(sisusb)),
0142             timeout);
0143 
0144     return i;
0145 }
0146 
0147 static int sisusb_outurb_available(struct sisusb_usb_data *sisusb)
0148 {
0149     int i;
0150 
0151     for (i = 0; i < sisusb->numobufs; i++) {
0152 
0153         if ((sisusb->urbstatus[i] & (SU_URB_BUSY|SU_URB_ALLOC)) == 0)
0154             return i;
0155 
0156     }
0157 
0158     return -1;
0159 }
0160 
0161 static int sisusb_get_free_outbuf(struct sisusb_usb_data *sisusb)
0162 {
0163     int i, timeout = 5 * HZ;
0164 
0165     wait_event_timeout(sisusb->wait_q,
0166             ((i = sisusb_outurb_available(sisusb)) >= 0), timeout);
0167 
0168     return i;
0169 }
0170 
0171 static int sisusb_alloc_outbuf(struct sisusb_usb_data *sisusb)
0172 {
0173     int i;
0174 
0175     i = sisusb_outurb_available(sisusb);
0176 
0177     if (i >= 0)
0178         sisusb->urbstatus[i] |= SU_URB_ALLOC;
0179 
0180     return i;
0181 }
0182 
0183 static void sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index)
0184 {
0185     if ((index >= 0) && (index < sisusb->numobufs))
0186         sisusb->urbstatus[index] &= ~SU_URB_ALLOC;
0187 }
0188 
0189 /* completion callback */
0190 
0191 static void sisusb_bulk_completeout(struct urb *urb)
0192 {
0193     struct sisusb_urb_context *context = urb->context;
0194     struct sisusb_usb_data *sisusb;
0195 
0196     if (!context)
0197         return;
0198 
0199     sisusb = context->sisusb;
0200 
0201     if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
0202         return;
0203 
0204 #ifndef SISUSB_DONTSYNC
0205     if (context->actual_length)
0206         *(context->actual_length) += urb->actual_length;
0207 #endif
0208 
0209     sisusb->urbstatus[context->urbindex] &= ~SU_URB_BUSY;
0210     wake_up(&sisusb->wait_q);
0211 }
0212 
0213 static int sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index,
0214         unsigned int pipe, void *data, int len, int *actual_length,
0215         int timeout, unsigned int tflags)
0216 {
0217     struct urb *urb = sisusb->sisurbout[index];
0218     int retval, byteswritten = 0;
0219 
0220     /* Set up URB */
0221     urb->transfer_flags = 0;
0222 
0223     usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
0224             sisusb_bulk_completeout,
0225             &sisusb->urbout_context[index]);
0226 
0227     urb->transfer_flags |= tflags;
0228     urb->actual_length = 0;
0229 
0230     /* Set up context */
0231     sisusb->urbout_context[index].actual_length = (timeout) ?
0232             NULL : actual_length;
0233 
0234     /* Declare this urb/buffer in use */
0235     sisusb->urbstatus[index] |= SU_URB_BUSY;
0236 
0237     /* Submit URB */
0238     retval = usb_submit_urb(urb, GFP_KERNEL);
0239 
0240     /* If OK, and if timeout > 0, wait for completion */
0241     if ((retval == 0) && timeout) {
0242         wait_event_timeout(sisusb->wait_q,
0243                 (!(sisusb->urbstatus[index] & SU_URB_BUSY)),
0244                 timeout);
0245         if (sisusb->urbstatus[index] & SU_URB_BUSY) {
0246             /* URB timed out... kill it and report error */
0247             usb_kill_urb(urb);
0248             retval = -ETIMEDOUT;
0249         } else {
0250             /* Otherwise, report urb status */
0251             retval = urb->status;
0252             byteswritten = urb->actual_length;
0253         }
0254     }
0255 
0256     if (actual_length)
0257         *actual_length = byteswritten;
0258 
0259     return retval;
0260 }
0261 
0262 /* 2. in-bulks */
0263 
0264 /* completion callback */
0265 
0266 static void sisusb_bulk_completein(struct urb *urb)
0267 {
0268     struct sisusb_usb_data *sisusb = urb->context;
0269 
0270     if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
0271         return;
0272 
0273     sisusb->completein = 1;
0274     wake_up(&sisusb->wait_q);
0275 }
0276 
0277 static int sisusb_bulkin_msg(struct sisusb_usb_data *sisusb,
0278         unsigned int pipe, void *data, int len,
0279         int *actual_length, int timeout, unsigned int tflags)
0280 {
0281     struct urb *urb = sisusb->sisurbin;
0282     int retval, readbytes = 0;
0283 
0284     urb->transfer_flags = 0;
0285 
0286     usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
0287             sisusb_bulk_completein, sisusb);
0288 
0289     urb->transfer_flags |= tflags;
0290     urb->actual_length = 0;
0291 
0292     sisusb->completein = 0;
0293     retval = usb_submit_urb(urb, GFP_KERNEL);
0294     if (retval == 0) {
0295         wait_event_timeout(sisusb->wait_q, sisusb->completein, timeout);
0296         if (!sisusb->completein) {
0297             /* URB timed out... kill it and report error */
0298             usb_kill_urb(urb);
0299             retval = -ETIMEDOUT;
0300         } else {
0301             /* URB completed within timeout */
0302             retval = urb->status;
0303             readbytes = urb->actual_length;
0304         }
0305     }
0306 
0307     if (actual_length)
0308         *actual_length = readbytes;
0309 
0310     return retval;
0311 }
0312 
0313 
0314 /* Level 1:  */
0315 
0316 /* Send a bulk message of variable size
0317  *
0318  * To copy the data from userspace, give pointer to "userbuffer",
0319  * to copy from (non-DMA) kernel memory, give "kernbuffer". If
0320  * both of these are NULL, it is assumed, that the transfer
0321  * buffer "sisusb->obuf[index]" is set up with the data to send.
0322  * Index is ignored if either kernbuffer or userbuffer is set.
0323  * If async is nonzero, URBs will be sent without waiting for
0324  * completion of the previous URB.
0325  *
0326  * (return 0 on success)
0327  */
0328 
0329 static int sisusb_send_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
0330         char *kernbuffer, const char __user *userbuffer, int index,
0331         ssize_t *bytes_written, unsigned int tflags, int async)
0332 {
0333     int result = 0, retry, count = len;
0334     int passsize, thispass, transferred_len = 0;
0335     int fromuser = (userbuffer != NULL) ? 1 : 0;
0336     int fromkern = (kernbuffer != NULL) ? 1 : 0;
0337     unsigned int pipe;
0338     char *buffer;
0339 
0340     (*bytes_written) = 0;
0341 
0342     /* Sanity check */
0343     if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
0344         return -ENODEV;
0345 
0346     /* If we copy data from kernel or userspace, force the
0347      * allocation of a buffer/urb. If we have the data in
0348      * the transfer buffer[index] already, reuse the buffer/URB
0349      * if the length is > buffer size. (So, transmitting
0350      * large data amounts directly from the transfer buffer
0351      * treats the buffer as a ring buffer. However, we need
0352      * to sync in this case.)
0353      */
0354     if (fromuser || fromkern)
0355         index = -1;
0356     else if (len > sisusb->obufsize)
0357         async = 0;
0358 
0359     pipe = usb_sndbulkpipe(sisusb->sisusb_dev, ep);
0360 
0361     do {
0362         passsize = thispass = (sisusb->obufsize < count) ?
0363                 sisusb->obufsize : count;
0364 
0365         if (index < 0)
0366             index = sisusb_get_free_outbuf(sisusb);
0367 
0368         if (index < 0)
0369             return -EIO;
0370 
0371         buffer = sisusb->obuf[index];
0372 
0373         if (fromuser) {
0374 
0375             if (copy_from_user(buffer, userbuffer, passsize))
0376                 return -EFAULT;
0377 
0378             userbuffer += passsize;
0379 
0380         } else if (fromkern) {
0381 
0382             memcpy(buffer, kernbuffer, passsize);
0383             kernbuffer += passsize;
0384 
0385         }
0386 
0387         retry = 5;
0388         while (thispass) {
0389 
0390             if (!sisusb->sisusb_dev)
0391                 return -ENODEV;
0392 
0393             result = sisusb_bulkout_msg(sisusb, index, pipe,
0394                     buffer, thispass, &transferred_len,
0395                     async ? 0 : 5 * HZ, tflags);
0396 
0397             if (result == -ETIMEDOUT) {
0398 
0399                 /* Will not happen if async */
0400                 if (!retry--)
0401                     return -ETIME;
0402 
0403                 continue;
0404             }
0405 
0406             if ((result == 0) && !async && transferred_len) {
0407 
0408                 thispass -= transferred_len;
0409                 buffer += transferred_len;
0410 
0411             } else
0412                 break;
0413         }
0414 
0415         if (result)
0416             return result;
0417 
0418         (*bytes_written) += passsize;
0419         count            -= passsize;
0420 
0421         /* Force new allocation in next iteration */
0422         if (fromuser || fromkern)
0423             index = -1;
0424 
0425     } while (count > 0);
0426 
0427     if (async) {
0428 #ifdef SISUSB_DONTSYNC
0429         (*bytes_written) = len;
0430         /* Some URBs/buffers might be busy */
0431 #else
0432         sisusb_wait_all_out_complete(sisusb);
0433         (*bytes_written) = transferred_len;
0434         /* All URBs and all buffers are available */
0435 #endif
0436     }
0437 
0438     return ((*bytes_written) == len) ? 0 : -EIO;
0439 }
0440 
0441 /* Receive a bulk message of variable size
0442  *
0443  * To copy the data to userspace, give pointer to "userbuffer",
0444  * to copy to kernel memory, give "kernbuffer". One of them
0445  * MUST be set. (There is no technique for letting the caller
0446  * read directly from the ibuf.)
0447  *
0448  */
0449 
0450 static int sisusb_recv_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
0451         void *kernbuffer, char __user *userbuffer, ssize_t *bytes_read,
0452         unsigned int tflags)
0453 {
0454     int result = 0, retry, count = len;
0455     int bufsize, thispass, transferred_len;
0456     unsigned int pipe;
0457     char *buffer;
0458 
0459     (*bytes_read) = 0;
0460 
0461     /* Sanity check */
0462     if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
0463         return -ENODEV;
0464 
0465     pipe = usb_rcvbulkpipe(sisusb->sisusb_dev, ep);
0466     buffer = sisusb->ibuf;
0467     bufsize = sisusb->ibufsize;
0468 
0469     retry = 5;
0470 
0471 #ifdef SISUSB_DONTSYNC
0472     if (!(sisusb_wait_all_out_complete(sisusb)))
0473         return -EIO;
0474 #endif
0475 
0476     while (count > 0) {
0477 
0478         if (!sisusb->sisusb_dev)
0479             return -ENODEV;
0480 
0481         thispass = (bufsize < count) ? bufsize : count;
0482 
0483         result = sisusb_bulkin_msg(sisusb, pipe, buffer, thispass,
0484                 &transferred_len, 5 * HZ, tflags);
0485 
0486         if (transferred_len)
0487             thispass = transferred_len;
0488 
0489         else if (result == -ETIMEDOUT) {
0490 
0491             if (!retry--)
0492                 return -ETIME;
0493 
0494             continue;
0495 
0496         } else
0497             return -EIO;
0498 
0499 
0500         if (thispass) {
0501 
0502             (*bytes_read) += thispass;
0503             count         -= thispass;
0504 
0505             if (userbuffer) {
0506 
0507                 if (copy_to_user(userbuffer, buffer, thispass))
0508                     return -EFAULT;
0509 
0510                 userbuffer += thispass;
0511 
0512             } else {
0513 
0514                 memcpy(kernbuffer, buffer, thispass);
0515                 kernbuffer += thispass;
0516 
0517             }
0518 
0519         }
0520 
0521     }
0522 
0523     return ((*bytes_read) == len) ? 0 : -EIO;
0524 }
0525 
0526 static int sisusb_send_packet(struct sisusb_usb_data *sisusb, int len,
0527         struct sisusb_packet *packet)
0528 {
0529     int ret;
0530     ssize_t bytes_transferred = 0;
0531     __le32 tmp;
0532 
0533     if (len == 6)
0534         packet->data = 0;
0535 
0536 #ifdef SISUSB_DONTSYNC
0537     if (!(sisusb_wait_all_out_complete(sisusb)))
0538         return 1;
0539 #endif
0540 
0541     /* Eventually correct endianness */
0542     SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
0543 
0544     /* 1. send the packet */
0545     ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_OUT, len,
0546             (char *)packet, NULL, 0, &bytes_transferred, 0, 0);
0547 
0548     if ((ret == 0) && (len == 6)) {
0549 
0550         /* 2. if packet len == 6, it means we read, so wait for 32bit
0551          *    return value and write it to packet->data
0552          */
0553         ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_GFX_IN, 4,
0554                 (char *)&tmp, NULL, &bytes_transferred, 0);
0555 
0556         packet->data = le32_to_cpu(tmp);
0557     }
0558 
0559     return ret;
0560 }
0561 
0562 static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
0563         struct sisusb_packet *packet, unsigned int tflags)
0564 {
0565     int ret;
0566     ssize_t bytes_transferred = 0;
0567     __le32 tmp;
0568 
0569     if (len == 6)
0570         packet->data = 0;
0571 
0572 #ifdef SISUSB_DONTSYNC
0573     if (!(sisusb_wait_all_out_complete(sisusb)))
0574         return 1;
0575 #endif
0576 
0577     /* Eventually correct endianness */
0578     SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
0579 
0580     /* 1. send the packet */
0581     ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_BRIDGE_OUT, len,
0582             (char *)packet, NULL, 0, &bytes_transferred, tflags, 0);
0583 
0584     if ((ret == 0) && (len == 6)) {
0585 
0586         /* 2. if packet len == 6, it means we read, so wait for 32bit
0587          *    return value and write it to packet->data
0588          */
0589         ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_BRIDGE_IN, 4,
0590                 (char *)&tmp, NULL, &bytes_transferred, 0);
0591 
0592         packet->data = le32_to_cpu(tmp);
0593     }
0594 
0595     return ret;
0596 }
0597 
0598 /* access video memory and mmio (return 0 on success) */
0599 
0600 /* Low level */
0601 
0602 /* The following routines assume being used to transfer byte, word,
0603  * long etc.
0604  * This means that
0605  *   - the write routines expect "data" in machine endianness format.
0606  *     The data will be converted to leXX in sisusb_xxx_packet.
0607  *   - the read routines can expect read data in machine-endianess.
0608  */
0609 
0610 static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,
0611         u32 addr, u8 data)
0612 {
0613     struct sisusb_packet packet;
0614 
0615     packet.header  = (1 << (addr & 3)) | (type << 6);
0616     packet.address = addr & ~3;
0617     packet.data    = data << ((addr & 3) << 3);
0618     return sisusb_send_packet(sisusb, 10, &packet);
0619 }
0620 
0621 static int sisusb_write_memio_word(struct sisusb_usb_data *sisusb, int type,
0622         u32 addr, u16 data)
0623 {
0624     struct sisusb_packet packet;
0625     int ret = 0;
0626 
0627     packet.address = addr & ~3;
0628 
0629     switch (addr & 3) {
0630     case 0:
0631         packet.header = (type << 6) | 0x0003;
0632         packet.data   = (u32)data;
0633         ret = sisusb_send_packet(sisusb, 10, &packet);
0634         break;
0635     case 1:
0636         packet.header = (type << 6) | 0x0006;
0637         packet.data   = (u32)data << 8;
0638         ret = sisusb_send_packet(sisusb, 10, &packet);
0639         break;
0640     case 2:
0641         packet.header = (type << 6) | 0x000c;
0642         packet.data   = (u32)data << 16;
0643         ret = sisusb_send_packet(sisusb, 10, &packet);
0644         break;
0645     case 3:
0646         packet.header = (type << 6) | 0x0008;
0647         packet.data   = (u32)data << 24;
0648         ret = sisusb_send_packet(sisusb, 10, &packet);
0649         packet.header = (type << 6) | 0x0001;
0650         packet.address = (addr & ~3) + 4;
0651         packet.data   = (u32)data >> 8;
0652         ret |= sisusb_send_packet(sisusb, 10, &packet);
0653     }
0654 
0655     return ret;
0656 }
0657 
0658 static int sisusb_write_memio_24bit(struct sisusb_usb_data *sisusb, int type,
0659         u32 addr, u32 data)
0660 {
0661     struct sisusb_packet packet;
0662     int ret = 0;
0663 
0664     packet.address = addr & ~3;
0665 
0666     switch (addr & 3) {
0667     case 0:
0668         packet.header  = (type << 6) | 0x0007;
0669         packet.data    = data & 0x00ffffff;
0670         ret = sisusb_send_packet(sisusb, 10, &packet);
0671         break;
0672     case 1:
0673         packet.header  = (type << 6) | 0x000e;
0674         packet.data    = data << 8;
0675         ret = sisusb_send_packet(sisusb, 10, &packet);
0676         break;
0677     case 2:
0678         packet.header  = (type << 6) | 0x000c;
0679         packet.data    = data << 16;
0680         ret = sisusb_send_packet(sisusb, 10, &packet);
0681         packet.header  = (type << 6) | 0x0001;
0682         packet.address = (addr & ~3) + 4;
0683         packet.data    = (data >> 16) & 0x00ff;
0684         ret |= sisusb_send_packet(sisusb, 10, &packet);
0685         break;
0686     case 3:
0687         packet.header  = (type << 6) | 0x0008;
0688         packet.data    = data << 24;
0689         ret = sisusb_send_packet(sisusb, 10, &packet);
0690         packet.header  = (type << 6) | 0x0003;
0691         packet.address = (addr & ~3) + 4;
0692         packet.data    = (data >> 8) & 0xffff;
0693         ret |= sisusb_send_packet(sisusb, 10, &packet);
0694     }
0695 
0696     return ret;
0697 }
0698 
0699 static int sisusb_write_memio_long(struct sisusb_usb_data *sisusb, int type,
0700         u32 addr, u32 data)
0701 {
0702     struct sisusb_packet packet;
0703     int ret = 0;
0704 
0705     packet.address = addr & ~3;
0706 
0707     switch (addr & 3) {
0708     case 0:
0709         packet.header  = (type << 6) | 0x000f;
0710         packet.data    = data;
0711         ret = sisusb_send_packet(sisusb, 10, &packet);
0712         break;
0713     case 1:
0714         packet.header  = (type << 6) | 0x000e;
0715         packet.data    = data << 8;
0716         ret = sisusb_send_packet(sisusb, 10, &packet);
0717         packet.header  = (type << 6) | 0x0001;
0718         packet.address = (addr & ~3) + 4;
0719         packet.data    = data >> 24;
0720         ret |= sisusb_send_packet(sisusb, 10, &packet);
0721         break;
0722     case 2:
0723         packet.header  = (type << 6) | 0x000c;
0724         packet.data    = data << 16;
0725         ret = sisusb_send_packet(sisusb, 10, &packet);
0726         packet.header  = (type << 6) | 0x0003;
0727         packet.address = (addr & ~3) + 4;
0728         packet.data    = data >> 16;
0729         ret |= sisusb_send_packet(sisusb, 10, &packet);
0730         break;
0731     case 3:
0732         packet.header  = (type << 6) | 0x0008;
0733         packet.data    = data << 24;
0734         ret = sisusb_send_packet(sisusb, 10, &packet);
0735         packet.header  = (type << 6) | 0x0007;
0736         packet.address = (addr & ~3) + 4;
0737         packet.data    = data >> 8;
0738         ret |= sisusb_send_packet(sisusb, 10, &packet);
0739     }
0740 
0741     return ret;
0742 }
0743 
0744 /* The xxx_bulk routines copy a buffer of variable size. They treat the
0745  * buffer as chars, therefore lsb/msb has to be corrected if using the
0746  * byte/word/long/etc routines for speed-up
0747  *
0748  * If data is from userland, set "userbuffer" (and clear "kernbuffer"),
0749  * if data is in kernel space, set "kernbuffer" (and clear "userbuffer");
0750  * if neither "kernbuffer" nor "userbuffer" are given, it is assumed
0751  * that the data already is in the transfer buffer "sisusb->obuf[index]".
0752  */
0753 
0754 static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
0755         char *kernbuffer, int length, const char __user *userbuffer,
0756         int index, ssize_t *bytes_written)
0757 {
0758     struct sisusb_packet packet;
0759     int  ret = 0;
0760     static int msgcount;
0761     u8   swap8, fromkern = kernbuffer ? 1 : 0;
0762     u16  swap16;
0763     u32  swap32, flag = (length >> 28) & 1;
0764     u8 buf[4];
0765 
0766     /* if neither kernbuffer not userbuffer are given, assume
0767      * data in obuf
0768      */
0769     if (!fromkern && !userbuffer)
0770         kernbuffer = sisusb->obuf[index];
0771 
0772     (*bytes_written = 0);
0773 
0774     length &= 0x00ffffff;
0775 
0776     while (length) {
0777         switch (length) {
0778         case 1:
0779             if (userbuffer) {
0780                 if (get_user(swap8, (u8 __user *)userbuffer))
0781                     return -EFAULT;
0782             } else
0783                 swap8 = kernbuffer[0];
0784 
0785             ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM,
0786                     addr, swap8);
0787 
0788             if (!ret)
0789                 (*bytes_written)++;
0790 
0791             return ret;
0792 
0793         case 2:
0794             if (userbuffer) {
0795                 if (get_user(swap16, (u16 __user *)userbuffer))
0796                     return -EFAULT;
0797             } else
0798                 swap16 = *((u16 *)kernbuffer);
0799 
0800             ret = sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
0801                     addr, swap16);
0802 
0803             if (!ret)
0804                 (*bytes_written) += 2;
0805 
0806             return ret;
0807 
0808         case 3:
0809             if (userbuffer) {
0810                 if (copy_from_user(&buf, userbuffer, 3))
0811                     return -EFAULT;
0812 #ifdef __BIG_ENDIAN
0813                 swap32 = (buf[0] << 16) |
0814                      (buf[1] <<  8) |
0815                      buf[2];
0816 #else
0817                 swap32 = (buf[2] << 16) |
0818                      (buf[1] <<  8) |
0819                      buf[0];
0820 #endif
0821             } else
0822 #ifdef __BIG_ENDIAN
0823                 swap32 = (kernbuffer[0] << 16) |
0824                      (kernbuffer[1] <<  8) |
0825                      kernbuffer[2];
0826 #else
0827                 swap32 = (kernbuffer[2] << 16) |
0828                      (kernbuffer[1] <<  8) |
0829                      kernbuffer[0];
0830 #endif
0831 
0832             ret = sisusb_write_memio_24bit(sisusb, SISUSB_TYPE_MEM,
0833                     addr, swap32);
0834 
0835             if (!ret)
0836                 (*bytes_written) += 3;
0837 
0838             return ret;
0839 
0840         case 4:
0841             if (userbuffer) {
0842                 if (get_user(swap32, (u32 __user *)userbuffer))
0843                     return -EFAULT;
0844             } else
0845                 swap32 = *((u32 *)kernbuffer);
0846 
0847             ret = sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM,
0848                     addr, swap32);
0849             if (!ret)
0850                 (*bytes_written) += 4;
0851 
0852             return ret;
0853 
0854         default:
0855             if ((length & ~3) > 0x10000) {
0856 
0857                 packet.header  = 0x001f;
0858                 packet.address = 0x000001d4;
0859                 packet.data    = addr;
0860                 ret = sisusb_send_bridge_packet(sisusb, 10,
0861                         &packet, 0);
0862                 packet.header  = 0x001f;
0863                 packet.address = 0x000001d0;
0864                 packet.data    = (length & ~3);
0865                 ret |= sisusb_send_bridge_packet(sisusb, 10,
0866                         &packet, 0);
0867                 packet.header  = 0x001f;
0868                 packet.address = 0x000001c0;
0869                 packet.data    = flag | 0x16;
0870                 ret |= sisusb_send_bridge_packet(sisusb, 10,
0871                         &packet, 0);
0872                 if (userbuffer) {
0873                     ret |= sisusb_send_bulk_msg(sisusb,
0874                             SISUSB_EP_GFX_LBULK_OUT,
0875                             (length & ~3),
0876                             NULL, userbuffer, 0,
0877                             bytes_written, 0, 1);
0878                     userbuffer += (*bytes_written);
0879                 } else if (fromkern) {
0880                     ret |= sisusb_send_bulk_msg(sisusb,
0881                             SISUSB_EP_GFX_LBULK_OUT,
0882                             (length & ~3),
0883                             kernbuffer, NULL, 0,
0884                             bytes_written, 0, 1);
0885                     kernbuffer += (*bytes_written);
0886                 } else {
0887                     ret |= sisusb_send_bulk_msg(sisusb,
0888                             SISUSB_EP_GFX_LBULK_OUT,
0889                             (length & ~3),
0890                             NULL, NULL, index,
0891                             bytes_written, 0, 1);
0892                     kernbuffer += ((*bytes_written) &
0893                             (sisusb->obufsize-1));
0894                 }
0895 
0896             } else {
0897 
0898                 packet.header  = 0x001f;
0899                 packet.address = 0x00000194;
0900                 packet.data    = addr;
0901                 ret = sisusb_send_bridge_packet(sisusb, 10,
0902                         &packet, 0);
0903                 packet.header  = 0x001f;
0904                 packet.address = 0x00000190;
0905                 packet.data    = (length & ~3);
0906                 ret |= sisusb_send_bridge_packet(sisusb, 10,
0907                         &packet, 0);
0908                 if (sisusb->flagb0 != 0x16) {
0909                     packet.header  = 0x001f;
0910                     packet.address = 0x00000180;
0911                     packet.data    = flag | 0x16;
0912                     ret |= sisusb_send_bridge_packet(sisusb,
0913                             10, &packet, 0);
0914                     sisusb->flagb0 = 0x16;
0915                 }
0916                 if (userbuffer) {
0917                     ret |= sisusb_send_bulk_msg(sisusb,
0918                             SISUSB_EP_GFX_BULK_OUT,
0919                             (length & ~3),
0920                             NULL, userbuffer, 0,
0921                             bytes_written, 0, 1);
0922                     userbuffer += (*bytes_written);
0923                 } else if (fromkern) {
0924                     ret |= sisusb_send_bulk_msg(sisusb,
0925                             SISUSB_EP_GFX_BULK_OUT,
0926                             (length & ~3),
0927                             kernbuffer, NULL, 0,
0928                             bytes_written, 0, 1);
0929                     kernbuffer += (*bytes_written);
0930                 } else {
0931                     ret |= sisusb_send_bulk_msg(sisusb,
0932                             SISUSB_EP_GFX_BULK_OUT,
0933                             (length & ~3),
0934                             NULL, NULL, index,
0935                             bytes_written, 0, 1);
0936                     kernbuffer += ((*bytes_written) &
0937                             (sisusb->obufsize-1));
0938                 }
0939             }
0940             if (ret) {
0941                 msgcount++;
0942                 if (msgcount < 500)
0943                     dev_err(&sisusb->sisusb_dev->dev,
0944                             "Wrote %zd of %d bytes, error %d\n",
0945                             *bytes_written, length,
0946                             ret);
0947                 else if (msgcount == 500)
0948                     dev_err(&sisusb->sisusb_dev->dev,
0949                             "Too many errors, logging stopped\n");
0950             }
0951             addr += (*bytes_written);
0952             length -= (*bytes_written);
0953         }
0954 
0955         if (ret)
0956             break;
0957 
0958     }
0959 
0960     return ret ? -EIO : 0;
0961 }
0962 
0963 /* Remember: Read data in packet is in machine-endianess! So for
0964  * byte, word, 24bit, long no endian correction is necessary.
0965  */
0966 
0967 static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
0968         u32 addr, u8 *data)
0969 {
0970     struct sisusb_packet packet;
0971     int ret;
0972 
0973     CLEARPACKET(&packet);
0974     packet.header  = (1 << (addr & 3)) | (type << 6);
0975     packet.address = addr & ~3;
0976     ret = sisusb_send_packet(sisusb, 6, &packet);
0977     *data = (u8)(packet.data >> ((addr & 3) << 3));
0978     return ret;
0979 }
0980 
0981 static int sisusb_read_memio_word(struct sisusb_usb_data *sisusb, int type,
0982         u32 addr, u16 *data)
0983 {
0984     struct sisusb_packet packet;
0985     int ret = 0;
0986 
0987     CLEARPACKET(&packet);
0988 
0989     packet.address = addr & ~3;
0990 
0991     switch (addr & 3) {
0992     case 0:
0993         packet.header = (type << 6) | 0x0003;
0994         ret = sisusb_send_packet(sisusb, 6, &packet);
0995         *data = (u16)(packet.data);
0996         break;
0997     case 1:
0998         packet.header = (type << 6) | 0x0006;
0999         ret = sisusb_send_packet(sisusb, 6, &packet);
1000         *data = (u16)(packet.data >> 8);
1001         break;
1002     case 2:
1003         packet.header = (type << 6) | 0x000c;
1004         ret = sisusb_send_packet(sisusb, 6, &packet);
1005         *data = (u16)(packet.data >> 16);
1006         break;
1007     case 3:
1008         packet.header = (type << 6) | 0x0008;
1009         ret = sisusb_send_packet(sisusb, 6, &packet);
1010         *data = (u16)(packet.data >> 24);
1011         packet.header = (type << 6) | 0x0001;
1012         packet.address = (addr & ~3) + 4;
1013         ret |= sisusb_send_packet(sisusb, 6, &packet);
1014         *data |= (u16)(packet.data << 8);
1015     }
1016 
1017     return ret;
1018 }
1019 
1020 static int sisusb_read_memio_24bit(struct sisusb_usb_data *sisusb, int type,
1021         u32 addr, u32 *data)
1022 {
1023     struct sisusb_packet packet;
1024     int ret = 0;
1025 
1026     packet.address = addr & ~3;
1027 
1028     switch (addr & 3) {
1029     case 0:
1030         packet.header  = (type << 6) | 0x0007;
1031         ret = sisusb_send_packet(sisusb, 6, &packet);
1032         *data = packet.data & 0x00ffffff;
1033         break;
1034     case 1:
1035         packet.header  = (type << 6) | 0x000e;
1036         ret = sisusb_send_packet(sisusb, 6, &packet);
1037         *data = packet.data >> 8;
1038         break;
1039     case 2:
1040         packet.header  = (type << 6) | 0x000c;
1041         ret = sisusb_send_packet(sisusb, 6, &packet);
1042         *data = packet.data >> 16;
1043         packet.header  = (type << 6) | 0x0001;
1044         packet.address = (addr & ~3) + 4;
1045         ret |= sisusb_send_packet(sisusb, 6, &packet);
1046         *data |= ((packet.data & 0xff) << 16);
1047         break;
1048     case 3:
1049         packet.header  = (type << 6) | 0x0008;
1050         ret = sisusb_send_packet(sisusb, 6, &packet);
1051         *data = packet.data >> 24;
1052         packet.header  = (type << 6) | 0x0003;
1053         packet.address = (addr & ~3) + 4;
1054         ret |= sisusb_send_packet(sisusb, 6, &packet);
1055         *data |= ((packet.data & 0xffff) << 8);
1056     }
1057 
1058     return ret;
1059 }
1060 
1061 static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type,
1062         u32 addr, u32 *data)
1063 {
1064     struct sisusb_packet packet;
1065     int ret = 0;
1066 
1067     packet.address = addr & ~3;
1068 
1069     switch (addr & 3) {
1070     case 0:
1071         packet.header  = (type << 6) | 0x000f;
1072         ret = sisusb_send_packet(sisusb, 6, &packet);
1073         *data = packet.data;
1074         break;
1075     case 1:
1076         packet.header  = (type << 6) | 0x000e;
1077         ret = sisusb_send_packet(sisusb, 6, &packet);
1078         *data = packet.data >> 8;
1079         packet.header  = (type << 6) | 0x0001;
1080         packet.address = (addr & ~3) + 4;
1081         ret |= sisusb_send_packet(sisusb, 6, &packet);
1082         *data |= (packet.data << 24);
1083         break;
1084     case 2:
1085         packet.header  = (type << 6) | 0x000c;
1086         ret = sisusb_send_packet(sisusb, 6, &packet);
1087         *data = packet.data >> 16;
1088         packet.header  = (type << 6) | 0x0003;
1089         packet.address = (addr & ~3) + 4;
1090         ret |= sisusb_send_packet(sisusb, 6, &packet);
1091         *data |= (packet.data << 16);
1092         break;
1093     case 3:
1094         packet.header  = (type << 6) | 0x0008;
1095         ret = sisusb_send_packet(sisusb, 6, &packet);
1096         *data = packet.data >> 24;
1097         packet.header  = (type << 6) | 0x0007;
1098         packet.address = (addr & ~3) + 4;
1099         ret |= sisusb_send_packet(sisusb, 6, &packet);
1100         *data |= (packet.data << 8);
1101     }
1102 
1103     return ret;
1104 }
1105 
1106 static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1107         char *kernbuffer, int length, char __user *userbuffer,
1108         ssize_t *bytes_read)
1109 {
1110     int ret = 0;
1111     char buf[4];
1112     u16 swap16;
1113     u32 swap32;
1114 
1115     (*bytes_read = 0);
1116 
1117     length &= 0x00ffffff;
1118 
1119     while (length) {
1120         switch (length) {
1121         case 1:
1122             ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM,
1123                     addr, &buf[0]);
1124             if (!ret) {
1125                 (*bytes_read)++;
1126                 if (userbuffer) {
1127                     if (put_user(buf[0], (u8 __user *)userbuffer))
1128                         return -EFAULT;
1129                 } else
1130                     kernbuffer[0] = buf[0];
1131             }
1132             return ret;
1133 
1134         case 2:
1135             ret |= sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM,
1136                     addr, &swap16);
1137             if (!ret) {
1138                 (*bytes_read) += 2;
1139                 if (userbuffer) {
1140                     if (put_user(swap16, (u16 __user *)userbuffer))
1141                         return -EFAULT;
1142                 } else {
1143                     *((u16 *)kernbuffer) = swap16;
1144                 }
1145             }
1146             return ret;
1147 
1148         case 3:
1149             ret |= sisusb_read_memio_24bit(sisusb, SISUSB_TYPE_MEM,
1150                     addr, &swap32);
1151             if (!ret) {
1152                 (*bytes_read) += 3;
1153 #ifdef __BIG_ENDIAN
1154                 buf[0] = (swap32 >> 16) & 0xff;
1155                 buf[1] = (swap32 >> 8) & 0xff;
1156                 buf[2] = swap32 & 0xff;
1157 #else
1158                 buf[2] = (swap32 >> 16) & 0xff;
1159                 buf[1] = (swap32 >> 8) & 0xff;
1160                 buf[0] = swap32 & 0xff;
1161 #endif
1162                 if (userbuffer) {
1163                     if (copy_to_user(userbuffer,
1164                             &buf[0], 3))
1165                         return -EFAULT;
1166                 } else {
1167                     kernbuffer[0] = buf[0];
1168                     kernbuffer[1] = buf[1];
1169                     kernbuffer[2] = buf[2];
1170                 }
1171             }
1172             return ret;
1173 
1174         default:
1175             ret |= sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM,
1176                     addr, &swap32);
1177             if (!ret) {
1178                 (*bytes_read) += 4;
1179                 if (userbuffer) {
1180                     if (put_user(swap32, (u32 __user *)userbuffer))
1181                         return -EFAULT;
1182 
1183                     userbuffer += 4;
1184                 } else {
1185                     *((u32 *)kernbuffer) = swap32;
1186                     kernbuffer += 4;
1187                 }
1188                 addr += 4;
1189                 length -= 4;
1190             }
1191         }
1192         if (ret)
1193             break;
1194     }
1195 
1196     return ret;
1197 }
1198 
1199 /* High level: Gfx (indexed) register access */
1200 
1201 #ifdef CONFIG_USB_SISUSBVGA_CON
1202 int sisusb_setreg(struct sisusb_usb_data *sisusb, u32 port, u8 data)
1203 {
1204     return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1205 }
1206 
1207 int sisusb_getreg(struct sisusb_usb_data *sisusb, u32 port, u8 *data)
1208 {
1209     return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1210 }
1211 #endif
1212 
1213 int sisusb_setidxreg(struct sisusb_usb_data *sisusb, u32 port,
1214         u8 index, u8 data)
1215 {
1216     int ret;
1217 
1218     ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1219     ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1220     return ret;
1221 }
1222 
1223 int sisusb_getidxreg(struct sisusb_usb_data *sisusb, u32 port,
1224         u8 index, u8 *data)
1225 {
1226     int ret;
1227 
1228     ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1229     ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1230     return ret;
1231 }
1232 
1233 int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, u32 port, u8 idx,
1234         u8 myand, u8 myor)
1235 {
1236     int ret;
1237     u8 tmp;
1238 
1239     ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1240     ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1241     tmp &= myand;
1242     tmp |= myor;
1243     ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1244     return ret;
1245 }
1246 
1247 static int sisusb_setidxregmask(struct sisusb_usb_data *sisusb,
1248         u32 port, u8 idx, u8 data, u8 mask)
1249 {
1250     int ret;
1251     u8 tmp;
1252 
1253     ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1254     ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1255     tmp &= ~(mask);
1256     tmp |= (data & mask);
1257     ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1258     return ret;
1259 }
1260 
1261 int sisusb_setidxregor(struct sisusb_usb_data *sisusb, u32 port,
1262         u8 index, u8 myor)
1263 {
1264     return sisusb_setidxregandor(sisusb, port, index, 0xff, myor);
1265 }
1266 
1267 int sisusb_setidxregand(struct sisusb_usb_data *sisusb, u32 port,
1268         u8 idx, u8 myand)
1269 {
1270     return sisusb_setidxregandor(sisusb, port, idx, myand, 0x00);
1271 }
1272 
1273 /* Write/read video ram */
1274 
1275 #ifdef CONFIG_USB_SISUSBVGA_CON
1276 int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data)
1277 {
1278     return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data);
1279 }
1280 
1281 int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)
1282 {
1283     return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data);
1284 }
1285 
1286 int sisusb_copy_memory(struct sisusb_usb_data *sisusb, u8 *src,
1287         u32 dest, int length)
1288 {
1289     size_t dummy;
1290 
1291     return sisusb_write_mem_bulk(sisusb, dest, src, length,
1292             NULL, 0, &dummy);
1293 }
1294 
1295 #ifdef SISUSBENDIANTEST
1296 static int sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
1297         u32 src, int length)
1298 {
1299     size_t dummy;
1300 
1301     return sisusb_read_mem_bulk(sisusb, src, dest, length,
1302             NULL, &dummy);
1303 }
1304 #endif
1305 #endif
1306 
1307 #ifdef SISUSBENDIANTEST
1308 static void sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
1309 {
1310     static u8 srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1311     char destbuffer[10];
1312     int i, j;
1313 
1314     sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7);
1315 
1316     for (i = 1; i <= 7; i++) {
1317         dev_dbg(&sisusb->sisusb_dev->dev,
1318                 "sisusb: rwtest %d bytes\n", i);
1319         sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i);
1320         for (j = 0; j < i; j++) {
1321             dev_dbg(&sisusb->sisusb_dev->dev,
1322                     "rwtest read[%d] = %x\n",
1323                     j, destbuffer[j]);
1324         }
1325     }
1326 }
1327 #endif
1328 
1329 /* access pci config registers (reg numbers 0, 4, 8, etc) */
1330 
1331 static int sisusb_write_pci_config(struct sisusb_usb_data *sisusb,
1332         int regnum, u32 data)
1333 {
1334     struct sisusb_packet packet;
1335 
1336     packet.header = 0x008f;
1337     packet.address = regnum | 0x10000;
1338     packet.data = data;
1339     return sisusb_send_packet(sisusb, 10, &packet);
1340 }
1341 
1342 static int sisusb_read_pci_config(struct sisusb_usb_data *sisusb,
1343         int regnum, u32 *data)
1344 {
1345     struct sisusb_packet packet;
1346     int ret;
1347 
1348     packet.header = 0x008f;
1349     packet.address = (u32)regnum | 0x10000;
1350     ret = sisusb_send_packet(sisusb, 6, &packet);
1351     *data = packet.data;
1352     return ret;
1353 }
1354 
1355 /* Clear video RAM */
1356 
1357 static int sisusb_clear_vram(struct sisusb_usb_data *sisusb,
1358         u32 address, int length)
1359 {
1360     int ret, i;
1361     ssize_t j;
1362 
1363     if (address < sisusb->vrambase)
1364         return 1;
1365 
1366     if (address >= sisusb->vrambase + sisusb->vramsize)
1367         return 1;
1368 
1369     if (address + length > sisusb->vrambase + sisusb->vramsize)
1370         length = sisusb->vrambase + sisusb->vramsize - address;
1371 
1372     if (length <= 0)
1373         return 0;
1374 
1375     /* allocate free buffer/urb and clear the buffer */
1376     i = sisusb_alloc_outbuf(sisusb);
1377     if (i < 0)
1378         return -EBUSY;
1379 
1380     memset(sisusb->obuf[i], 0, sisusb->obufsize);
1381 
1382     /* We can write a length > buffer size here. The buffer
1383      * data will simply be re-used (like a ring-buffer).
1384      */
1385     ret = sisusb_write_mem_bulk(sisusb, address, NULL, length, NULL, i, &j);
1386 
1387     /* Free the buffer/urb */
1388     sisusb_free_outbuf(sisusb, i);
1389 
1390     return ret;
1391 }
1392 
1393 /* Initialize the graphics core (return 0 on success)
1394  * This resets the graphics hardware and puts it into
1395  * a defined mode (640x480@60Hz)
1396  */
1397 
1398 #define GETREG(r, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1399 #define SETREG(r, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1400 #define SETIREG(r, i, d) sisusb_setidxreg(sisusb, r, i, d)
1401 #define GETIREG(r, i, d) sisusb_getidxreg(sisusb, r, i, d)
1402 #define SETIREGOR(r, i, o) sisusb_setidxregor(sisusb, r, i, o)
1403 #define SETIREGAND(r, i, a) sisusb_setidxregand(sisusb, r, i, a)
1404 #define SETIREGANDOR(r, i, a, o) sisusb_setidxregandor(sisusb, r, i, a, o)
1405 #define READL(a, d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1406 #define WRITEL(a, d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1407 #define READB(a, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1408 #define WRITEB(a, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1409 
1410 static int sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype)
1411 {
1412     int ret;
1413     u8 tmp8;
1414 
1415     ret = GETIREG(SISSR, 0x16, &tmp8);
1416     if (ramtype <= 1) {
1417         tmp8 &= 0x3f;
1418         ret |= SETIREG(SISSR, 0x16, tmp8);
1419         tmp8 |= 0x80;
1420         ret |= SETIREG(SISSR, 0x16, tmp8);
1421     } else {
1422         tmp8 |= 0xc0;
1423         ret |= SETIREG(SISSR, 0x16, tmp8);
1424         tmp8 &= 0x0f;
1425         ret |= SETIREG(SISSR, 0x16, tmp8);
1426         tmp8 |= 0x80;
1427         ret |= SETIREG(SISSR, 0x16, tmp8);
1428         tmp8 &= 0x0f;
1429         ret |= SETIREG(SISSR, 0x16, tmp8);
1430         tmp8 |= 0xd0;
1431         ret |= SETIREG(SISSR, 0x16, tmp8);
1432         tmp8 &= 0x0f;
1433         ret |= SETIREG(SISSR, 0x16, tmp8);
1434         tmp8 |= 0xa0;
1435         ret |= SETIREG(SISSR, 0x16, tmp8);
1436     }
1437     return ret;
1438 }
1439 
1440 static int sisusb_getbuswidth(struct sisusb_usb_data *sisusb,
1441         int *bw, int *chab)
1442 {
1443     int ret;
1444     u8  ramtype, done = 0;
1445     u32 t0, t1, t2, t3;
1446     u32 ramptr = SISUSB_PCI_MEMBASE;
1447 
1448     ret = GETIREG(SISSR, 0x3a, &ramtype);
1449     ramtype &= 3;
1450 
1451     ret |= SETIREG(SISSR, 0x13, 0x00);
1452 
1453     if (ramtype <= 1) {
1454         ret |= SETIREG(SISSR, 0x14, 0x12);
1455         ret |= SETIREGAND(SISSR, 0x15, 0xef);
1456     } else {
1457         ret |= SETIREG(SISSR, 0x14, 0x02);
1458     }
1459 
1460     ret |= sisusb_triggersr16(sisusb, ramtype);
1461     ret |= WRITEL(ramptr +  0, 0x01234567);
1462     ret |= WRITEL(ramptr +  4, 0x456789ab);
1463     ret |= WRITEL(ramptr +  8, 0x89abcdef);
1464     ret |= WRITEL(ramptr + 12, 0xcdef0123);
1465     ret |= WRITEL(ramptr + 16, 0x55555555);
1466     ret |= WRITEL(ramptr + 20, 0x55555555);
1467     ret |= WRITEL(ramptr + 24, 0xffffffff);
1468     ret |= WRITEL(ramptr + 28, 0xffffffff);
1469     ret |= READL(ramptr +  0, &t0);
1470     ret |= READL(ramptr +  4, &t1);
1471     ret |= READL(ramptr +  8, &t2);
1472     ret |= READL(ramptr + 12, &t3);
1473 
1474     if (ramtype <= 1) {
1475 
1476         *chab = 0; *bw = 64;
1477 
1478         if ((t3 != 0xcdef0123) || (t2 != 0x89abcdef)) {
1479             if ((t1 == 0x456789ab) && (t0 == 0x01234567)) {
1480                 *chab = 0; *bw = 64;
1481                 ret |= SETIREGAND(SISSR, 0x14, 0xfd);
1482             }
1483         }
1484         if ((t1 != 0x456789ab) || (t0 != 0x01234567)) {
1485             *chab = 1; *bw = 64;
1486             ret |= SETIREGANDOR(SISSR, 0x14, 0xfc, 0x01);
1487 
1488             ret |= sisusb_triggersr16(sisusb, ramtype);
1489             ret |= WRITEL(ramptr +  0, 0x89abcdef);
1490             ret |= WRITEL(ramptr +  4, 0xcdef0123);
1491             ret |= WRITEL(ramptr +  8, 0x55555555);
1492             ret |= WRITEL(ramptr + 12, 0x55555555);
1493             ret |= WRITEL(ramptr + 16, 0xaaaaaaaa);
1494             ret |= WRITEL(ramptr + 20, 0xaaaaaaaa);
1495             ret |= READL(ramptr +  4, &t1);
1496 
1497             if (t1 != 0xcdef0123) {
1498                 *bw = 32;
1499                 ret |= SETIREGOR(SISSR, 0x15, 0x10);
1500             }
1501         }
1502 
1503     } else {
1504 
1505         *chab = 0; *bw = 64;    /* default: cha, bw = 64 */
1506 
1507         done = 0;
1508 
1509         if (t1 == 0x456789ab) {
1510             if (t0 == 0x01234567) {
1511                 *chab = 0; *bw = 64;
1512                 done = 1;
1513             }
1514         } else {
1515             if (t0 == 0x01234567) {
1516                 *chab = 0; *bw = 32;
1517                 ret |= SETIREG(SISSR, 0x14, 0x00);
1518                 done = 1;
1519             }
1520         }
1521 
1522         if (!done) {
1523             ret |= SETIREG(SISSR, 0x14, 0x03);
1524             ret |= sisusb_triggersr16(sisusb, ramtype);
1525 
1526             ret |= WRITEL(ramptr +  0, 0x01234567);
1527             ret |= WRITEL(ramptr +  4, 0x456789ab);
1528             ret |= WRITEL(ramptr +  8, 0x89abcdef);
1529             ret |= WRITEL(ramptr + 12, 0xcdef0123);
1530             ret |= WRITEL(ramptr + 16, 0x55555555);
1531             ret |= WRITEL(ramptr + 20, 0x55555555);
1532             ret |= WRITEL(ramptr + 24, 0xffffffff);
1533             ret |= WRITEL(ramptr + 28, 0xffffffff);
1534             ret |= READL(ramptr +  0, &t0);
1535             ret |= READL(ramptr +  4, &t1);
1536 
1537             if (t1 == 0x456789ab) {
1538                 if (t0 == 0x01234567) {
1539                     *chab = 1; *bw = 64;
1540                     return ret;
1541                 } /* else error */
1542             } else {
1543                 if (t0 == 0x01234567) {
1544                     *chab = 1; *bw = 32;
1545                     ret |= SETIREG(SISSR, 0x14, 0x01);
1546                 } /* else error */
1547             }
1548         }
1549     }
1550     return ret;
1551 }
1552 
1553 static int sisusb_verify_mclk(struct sisusb_usb_data *sisusb)
1554 {
1555     int ret = 0;
1556     u32 ramptr = SISUSB_PCI_MEMBASE;
1557     u8 tmp1, tmp2, i, j;
1558 
1559     ret |= WRITEB(ramptr, 0xaa);
1560     ret |= WRITEB(ramptr + 16, 0x55);
1561     ret |= READB(ramptr, &tmp1);
1562     ret |= READB(ramptr + 16, &tmp2);
1563     if ((tmp1 != 0xaa) || (tmp2 != 0x55)) {
1564         for (i = 0, j = 16; i < 2; i++, j += 16) {
1565             ret |= GETIREG(SISSR, 0x21, &tmp1);
1566             ret |= SETIREGAND(SISSR, 0x21, (tmp1 & 0xfb));
1567             ret |= SETIREGOR(SISSR, 0x3c, 0x01);  /* not on 330 */
1568             ret |= SETIREGAND(SISSR, 0x3c, 0xfe); /* not on 330 */
1569             ret |= SETIREG(SISSR, 0x21, tmp1);
1570             ret |= WRITEB(ramptr + 16 + j, j);
1571             ret |= READB(ramptr + 16 + j, &tmp1);
1572             if (tmp1 == j) {
1573                 ret |= WRITEB(ramptr + j, j);
1574                 break;
1575             }
1576         }
1577     }
1578     return ret;
1579 }
1580 
1581 static int sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret,
1582         int index, u8 rankno, u8 chab, const u8 dramtype[][5], int bw)
1583 {
1584     int ret = 0, ranksize;
1585     u8 tmp;
1586 
1587     *iret = 0;
1588 
1589     if ((rankno == 2) && (dramtype[index][0] == 2))
1590         return ret;
1591 
1592     ranksize = dramtype[index][3] / 2 * bw / 32;
1593 
1594     if ((ranksize * rankno) > 128)
1595         return ret;
1596 
1597     tmp = 0;
1598     while ((ranksize >>= 1) > 0)
1599         tmp += 0x10;
1600 
1601     tmp |= ((rankno - 1) << 2);
1602     tmp |= ((bw / 64) & 0x02);
1603     tmp |= (chab & 0x01);
1604 
1605     ret = SETIREG(SISSR, 0x14, tmp);
1606     ret |= sisusb_triggersr16(sisusb, 0); /* sic! */
1607 
1608     *iret = 1;
1609 
1610     return ret;
1611 }
1612 
1613 static int sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret,
1614         u32 inc, int testn)
1615 {
1616     int ret = 0, i;
1617     u32 j, tmp;
1618 
1619     *iret = 0;
1620 
1621     for (i = 0, j = 0; i < testn; i++) {
1622         ret |= WRITEL(sisusb->vrambase + j, j);
1623         j += inc;
1624     }
1625 
1626     for (i = 0, j = 0; i < testn; i++) {
1627         ret |= READL(sisusb->vrambase + j, &tmp);
1628         if (tmp != j)
1629             return ret;
1630 
1631         j += inc;
1632     }
1633 
1634     *iret = 1;
1635     return ret;
1636 }
1637 
1638 static int sisusb_check_ranks(struct sisusb_usb_data *sisusb,
1639         int *iret, int rankno, int idx, int bw, const u8 rtype[][5])
1640 {
1641     int ret = 0, i, i2ret;
1642     u32 inc;
1643 
1644     *iret = 0;
1645 
1646     for (i = rankno; i >= 1; i--) {
1647         inc = 1 << (rtype[idx][2] + rtype[idx][1] + rtype[idx][0] +
1648                 bw / 64 + i);
1649         ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1650         if (!i2ret)
1651             return ret;
1652     }
1653 
1654     inc = 1 << (rtype[idx][2] + bw / 64 + 2);
1655     ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 4);
1656     if (!i2ret)
1657         return ret;
1658 
1659     inc = 1 << (10 + bw / 64);
1660     ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1661     if (!i2ret)
1662         return ret;
1663 
1664     *iret = 1;
1665     return ret;
1666 }
1667 
1668 static int sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret,
1669         int bw, int chab)
1670 {
1671     int ret = 0, i2ret = 0, i, j;
1672     static const u8 sdramtype[13][5] = {
1673         { 2, 12, 9, 64, 0x35 },
1674         { 1, 13, 9, 64, 0x44 },
1675         { 2, 12, 8, 32, 0x31 },
1676         { 2, 11, 9, 32, 0x25 },
1677         { 1, 12, 9, 32, 0x34 },
1678         { 1, 13, 8, 32, 0x40 },
1679         { 2, 11, 8, 16, 0x21 },
1680         { 1, 12, 8, 16, 0x30 },
1681         { 1, 11, 9, 16, 0x24 },
1682         { 1, 11, 8,  8, 0x20 },
1683         { 2,  9, 8,  4, 0x01 },
1684         { 1, 10, 8,  4, 0x10 },
1685         { 1,  9, 8,  2, 0x00 }
1686     };
1687 
1688     *iret = 1; /* error */
1689 
1690     for (i = 0; i < 13; i++) {
1691         ret |= SETIREGANDOR(SISSR, 0x13, 0x80, sdramtype[i][4]);
1692         for (j = 2; j > 0; j--) {
1693             ret |= sisusb_set_rank(sisusb, &i2ret, i, j, chab,
1694                     sdramtype, bw);
1695             if (!i2ret)
1696                 continue;
1697 
1698             ret |= sisusb_check_ranks(sisusb, &i2ret, j, i, bw,
1699                     sdramtype);
1700             if (i2ret) {
1701                 *iret = 0;  /* ram size found */
1702                 return ret;
1703             }
1704         }
1705     }
1706 
1707     return ret;
1708 }
1709 
1710 static int sisusb_setup_screen(struct sisusb_usb_data *sisusb,
1711         int clrall, int drwfr)
1712 {
1713     int ret = 0;
1714     u32 address;
1715     int i, length, modex, modey, bpp;
1716 
1717     modex = 640; modey = 480; bpp = 2;
1718 
1719     address = sisusb->vrambase; /* Clear video ram */
1720 
1721     if (clrall)
1722         length = sisusb->vramsize;
1723     else
1724         length = modex * bpp * modey;
1725 
1726     ret = sisusb_clear_vram(sisusb, address, length);
1727 
1728     if (!ret && drwfr) {
1729         for (i = 0; i < modex; i++) {
1730             address = sisusb->vrambase + (i * bpp);
1731             ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1732                     address, 0xf100);
1733             address += (modex * (modey-1) * bpp);
1734             ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1735                     address, 0xf100);
1736         }
1737         for (i = 0; i < modey; i++) {
1738             address = sisusb->vrambase + ((i * modex) * bpp);
1739             ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1740                     address, 0xf100);
1741             address += ((modex - 1) * bpp);
1742             ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1743                     address, 0xf100);
1744         }
1745     }
1746 
1747     return ret;
1748 }
1749 
1750 static void sisusb_set_default_mode(struct sisusb_usb_data *sisusb,
1751         int touchengines)
1752 {
1753     int i, j, modex, bpp, du;
1754     u8 sr31, cr63, tmp8;
1755     static const char attrdata[] = {
1756         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1757         0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1758         0x01, 0x00, 0x00, 0x00
1759     };
1760     static const char crtcrdata[] = {
1761         0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
1762         0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1763         0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3,
1764         0xff
1765     };
1766     static const char grcdata[] = {
1767         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
1768         0xff
1769     };
1770     static const char crtcdata[] = {
1771         0x5f, 0x4f, 0x4f, 0x83, 0x55, 0x81, 0x0b, 0x3e,
1772         0xe9, 0x8b, 0xdf, 0xe8, 0x0c, 0x00, 0x00, 0x05,
1773         0x00
1774     };
1775 
1776     modex = 640; bpp = 2;
1777 
1778     GETIREG(SISSR, 0x31, &sr31);
1779     GETIREG(SISCR, 0x63, &cr63);
1780     SETIREGOR(SISSR, 0x01, 0x20);
1781     SETIREG(SISCR, 0x63, cr63 & 0xbf);
1782     SETIREGOR(SISCR, 0x17, 0x80);
1783     SETIREGOR(SISSR, 0x1f, 0x04);
1784     SETIREGAND(SISSR, 0x07, 0xfb);
1785     SETIREG(SISSR, 0x00, 0x03); /* seq */
1786     SETIREG(SISSR, 0x01, 0x21);
1787     SETIREG(SISSR, 0x02, 0x0f);
1788     SETIREG(SISSR, 0x03, 0x00);
1789     SETIREG(SISSR, 0x04, 0x0e);
1790     SETREG(SISMISCW, 0x23);     /* misc */
1791     for (i = 0; i <= 0x18; i++) {   /* crtc */
1792         SETIREG(SISCR, i, crtcrdata[i]);
1793     }
1794     for (i = 0; i <= 0x13; i++) {   /* att */
1795         GETREG(SISINPSTAT, &tmp8);
1796         SETREG(SISAR, i);
1797         SETREG(SISAR, attrdata[i]);
1798     }
1799     GETREG(SISINPSTAT, &tmp8);
1800     SETREG(SISAR, 0x14);
1801     SETREG(SISAR, 0x00);
1802     GETREG(SISINPSTAT, &tmp8);
1803     SETREG(SISAR, 0x20);
1804     GETREG(SISINPSTAT, &tmp8);
1805     for (i = 0; i <= 0x08; i++) {   /* grc */
1806         SETIREG(SISGR, i, grcdata[i]);
1807     }
1808     SETIREGAND(SISGR, 0x05, 0xbf);
1809     for (i = 0x0A; i <= 0x0E; i++) {    /* clr ext */
1810         SETIREG(SISSR, i, 0x00);
1811     }
1812     SETIREGAND(SISSR, 0x37, 0xfe);
1813     SETREG(SISMISCW, 0xef);     /* sync */
1814     SETIREG(SISCR, 0x11, 0x00); /* crtc */
1815     for (j = 0x00, i = 0; i <= 7; i++, j++)
1816         SETIREG(SISCR, j, crtcdata[i]);
1817 
1818     for (j = 0x10; i <= 10; i++, j++)
1819         SETIREG(SISCR, j, crtcdata[i]);
1820 
1821     for (j = 0x15; i <= 12; i++, j++)
1822         SETIREG(SISCR, j, crtcdata[i]);
1823 
1824     for (j = 0x0A; i <= 15; i++, j++)
1825         SETIREG(SISSR, j, crtcdata[i]);
1826 
1827     SETIREG(SISSR, 0x0E, (crtcdata[16] & 0xE0));
1828     SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5));
1829     SETIREG(SISCR, 0x14, 0x4f);
1830     du = (modex / 16) * (bpp * 2);  /* offset/pitch */
1831     SETIREGANDOR(SISSR, 0x0e, 0xf0, ((du >> 8) & 0x0f));
1832     SETIREG(SISCR, 0x13, (du & 0xff));
1833     du <<= 5;
1834     tmp8 = du >> 8;
1835     SETIREG(SISSR, 0x10, tmp8);
1836     SETIREG(SISSR, 0x31, 0x00); /* VCLK */
1837     SETIREG(SISSR, 0x2b, 0x1b);
1838     SETIREG(SISSR, 0x2c, 0xe1);
1839     SETIREG(SISSR, 0x2d, 0x01);
1840     SETIREGAND(SISSR, 0x3d, 0xfe);  /* FIFO */
1841     SETIREG(SISSR, 0x08, 0xae);
1842     SETIREGAND(SISSR, 0x09, 0xf0);
1843     SETIREG(SISSR, 0x08, 0x34);
1844     SETIREGOR(SISSR, 0x3d, 0x01);
1845     SETIREGAND(SISSR, 0x1f, 0x3f);  /* mode regs */
1846     SETIREGANDOR(SISSR, 0x06, 0xc0, 0x0a);
1847     SETIREG(SISCR, 0x19, 0x00);
1848     SETIREGAND(SISCR, 0x1a, 0xfc);
1849     SETIREGAND(SISSR, 0x0f, 0xb7);
1850     SETIREGAND(SISSR, 0x31, 0xfb);
1851     SETIREGANDOR(SISSR, 0x21, 0x1f, 0xa0);
1852     SETIREGAND(SISSR, 0x32, 0xf3);
1853     SETIREGANDOR(SISSR, 0x07, 0xf8, 0x03);
1854     SETIREG(SISCR, 0x52, 0x6c);
1855 
1856     SETIREG(SISCR, 0x0d, 0x00); /* adjust frame */
1857     SETIREG(SISCR, 0x0c, 0x00);
1858     SETIREG(SISSR, 0x0d, 0x00);
1859     SETIREGAND(SISSR, 0x37, 0xfe);
1860 
1861     SETIREG(SISCR, 0x32, 0x20);
1862     SETIREGAND(SISSR, 0x01, 0xdf);  /* enable display */
1863     SETIREG(SISCR, 0x63, (cr63 & 0xbf));
1864     SETIREG(SISSR, 0x31, (sr31 & 0xfb));
1865 
1866     if (touchengines) {
1867         SETIREG(SISSR, 0x20, 0xa1); /* enable engines */
1868         SETIREGOR(SISSR, 0x1e, 0x5a);
1869 
1870         SETIREG(SISSR, 0x26, 0x01); /* disable cmdqueue */
1871         SETIREG(SISSR, 0x27, 0x1f);
1872         SETIREG(SISSR, 0x26, 0x00);
1873     }
1874 
1875     SETIREG(SISCR, 0x34, 0x44); /* we just set std mode #44 */
1876 }
1877 
1878 static int sisusb_init_gfxcore(struct sisusb_usb_data *sisusb)
1879 {
1880     int ret = 0, i, j, bw, chab, iret, retry = 3;
1881     u8 tmp8, ramtype;
1882     u32 tmp32;
1883     static const char mclktable[] = {
1884         0x3b, 0x22, 0x01, 143,
1885         0x3b, 0x22, 0x01, 143,
1886         0x3b, 0x22, 0x01, 143,
1887         0x3b, 0x22, 0x01, 143
1888     };
1889     static const char eclktable[] = {
1890         0x3b, 0x22, 0x01, 143,
1891         0x3b, 0x22, 0x01, 143,
1892         0x3b, 0x22, 0x01, 143,
1893         0x3b, 0x22, 0x01, 143
1894     };
1895     static const char ramtypetable1[] = {
1896         0x00, 0x04, 0x60, 0x60,
1897         0x0f, 0x0f, 0x1f, 0x1f,
1898         0xba, 0xba, 0xba, 0xba,
1899         0xa9, 0xa9, 0xac, 0xac,
1900         0xa0, 0xa0, 0xa0, 0xa8,
1901         0x00, 0x00, 0x02, 0x02,
1902         0x30, 0x30, 0x40, 0x40
1903     };
1904     static const char ramtypetable2[] = {
1905         0x77, 0x77, 0x44, 0x44,
1906         0x77, 0x77, 0x44, 0x44,
1907         0x00, 0x00, 0x00, 0x00,
1908         0x5b, 0x5b, 0xab, 0xab,
1909         0x00, 0x00, 0xf0, 0xf8
1910     };
1911 
1912     while (retry--) {
1913 
1914         /* Enable VGA */
1915         ret = GETREG(SISVGAEN, &tmp8);
1916         ret |= SETREG(SISVGAEN, (tmp8 | 0x01));
1917 
1918         /* Enable GPU access to VRAM */
1919         ret |= GETREG(SISMISCR, &tmp8);
1920         ret |= SETREG(SISMISCW, (tmp8 | 0x01));
1921 
1922         if (ret)
1923             continue;
1924 
1925         /* Reset registers */
1926         ret |= SETIREGAND(SISCR, 0x5b, 0xdf);
1927         ret |= SETIREG(SISSR, 0x05, 0x86);
1928         ret |= SETIREGOR(SISSR, 0x20, 0x01);
1929 
1930         ret |= SETREG(SISMISCW, 0x67);
1931 
1932         for (i = 0x06; i <= 0x1f; i++)
1933             ret |= SETIREG(SISSR, i, 0x00);
1934 
1935         for (i = 0x21; i <= 0x27; i++)
1936             ret |= SETIREG(SISSR, i, 0x00);
1937 
1938         for (i = 0x31; i <= 0x3d; i++)
1939             ret |= SETIREG(SISSR, i, 0x00);
1940 
1941         for (i = 0x12; i <= 0x1b; i++)
1942             ret |= SETIREG(SISSR, i, 0x00);
1943 
1944         for (i = 0x79; i <= 0x7c; i++)
1945             ret |= SETIREG(SISCR, i, 0x00);
1946 
1947         if (ret)
1948             continue;
1949 
1950         ret |= SETIREG(SISCR, 0x63, 0x80);
1951 
1952         ret |= GETIREG(SISSR, 0x3a, &ramtype);
1953         ramtype &= 0x03;
1954 
1955         ret |= SETIREG(SISSR, 0x28, mclktable[ramtype * 4]);
1956         ret |= SETIREG(SISSR, 0x29, mclktable[(ramtype * 4) + 1]);
1957         ret |= SETIREG(SISSR, 0x2a, mclktable[(ramtype * 4) + 2]);
1958 
1959         ret |= SETIREG(SISSR, 0x2e, eclktable[ramtype * 4]);
1960         ret |= SETIREG(SISSR, 0x2f, eclktable[(ramtype * 4) + 1]);
1961         ret |= SETIREG(SISSR, 0x30, eclktable[(ramtype * 4) + 2]);
1962 
1963         ret |= SETIREG(SISSR, 0x07, 0x18);
1964         ret |= SETIREG(SISSR, 0x11, 0x0f);
1965 
1966         if (ret)
1967             continue;
1968 
1969         for (i = 0x15, j = 0; i <= 0x1b; i++, j++) {
1970             ret |= SETIREG(SISSR, i,
1971                     ramtypetable1[(j*4) + ramtype]);
1972         }
1973         for (i = 0x40, j = 0; i <= 0x44; i++, j++) {
1974             ret |= SETIREG(SISCR, i,
1975                     ramtypetable2[(j*4) + ramtype]);
1976         }
1977 
1978         ret |= SETIREG(SISCR, 0x49, 0xaa);
1979 
1980         ret |= SETIREG(SISSR, 0x1f, 0x00);
1981         ret |= SETIREG(SISSR, 0x20, 0xa0);
1982         ret |= SETIREG(SISSR, 0x23, 0xf6);
1983         ret |= SETIREG(SISSR, 0x24, 0x0d);
1984         ret |= SETIREG(SISSR, 0x25, 0x33);
1985 
1986         ret |= SETIREG(SISSR, 0x11, 0x0f);
1987 
1988         ret |= SETIREGOR(SISPART1, 0x2f, 0x01);
1989 
1990         ret |= SETIREGAND(SISCAP, 0x3f, 0xef);
1991 
1992         if (ret)
1993             continue;
1994 
1995         ret |= SETIREG(SISPART1, 0x00, 0x00);
1996 
1997         ret |= GETIREG(SISSR, 0x13, &tmp8);
1998         tmp8 >>= 4;
1999 
2000         ret |= SETIREG(SISPART1, 0x02, 0x00);
2001         ret |= SETIREG(SISPART1, 0x2e, 0x08);
2002 
2003         ret |= sisusb_read_pci_config(sisusb, 0x50, &tmp32);
2004         tmp32 &= 0x00f00000;
2005         tmp8 = (tmp32 == 0x100000) ? 0x33 : 0x03;
2006         ret |= SETIREG(SISSR, 0x25, tmp8);
2007         tmp8 = (tmp32 == 0x100000) ? 0xaa : 0x88;
2008         ret |= SETIREG(SISCR, 0x49, tmp8);
2009 
2010         ret |= SETIREG(SISSR, 0x27, 0x1f);
2011         ret |= SETIREG(SISSR, 0x31, 0x00);
2012         ret |= SETIREG(SISSR, 0x32, 0x11);
2013         ret |= SETIREG(SISSR, 0x33, 0x00);
2014 
2015         if (ret)
2016             continue;
2017 
2018         ret |= SETIREG(SISCR, 0x83, 0x00);
2019 
2020         sisusb_set_default_mode(sisusb, 0);
2021 
2022         ret |= SETIREGAND(SISSR, 0x21, 0xdf);
2023         ret |= SETIREGOR(SISSR, 0x01, 0x20);
2024         ret |= SETIREGOR(SISSR, 0x16, 0x0f);
2025 
2026         ret |= sisusb_triggersr16(sisusb, ramtype);
2027 
2028         /* Disable refresh */
2029         ret |= SETIREGAND(SISSR, 0x17, 0xf8);
2030         ret |= SETIREGOR(SISSR, 0x19, 0x03);
2031 
2032         ret |= sisusb_getbuswidth(sisusb, &bw, &chab);
2033         ret |= sisusb_verify_mclk(sisusb);
2034 
2035         if (ramtype <= 1) {
2036             ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab);
2037             if (iret) {
2038                 dev_err(&sisusb->sisusb_dev->dev,
2039                         "RAM size detection failed, assuming 8MB video RAM\n");
2040                 ret |= SETIREG(SISSR, 0x14, 0x31);
2041                 /* TODO */
2042             }
2043         } else {
2044             dev_err(&sisusb->sisusb_dev->dev,
2045                     "DDR RAM device found, assuming 8MB video RAM\n");
2046             ret |= SETIREG(SISSR, 0x14, 0x31);
2047             /* *** TODO *** */
2048         }
2049 
2050         /* Enable refresh */
2051         ret |= SETIREG(SISSR, 0x16, ramtypetable1[4 + ramtype]);
2052         ret |= SETIREG(SISSR, 0x17, ramtypetable1[8 + ramtype]);
2053         ret |= SETIREG(SISSR, 0x19, ramtypetable1[16 + ramtype]);
2054 
2055         ret |= SETIREGOR(SISSR, 0x21, 0x20);
2056 
2057         ret |= SETIREG(SISSR, 0x22, 0xfb);
2058         ret |= SETIREG(SISSR, 0x21, 0xa5);
2059 
2060         if (ret == 0)
2061             break;
2062     }
2063 
2064     return ret;
2065 }
2066 
2067 #undef SETREG
2068 #undef GETREG
2069 #undef SETIREG
2070 #undef GETIREG
2071 #undef SETIREGOR
2072 #undef SETIREGAND
2073 #undef SETIREGANDOR
2074 #undef READL
2075 #undef WRITEL
2076 
2077 static void sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
2078 {
2079     u8 tmp8, tmp82, ramtype;
2080     int bw = 0;
2081     char *ramtypetext1 = NULL;
2082     static const char ram_datarate[4] = {'S', 'S', 'D', 'D'};
2083     static const char ram_dynamictype[4] = {'D', 'G', 'D', 'G'};
2084     static const int busSDR[4]  = {64, 64, 128, 128};
2085     static const int busDDR[4]  = {32, 32,  64,  64};
2086     static const int busDDRA[4] = {64+32, 64+32, (64+32)*2, (64+32)*2};
2087 
2088     sisusb_getidxreg(sisusb, SISSR, 0x14, &tmp8);
2089     sisusb_getidxreg(sisusb, SISSR, 0x15, &tmp82);
2090     sisusb_getidxreg(sisusb, SISSR, 0x3a, &ramtype);
2091     sisusb->vramsize = (1 << ((tmp8 & 0xf0) >> 4)) * 1024 * 1024;
2092     ramtype &= 0x03;
2093     switch ((tmp8 >> 2) & 0x03) {
2094     case 0:
2095         ramtypetext1 = "1 ch/1 r";
2096         if (tmp82 & 0x10)
2097             bw = 32;
2098         else
2099             bw = busSDR[(tmp8 & 0x03)];
2100 
2101         break;
2102     case 1:
2103         ramtypetext1 = "1 ch/2 r";
2104         sisusb->vramsize <<= 1;
2105         bw = busSDR[(tmp8 & 0x03)];
2106         break;
2107     case 2:
2108         ramtypetext1 = "asymmetric";
2109         sisusb->vramsize += sisusb->vramsize/2;
2110         bw = busDDRA[(tmp8 & 0x03)];
2111         break;
2112     case 3:
2113         ramtypetext1 = "2 channel";
2114         sisusb->vramsize <<= 1;
2115         bw = busDDR[(tmp8 & 0x03)];
2116         break;
2117     }
2118 
2119     dev_info(&sisusb->sisusb_dev->dev,
2120             "%dMB %s %cDR S%cRAM, bus width %d\n",
2121             sisusb->vramsize >> 20, ramtypetext1,
2122             ram_datarate[ramtype], ram_dynamictype[ramtype], bw);
2123 }
2124 
2125 static int sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb)
2126 {
2127     struct sisusb_packet packet;
2128     int ret;
2129     u32 tmp32;
2130 
2131     /* Do some magic */
2132     packet.header  = 0x001f;
2133     packet.address = 0x00000324;
2134     packet.data    = 0x00000004;
2135     ret = sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2136 
2137     packet.header  = 0x001f;
2138     packet.address = 0x00000364;
2139     packet.data    = 0x00000004;
2140     ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2141 
2142     packet.header  = 0x001f;
2143     packet.address = 0x00000384;
2144     packet.data    = 0x00000004;
2145     ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2146 
2147     packet.header  = 0x001f;
2148     packet.address = 0x00000100;
2149     packet.data    = 0x00000700;
2150     ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2151 
2152     packet.header  = 0x000f;
2153     packet.address = 0x00000004;
2154     ret |= sisusb_send_bridge_packet(sisusb, 6, &packet, 0);
2155     packet.data |= 0x17;
2156     ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2157 
2158     /* Init BAR 0 (VRAM) */
2159     ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2160     ret |= sisusb_write_pci_config(sisusb, 0x10, 0xfffffff0);
2161     ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2162     tmp32 &= 0x0f;
2163     tmp32 |= SISUSB_PCI_MEMBASE;
2164     ret |= sisusb_write_pci_config(sisusb, 0x10, tmp32);
2165 
2166     /* Init BAR 1 (MMIO) */
2167     ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2168     ret |= sisusb_write_pci_config(sisusb, 0x14, 0xfffffff0);
2169     ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2170     tmp32 &= 0x0f;
2171     tmp32 |= SISUSB_PCI_MMIOBASE;
2172     ret |= sisusb_write_pci_config(sisusb, 0x14, tmp32);
2173 
2174     /* Init BAR 2 (i/o ports) */
2175     ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2176     ret |= sisusb_write_pci_config(sisusb, 0x18, 0xfffffff0);
2177     ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2178     tmp32 &= 0x0f;
2179     tmp32 |= SISUSB_PCI_IOPORTBASE;
2180     ret |= sisusb_write_pci_config(sisusb, 0x18, tmp32);
2181 
2182     /* Enable memory and i/o access */
2183     ret |= sisusb_read_pci_config(sisusb, 0x04, &tmp32);
2184     tmp32 |= 0x3;
2185     ret |= sisusb_write_pci_config(sisusb, 0x04, tmp32);
2186 
2187     if (ret == 0) {
2188         /* Some further magic */
2189         packet.header  = 0x001f;
2190         packet.address = 0x00000050;
2191         packet.data    = 0x000000ff;
2192         ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2193     }
2194 
2195     return ret;
2196 }
2197 
2198 /* Initialize the graphics device (return 0 on success)
2199  * This initializes the net2280 as well as the PCI registers
2200  * of the graphics board.
2201  */
2202 
2203 static int sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
2204 {
2205     int ret = 0, test = 0;
2206     u32 tmp32;
2207 
2208     if (sisusb->devinit == 1) {
2209         /* Read PCI BARs and see if they have been set up */
2210         ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2211         if (ret)
2212             return ret;
2213 
2214         if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE)
2215             test++;
2216 
2217         ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2218         if (ret)
2219             return ret;
2220 
2221         if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE)
2222             test++;
2223 
2224         ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2225         if (ret)
2226             return ret;
2227 
2228         if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE)
2229             test++;
2230     }
2231 
2232     /* No? So reset the device */
2233     if ((sisusb->devinit == 0) || (test != 3)) {
2234 
2235         ret |= sisusb_do_init_gfxdevice(sisusb);
2236 
2237         if (ret == 0)
2238             sisusb->devinit = 1;
2239 
2240     }
2241 
2242     if (sisusb->devinit) {
2243         /* Initialize the graphics core */
2244         if (sisusb_init_gfxcore(sisusb) == 0) {
2245             sisusb->gfxinit = 1;
2246             sisusb_get_ramconfig(sisusb);
2247             sisusb_set_default_mode(sisusb, 1);
2248             ret |= sisusb_setup_screen(sisusb, 1, initscreen);
2249         }
2250     }
2251 
2252     return ret;
2253 }
2254 
2255 
2256 #ifdef CONFIG_USB_SISUSBVGA_CON
2257 
2258 /* Set up default text mode:
2259  * - Set text mode (0x03)
2260  * - Upload default font
2261  * - Upload user font (if available)
2262  */
2263 
2264 int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
2265 {
2266     int ret = 0, slot = sisusb->font_slot, i;
2267     const struct font_desc *myfont;
2268     u8 *tempbuf;
2269     u16 *tempbufb;
2270     static const char bootstring[] =
2271         "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2272     static const char bootlogo[] = "(o_ //\\ V_/_";
2273 
2274     /* sisusb->lock is down */
2275 
2276     if (!sisusb->SiS_Pr)
2277         return 1;
2278 
2279     sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2280     sisusb->SiS_Pr->sisusb = (void *)sisusb;
2281 
2282     /* Set mode 0x03 */
2283     SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
2284 
2285     myfont = find_font("VGA8x16");
2286     if (!myfont)
2287         return 1;
2288 
2289     tempbuf = vmalloc(8192);
2290     if (!tempbuf)
2291         return 1;
2292 
2293     for (i = 0; i < 256; i++)
2294         memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
2295 
2296     /* Upload default font */
2297     ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192,
2298             0, 1, NULL, 16, 0);
2299 
2300     vfree(tempbuf);
2301 
2302     /* Upload user font (and reset current slot) */
2303     if (sisusb->font_backup) {
2304         ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
2305                 8192, sisusb->font_backup_512, 1, NULL,
2306                 sisusb->font_backup_height, 0);
2307         if (slot != 2)
2308             sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
2309                     NULL, 16, 0);
2310     }
2311 
2312     if (init && !sisusb->scrbuf) {
2313 
2314         tempbuf = vmalloc(8192);
2315         if (tempbuf) {
2316 
2317             i = 4096;
2318             tempbufb = (u16 *)tempbuf;
2319             while (i--)
2320                 *(tempbufb++) = 0x0720;
2321 
2322             i = 0;
2323             tempbufb = (u16 *)tempbuf;
2324             while (bootlogo[i]) {
2325                 *(tempbufb++) = 0x0700 | bootlogo[i++];
2326                 if (!(i % 4))
2327                     tempbufb += 76;
2328             }
2329 
2330             i = 0;
2331             tempbufb = (u16 *)tempbuf + 6;
2332             while (bootstring[i])
2333                 *(tempbufb++) = 0x0700 | bootstring[i++];
2334 
2335             ret |= sisusb_copy_memory(sisusb, tempbuf,
2336                     sisusb->vrambase, 8192);
2337 
2338             vfree(tempbuf);
2339 
2340         }
2341 
2342     } else if (sisusb->scrbuf) {
2343         ret |= sisusb_copy_memory(sisusb, (u8 *)sisusb->scrbuf,
2344                 sisusb->vrambase, sisusb->scrbuf_size);
2345     }
2346 
2347     if (sisusb->sisusb_cursor_size_from >= 0 &&
2348             sisusb->sisusb_cursor_size_to >= 0) {
2349         sisusb_setidxreg(sisusb, SISCR, 0x0a,
2350                 sisusb->sisusb_cursor_size_from);
2351         sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
2352                 sisusb->sisusb_cursor_size_to);
2353     } else {
2354         sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
2355         sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
2356         sisusb->sisusb_cursor_size_to = -1;
2357     }
2358 
2359     slot = sisusb->sisusb_cursor_loc;
2360     if (slot < 0)
2361         slot = 0;
2362 
2363     sisusb->sisusb_cursor_loc = -1;
2364     sisusb->bad_cursor_pos = 1;
2365 
2366     sisusb_set_cursor(sisusb, slot);
2367 
2368     sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
2369     sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
2370 
2371     sisusb->textmodedestroyed = 0;
2372 
2373     /* sisusb->lock is down */
2374 
2375     return ret;
2376 }
2377 
2378 #endif
2379 
2380 /* fops */
2381 
2382 static int sisusb_open(struct inode *inode, struct file *file)
2383 {
2384     struct sisusb_usb_data *sisusb;
2385     struct usb_interface *interface;
2386     int subminor = iminor(inode);
2387 
2388     interface = usb_find_interface(&sisusb_driver, subminor);
2389     if (!interface)
2390         return -ENODEV;
2391 
2392     sisusb = usb_get_intfdata(interface);
2393     if (!sisusb)
2394         return -ENODEV;
2395 
2396     mutex_lock(&sisusb->lock);
2397 
2398     if (!sisusb->present || !sisusb->ready) {
2399         mutex_unlock(&sisusb->lock);
2400         return -ENODEV;
2401     }
2402 
2403     if (sisusb->isopen) {
2404         mutex_unlock(&sisusb->lock);
2405         return -EBUSY;
2406     }
2407 
2408     if (!sisusb->devinit) {
2409         if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH ||
2410                 sisusb->sisusb_dev->speed >= USB_SPEED_SUPER) {
2411             if (sisusb_init_gfxdevice(sisusb, 0)) {
2412                 mutex_unlock(&sisusb->lock);
2413                 dev_err(&sisusb->sisusb_dev->dev,
2414                         "Failed to initialize device\n");
2415                 return -EIO;
2416             }
2417         } else {
2418             mutex_unlock(&sisusb->lock);
2419             dev_err(&sisusb->sisusb_dev->dev,
2420                     "Device not attached to USB 2.0 hub\n");
2421             return -EIO;
2422         }
2423     }
2424 
2425     /* Increment usage count for our sisusb */
2426     kref_get(&sisusb->kref);
2427 
2428     sisusb->isopen = 1;
2429 
2430     file->private_data = sisusb;
2431 
2432     mutex_unlock(&sisusb->lock);
2433 
2434     return 0;
2435 }
2436 
2437 void sisusb_delete(struct kref *kref)
2438 {
2439     struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
2440 
2441     if (!sisusb)
2442         return;
2443 
2444     usb_put_dev(sisusb->sisusb_dev);
2445 
2446     sisusb->sisusb_dev = NULL;
2447     sisusb_free_buffers(sisusb);
2448     sisusb_free_urbs(sisusb);
2449 #ifdef CONFIG_USB_SISUSBVGA_CON
2450     kfree(sisusb->SiS_Pr);
2451 #endif
2452     kfree(sisusb);
2453 }
2454 
2455 static int sisusb_release(struct inode *inode, struct file *file)
2456 {
2457     struct sisusb_usb_data *sisusb;
2458 
2459     sisusb = file->private_data;
2460     if (!sisusb)
2461         return -ENODEV;
2462 
2463     mutex_lock(&sisusb->lock);
2464 
2465     if (sisusb->present) {
2466         /* Wait for all URBs to finish if device still present */
2467         if (!sisusb_wait_all_out_complete(sisusb))
2468             sisusb_kill_all_busy(sisusb);
2469     }
2470 
2471     sisusb->isopen = 0;
2472     file->private_data = NULL;
2473 
2474     mutex_unlock(&sisusb->lock);
2475 
2476     /* decrement the usage count on our device */
2477     kref_put(&sisusb->kref, sisusb_delete);
2478 
2479     return 0;
2480 }
2481 
2482 static ssize_t sisusb_read(struct file *file, char __user *buffer,
2483         size_t count, loff_t *ppos)
2484 {
2485     struct sisusb_usb_data *sisusb;
2486     ssize_t bytes_read = 0;
2487     int errno = 0;
2488     u8 buf8;
2489     u16 buf16;
2490     u32 buf32, address;
2491 
2492     sisusb = file->private_data;
2493     if (!sisusb)
2494         return -ENODEV;
2495 
2496     mutex_lock(&sisusb->lock);
2497 
2498     /* Sanity check */
2499     if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2500         mutex_unlock(&sisusb->lock);
2501         return -ENODEV;
2502     }
2503 
2504     if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2505             (*ppos) <  SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2506 
2507         address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE +
2508                 SISUSB_PCI_IOPORTBASE;
2509 
2510         /* Read i/o ports
2511          * Byte, word and long(32) can be read. As this
2512          * emulates inX instructions, the data returned is
2513          * in machine-endianness.
2514          */
2515         switch (count) {
2516         case 1:
2517             if (sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO,
2518                     address, &buf8))
2519                 errno = -EIO;
2520             else if (put_user(buf8, (u8 __user *)buffer))
2521                 errno = -EFAULT;
2522             else
2523                 bytes_read = 1;
2524 
2525             break;
2526 
2527         case 2:
2528             if (sisusb_read_memio_word(sisusb, SISUSB_TYPE_IO,
2529                     address, &buf16))
2530                 errno = -EIO;
2531             else if (put_user(buf16, (u16 __user *)buffer))
2532                 errno = -EFAULT;
2533             else
2534                 bytes_read = 2;
2535 
2536             break;
2537 
2538         case 4:
2539             if (sisusb_read_memio_long(sisusb, SISUSB_TYPE_IO,
2540                     address, &buf32))
2541                 errno = -EIO;
2542             else if (put_user(buf32, (u32 __user *)buffer))
2543                 errno = -EFAULT;
2544             else
2545                 bytes_read = 4;
2546 
2547             break;
2548 
2549         default:
2550             errno = -EIO;
2551 
2552         }
2553 
2554     } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && (*ppos) <
2555             SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2556 
2557         address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE +
2558                 SISUSB_PCI_MEMBASE;
2559 
2560         /* Read video ram
2561          * Remember: Data delivered is never endian-corrected
2562          */
2563         errno = sisusb_read_mem_bulk(sisusb, address,
2564                 NULL, count, buffer, &bytes_read);
2565 
2566         if (bytes_read)
2567             errno = bytes_read;
2568 
2569     } else  if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2570                 (*ppos) <  SISUSB_PCI_PSEUDO_MMIOBASE +
2571                 SISUSB_PCI_MMIOSIZE) {
2572 
2573         address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE +
2574                 SISUSB_PCI_MMIOBASE;
2575 
2576         /* Read MMIO
2577          * Remember: Data delivered is never endian-corrected
2578          */
2579         errno = sisusb_read_mem_bulk(sisusb, address,
2580                 NULL, count, buffer, &bytes_read);
2581 
2582         if (bytes_read)
2583             errno = bytes_read;
2584 
2585     } else  if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2586             (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
2587 
2588         if (count != 4) {
2589             mutex_unlock(&sisusb->lock);
2590             return -EINVAL;
2591         }
2592 
2593         address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2594 
2595         /* Read PCI config register
2596          * Return value delivered in machine endianness.
2597          */
2598         if (sisusb_read_pci_config(sisusb, address, &buf32))
2599             errno = -EIO;
2600         else if (put_user(buf32, (u32 __user *)buffer))
2601             errno = -EFAULT;
2602         else
2603             bytes_read = 4;
2604 
2605     } else {
2606 
2607         errno = -EBADFD;
2608 
2609     }
2610 
2611     (*ppos) += bytes_read;
2612 
2613     mutex_unlock(&sisusb->lock);
2614 
2615     return errno ? errno : bytes_read;
2616 }
2617 
2618 static ssize_t sisusb_write(struct file *file, const char __user *buffer,
2619         size_t count, loff_t *ppos)
2620 {
2621     struct sisusb_usb_data *sisusb;
2622     int errno = 0;
2623     ssize_t bytes_written = 0;
2624     u8 buf8;
2625     u16 buf16;
2626     u32 buf32, address;
2627 
2628     sisusb = file->private_data;
2629     if (!sisusb)
2630         return -ENODEV;
2631 
2632     mutex_lock(&sisusb->lock);
2633 
2634     /* Sanity check */
2635     if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2636         mutex_unlock(&sisusb->lock);
2637         return -ENODEV;
2638     }
2639 
2640     if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2641             (*ppos) <  SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2642 
2643         address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE +
2644                 SISUSB_PCI_IOPORTBASE;
2645 
2646         /* Write i/o ports
2647          * Byte, word and long(32) can be written. As this
2648          * emulates outX instructions, the data is expected
2649          * in machine-endianness.
2650          */
2651         switch (count) {
2652         case 1:
2653             if (get_user(buf8, (u8 __user *)buffer))
2654                 errno = -EFAULT;
2655             else if (sisusb_write_memio_byte(sisusb,
2656                     SISUSB_TYPE_IO, address, buf8))
2657                 errno = -EIO;
2658             else
2659                 bytes_written = 1;
2660 
2661             break;
2662 
2663         case 2:
2664             if (get_user(buf16, (u16 __user *)buffer))
2665                 errno = -EFAULT;
2666             else if (sisusb_write_memio_word(sisusb,
2667                     SISUSB_TYPE_IO, address, buf16))
2668                 errno = -EIO;
2669             else
2670                 bytes_written = 2;
2671 
2672             break;
2673 
2674         case 4:
2675             if (get_user(buf32, (u32 __user *)buffer))
2676                 errno = -EFAULT;
2677             else if (sisusb_write_memio_long(sisusb,
2678                     SISUSB_TYPE_IO, address, buf32))
2679                 errno = -EIO;
2680             else
2681                 bytes_written = 4;
2682 
2683             break;
2684 
2685         default:
2686             errno = -EIO;
2687         }
2688 
2689     } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2690             (*ppos) <  SISUSB_PCI_PSEUDO_MEMBASE +
2691             sisusb->vramsize) {
2692 
2693         address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE +
2694                 SISUSB_PCI_MEMBASE;
2695 
2696         /* Write video ram.
2697          * Buffer is copied 1:1, therefore, on big-endian
2698          * machines, the data must be swapped by userland
2699          * in advance (if applicable; no swapping in 8bpp
2700          * mode or if YUV data is being transferred).
2701          */
2702         errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2703                 count, buffer, 0, &bytes_written);
2704 
2705         if (bytes_written)
2706             errno = bytes_written;
2707 
2708     } else  if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2709             (*ppos) <  SISUSB_PCI_PSEUDO_MMIOBASE +
2710             SISUSB_PCI_MMIOSIZE) {
2711 
2712         address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE +
2713                 SISUSB_PCI_MMIOBASE;
2714 
2715         /* Write MMIO.
2716          * Buffer is copied 1:1, therefore, on big-endian
2717          * machines, the data must be swapped by userland
2718          * in advance.
2719          */
2720         errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2721                 count, buffer, 0, &bytes_written);
2722 
2723         if (bytes_written)
2724             errno = bytes_written;
2725 
2726     } else  if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2727                 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE +
2728                 SISUSB_PCI_PCONFSIZE) {
2729 
2730         if (count != 4) {
2731             mutex_unlock(&sisusb->lock);
2732             return -EINVAL;
2733         }
2734 
2735         address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2736 
2737         /* Write PCI config register.
2738          * Given value expected in machine endianness.
2739          */
2740         if (get_user(buf32, (u32 __user *)buffer))
2741             errno = -EFAULT;
2742         else if (sisusb_write_pci_config(sisusb, address, buf32))
2743             errno = -EIO;
2744         else
2745             bytes_written = 4;
2746 
2747 
2748     } else {
2749 
2750         /* Error */
2751         errno = -EBADFD;
2752 
2753     }
2754 
2755     (*ppos) += bytes_written;
2756 
2757     mutex_unlock(&sisusb->lock);
2758 
2759     return errno ? errno : bytes_written;
2760 }
2761 
2762 static loff_t sisusb_lseek(struct file *file, loff_t offset, int orig)
2763 {
2764     struct sisusb_usb_data *sisusb;
2765     loff_t ret;
2766 
2767     sisusb = file->private_data;
2768     if (!sisusb)
2769         return -ENODEV;
2770 
2771     mutex_lock(&sisusb->lock);
2772 
2773     /* Sanity check */
2774     if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2775         mutex_unlock(&sisusb->lock);
2776         return -ENODEV;
2777     }
2778 
2779     ret = no_seek_end_llseek(file, offset, orig);
2780 
2781     mutex_unlock(&sisusb->lock);
2782     return ret;
2783 }
2784 
2785 static int sisusb_handle_command(struct sisusb_usb_data *sisusb,
2786         struct sisusb_command *y, unsigned long arg)
2787 {
2788     int retval, length;
2789     u32 port, address;
2790 
2791     /* All our commands require the device
2792      * to be initialized.
2793      */
2794     if (!sisusb->devinit)
2795         return -ENODEV;
2796 
2797     port = y->data3 -
2798         SISUSB_PCI_PSEUDO_IOPORTBASE +
2799         SISUSB_PCI_IOPORTBASE;
2800 
2801     switch (y->operation) {
2802     case SUCMD_GET:
2803         retval = sisusb_getidxreg(sisusb, port, y->data0, &y->data1);
2804         if (!retval) {
2805             if (copy_to_user((void __user *)arg, y, sizeof(*y)))
2806                 retval = -EFAULT;
2807         }
2808         break;
2809 
2810     case SUCMD_SET:
2811         retval = sisusb_setidxreg(sisusb, port, y->data0, y->data1);
2812         break;
2813 
2814     case SUCMD_SETOR:
2815         retval = sisusb_setidxregor(sisusb, port, y->data0, y->data1);
2816         break;
2817 
2818     case SUCMD_SETAND:
2819         retval = sisusb_setidxregand(sisusb, port, y->data0, y->data1);
2820         break;
2821 
2822     case SUCMD_SETANDOR:
2823         retval = sisusb_setidxregandor(sisusb, port, y->data0,
2824                 y->data1, y->data2);
2825         break;
2826 
2827     case SUCMD_SETMASK:
2828         retval = sisusb_setidxregmask(sisusb, port, y->data0,
2829                 y->data1, y->data2);
2830         break;
2831 
2832     case SUCMD_CLRSCR:
2833         /* Gfx core must be initialized */
2834         if (!sisusb->gfxinit)
2835             return -ENODEV;
2836 
2837         length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
2838         address = y->data3 - SISUSB_PCI_PSEUDO_MEMBASE +
2839                 SISUSB_PCI_MEMBASE;
2840         retval = sisusb_clear_vram(sisusb, address, length);
2841         break;
2842 
2843     case SUCMD_HANDLETEXTMODE:
2844         retval = 0;
2845 #ifdef CONFIG_USB_SISUSBVGA_CON
2846         /* Gfx core must be initialized, SiS_Pr must exist */
2847         if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2848             return -ENODEV;
2849 
2850         switch (y->data0) {
2851         case 0:
2852             retval = sisusb_reset_text_mode(sisusb, 0);
2853             break;
2854         case 1:
2855             sisusb->textmodedestroyed = 1;
2856             break;
2857         }
2858 #endif
2859         break;
2860 
2861 #ifdef CONFIG_USB_SISUSBVGA_CON
2862     case SUCMD_SETMODE:
2863         /* Gfx core must be initialized, SiS_Pr must exist */
2864         if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2865             return -ENODEV;
2866 
2867         retval = 0;
2868 
2869         sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2870         sisusb->SiS_Pr->sisusb = (void *)sisusb;
2871 
2872         if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
2873             retval = -EINVAL;
2874 
2875         break;
2876 
2877     case SUCMD_SETVESAMODE:
2878         /* Gfx core must be initialized, SiS_Pr must exist */
2879         if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2880             return -ENODEV;
2881 
2882         retval = 0;
2883 
2884         sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2885         sisusb->SiS_Pr->sisusb = (void *)sisusb;
2886 
2887         if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
2888             retval = -EINVAL;
2889 
2890         break;
2891 #endif
2892 
2893     default:
2894         retval = -EINVAL;
2895     }
2896 
2897     if (retval > 0)
2898         retval = -EIO;
2899 
2900     return retval;
2901 }
2902 
2903 static long sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2904 {
2905     struct sisusb_usb_data *sisusb;
2906     struct sisusb_info x;
2907     struct sisusb_command y;
2908     long retval = 0;
2909     u32 __user *argp = (u32 __user *)arg;
2910 
2911     sisusb = file->private_data;
2912     if (!sisusb)
2913         return -ENODEV;
2914 
2915     mutex_lock(&sisusb->lock);
2916 
2917     /* Sanity check */
2918     if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2919         retval = -ENODEV;
2920         goto err_out;
2921     }
2922 
2923     switch (cmd) {
2924     case SISUSB_GET_CONFIG_SIZE:
2925 
2926         if (put_user(sizeof(x), argp))
2927             retval = -EFAULT;
2928 
2929         break;
2930 
2931     case SISUSB_GET_CONFIG:
2932 
2933         x.sisusb_id = SISUSB_ID;
2934         x.sisusb_version = SISUSB_VERSION;
2935         x.sisusb_revision = SISUSB_REVISION;
2936         x.sisusb_patchlevel = SISUSB_PATCHLEVEL;
2937         x.sisusb_gfxinit = sisusb->gfxinit;
2938         x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE;
2939         x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE;
2940         x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE;
2941         x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE;
2942         x.sisusb_vramsize = sisusb->vramsize;
2943         x.sisusb_minor = sisusb->minor;
2944         x.sisusb_fbdevactive = 0;
2945 #ifdef CONFIG_USB_SISUSBVGA_CON
2946         x.sisusb_conactive  = sisusb->haveconsole ? 1 : 0;
2947 #else
2948         x.sisusb_conactive  = 0;
2949 #endif
2950         memset(x.sisusb_reserved, 0, sizeof(x.sisusb_reserved));
2951 
2952         if (copy_to_user((void __user *)arg, &x, sizeof(x)))
2953             retval = -EFAULT;
2954 
2955         break;
2956 
2957     case SISUSB_COMMAND:
2958 
2959         if (copy_from_user(&y, (void __user *)arg, sizeof(y)))
2960             retval = -EFAULT;
2961         else
2962             retval = sisusb_handle_command(sisusb, &y, arg);
2963 
2964         break;
2965 
2966     default:
2967         retval = -ENOTTY;
2968         break;
2969     }
2970 
2971 err_out:
2972     mutex_unlock(&sisusb->lock);
2973     return retval;
2974 }
2975 
2976 #ifdef CONFIG_COMPAT
2977 static long sisusb_compat_ioctl(struct file *f, unsigned int cmd,
2978         unsigned long arg)
2979 {
2980     switch (cmd) {
2981     case SISUSB_GET_CONFIG_SIZE:
2982     case SISUSB_GET_CONFIG:
2983     case SISUSB_COMMAND:
2984         return sisusb_ioctl(f, cmd, arg);
2985 
2986     default:
2987         return -ENOIOCTLCMD;
2988     }
2989 }
2990 #endif
2991 
2992 static const struct file_operations usb_sisusb_fops = {
2993     .owner =    THIS_MODULE,
2994     .open =     sisusb_open,
2995     .release =  sisusb_release,
2996     .read =     sisusb_read,
2997     .write =    sisusb_write,
2998     .llseek =   sisusb_lseek,
2999 #ifdef CONFIG_COMPAT
3000     .compat_ioctl = sisusb_compat_ioctl,
3001 #endif
3002     .unlocked_ioctl = sisusb_ioctl
3003 };
3004 
3005 static struct usb_class_driver usb_sisusb_class = {
3006     .name =     "sisusbvga%d",
3007     .fops =     &usb_sisusb_fops,
3008     .minor_base =   SISUSB_MINOR
3009 };
3010 
3011 static int sisusb_probe(struct usb_interface *intf,
3012         const struct usb_device_id *id)
3013 {
3014     struct usb_device *dev = interface_to_usbdev(intf);
3015     struct sisusb_usb_data *sisusb;
3016     int retval = 0, i;
3017 
3018     dev_info(&dev->dev, "USB2VGA dongle found at address %d\n",
3019             dev->devnum);
3020 
3021     /* Allocate memory for our private */
3022     sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL);
3023     if (!sisusb)
3024         return -ENOMEM;
3025 
3026     kref_init(&sisusb->kref);
3027 
3028     mutex_init(&(sisusb->lock));
3029 
3030     sisusb->sisusb_dev = dev;
3031     sisusb->vrambase   = SISUSB_PCI_MEMBASE;
3032     sisusb->mmiobase   = SISUSB_PCI_MMIOBASE;
3033     sisusb->mmiosize   = SISUSB_PCI_MMIOSIZE;
3034     sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
3035     /* Everything else is zero */
3036 
3037     /* Register device */
3038     retval = usb_register_dev(intf, &usb_sisusb_class);
3039     if (retval) {
3040         dev_err(&sisusb->sisusb_dev->dev,
3041                 "Failed to get a minor for device %d\n",
3042                 dev->devnum);
3043         retval = -ENODEV;
3044         goto error_1;
3045     }
3046 
3047     sisusb->minor = intf->minor;
3048 
3049     /* Allocate buffers */
3050     sisusb->ibufsize = SISUSB_IBUF_SIZE;
3051     sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL);
3052     if (!sisusb->ibuf) {
3053         retval = -ENOMEM;
3054         goto error_2;
3055     }
3056 
3057     sisusb->numobufs = 0;
3058     sisusb->obufsize = SISUSB_OBUF_SIZE;
3059     for (i = 0; i < NUMOBUFS; i++) {
3060         sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL);
3061         if (!sisusb->obuf[i]) {
3062             if (i == 0) {
3063                 retval = -ENOMEM;
3064                 goto error_3;
3065             }
3066             break;
3067         }
3068         sisusb->numobufs++;
3069     }
3070 
3071     /* Allocate URBs */
3072     sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL);
3073     if (!sisusb->sisurbin) {
3074         retval = -ENOMEM;
3075         goto error_3;
3076     }
3077     sisusb->completein = 1;
3078 
3079     for (i = 0; i < sisusb->numobufs; i++) {
3080         sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL);
3081         if (!sisusb->sisurbout[i]) {
3082             retval = -ENOMEM;
3083             goto error_4;
3084         }
3085         sisusb->urbout_context[i].sisusb = (void *)sisusb;
3086         sisusb->urbout_context[i].urbindex = i;
3087         sisusb->urbstatus[i] = 0;
3088     }
3089 
3090     dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n",
3091             sisusb->numobufs);
3092 
3093 #ifdef CONFIG_USB_SISUSBVGA_CON
3094     /* Allocate our SiS_Pr */
3095     sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL);
3096     if (!sisusb->SiS_Pr) {
3097         retval = -ENOMEM;
3098         goto error_4;
3099     }
3100 #endif
3101 
3102     /* Do remaining init stuff */
3103 
3104     init_waitqueue_head(&sisusb->wait_q);
3105 
3106     usb_set_intfdata(intf, sisusb);
3107 
3108     usb_get_dev(sisusb->sisusb_dev);
3109 
3110     sisusb->present = 1;
3111 
3112     if (dev->speed == USB_SPEED_HIGH || dev->speed >= USB_SPEED_SUPER) {
3113         int initscreen = 1;
3114 #ifdef CONFIG_USB_SISUSBVGA_CON
3115         if (sisusb_first_vc > 0 && sisusb_last_vc > 0 &&
3116                 sisusb_first_vc <= sisusb_last_vc &&
3117                 sisusb_last_vc <= MAX_NR_CONSOLES)
3118             initscreen = 0;
3119 #endif
3120         if (sisusb_init_gfxdevice(sisusb, initscreen))
3121             dev_err(&sisusb->sisusb_dev->dev,
3122                     "Failed to early initialize device\n");
3123 
3124     } else
3125         dev_info(&sisusb->sisusb_dev->dev,
3126                 "Not attached to USB 2.0 hub, deferring init\n");
3127 
3128     sisusb->ready = 1;
3129 
3130 #ifdef SISUSBENDIANTEST
3131     dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST ***\n");
3132     sisusb_testreadwrite(sisusb);
3133     dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST END ***\n");
3134 #endif
3135 
3136 #ifdef CONFIG_USB_SISUSBVGA_CON
3137     sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
3138 #endif
3139 
3140     return 0;
3141 
3142 error_4:
3143     sisusb_free_urbs(sisusb);
3144 error_3:
3145     sisusb_free_buffers(sisusb);
3146 error_2:
3147     usb_deregister_dev(intf, &usb_sisusb_class);
3148 error_1:
3149     kfree(sisusb);
3150     return retval;
3151 }
3152 
3153 static void sisusb_disconnect(struct usb_interface *intf)
3154 {
3155     struct sisusb_usb_data *sisusb;
3156 
3157     /* This should *not* happen */
3158     sisusb = usb_get_intfdata(intf);
3159     if (!sisusb)
3160         return;
3161 
3162 #ifdef CONFIG_USB_SISUSBVGA_CON
3163     sisusb_console_exit(sisusb);
3164 #endif
3165 
3166     usb_deregister_dev(intf, &usb_sisusb_class);
3167 
3168     mutex_lock(&sisusb->lock);
3169 
3170     /* Wait for all URBs to complete and kill them in case (MUST do) */
3171     if (!sisusb_wait_all_out_complete(sisusb))
3172         sisusb_kill_all_busy(sisusb);
3173 
3174     usb_set_intfdata(intf, NULL);
3175 
3176     sisusb->present = 0;
3177     sisusb->ready = 0;
3178 
3179     mutex_unlock(&sisusb->lock);
3180 
3181     /* decrement our usage count */
3182     kref_put(&sisusb->kref, sisusb_delete);
3183 }
3184 
3185 static const struct usb_device_id sisusb_table[] = {
3186     { USB_DEVICE(0x0711, 0x0550) },
3187     { USB_DEVICE(0x0711, 0x0900) },
3188     { USB_DEVICE(0x0711, 0x0901) },
3189     { USB_DEVICE(0x0711, 0x0902) },
3190     { USB_DEVICE(0x0711, 0x0903) },
3191     { USB_DEVICE(0x0711, 0x0918) },
3192     { USB_DEVICE(0x0711, 0x0920) },
3193     { USB_DEVICE(0x0711, 0x0950) },
3194     { USB_DEVICE(0x0711, 0x5200) },
3195     { USB_DEVICE(0x182d, 0x021c) },
3196     { USB_DEVICE(0x182d, 0x0269) },
3197     { }
3198 };
3199 
3200 MODULE_DEVICE_TABLE(usb, sisusb_table);
3201 
3202 static struct usb_driver sisusb_driver = {
3203     .name =     "sisusb",
3204     .probe =    sisusb_probe,
3205     .disconnect =   sisusb_disconnect,
3206     .id_table = sisusb_table,
3207 };
3208 
3209 static int __init usb_sisusb_init(void)
3210 {
3211 
3212 #ifdef CONFIG_USB_SISUSBVGA_CON
3213     sisusb_init_concode();
3214 #endif
3215 
3216     return usb_register(&sisusb_driver);
3217 }
3218 
3219 static void __exit usb_sisusb_exit(void)
3220 {
3221     usb_deregister(&sisusb_driver);
3222 }
3223 
3224 module_init(usb_sisusb_init);
3225 module_exit(usb_sisusb_exit);
3226 
3227 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3228 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3229 MODULE_LICENSE("GPL");
3230