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