Linux Audio

Check our new training course

Linux kernel drivers training

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