Linux Audio

Check our new training course

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