cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sisusb.c (76881B)


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