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 
59 static struct usb_driver sisusb_driver;
60 
61 static 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 
73 static 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 */
92 static 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 */
107 static 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) */
123 static 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 
133 static 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 
147 static 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 
157 static 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 
169 static 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 
177 static 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 
199 static 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 
252 static 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 
263 static 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 
315 static 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 
436 static 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 
512 static 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 
548 static 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 
596 static 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 
607 static 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 
644 static 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 
685 static 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 
740 static 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 
953 static 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 
967 static 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 
1006 static 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 
1047 static 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 
1092 static 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 
1187 static 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 
1197 static 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 
1207 static 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 
1221 static 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 
1235 static 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 
1241 static 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
1250 static 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 
1273 static 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 
1284 static 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 
1299 static 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 
1352 static 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 
1382 static 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 
1495 static 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 
1523 static 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 
1555 static 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 
1580 static 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 
1610 static 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 
1652 static 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 
1692 static 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 
1820 static 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 
2019 static 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 
2067 static 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 
2145 static 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 
2199 static 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 
2254 static 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 
2269 static 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 
2296 static 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 
2432 static 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 
2576 static 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 
2599 static 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 
2671 static 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 
2735 err_out:
2736 	mutex_unlock(&sisusb->lock);
2737 	return retval;
2738 }
2739 
2740 #ifdef CONFIG_COMPAT
2741 static 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 
2756 static 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 
2769 static struct usb_class_driver usb_sisusb_class = {
2770 	.name =		"sisusbvga%d",
2771 	.fops =		&usb_sisusb_fops,
2772 	.minor_base =	SISUSB_MINOR
2773 };
2774 
2775 static 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 
2782 	dev_info(&dev->dev, "USB2VGA dongle found at address %d\n",
2783 			dev->devnum);
2784 
2785 	/* Allocate memory for our private */
2786 	sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL);
2787 	if (!sisusb)
2788 		return -ENOMEM;
2789 
2790 	kref_init(&sisusb->kref);
2791 
2792 	mutex_init(&(sisusb->lock));
2793 
2794 	sisusb->sisusb_dev = dev;
2795 	sisusb->vrambase   = SISUSB_PCI_MEMBASE;
2796 	sisusb->mmiobase   = SISUSB_PCI_MMIOBASE;
2797 	sisusb->mmiosize   = SISUSB_PCI_MMIOSIZE;
2798 	sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
2799 	/* Everything else is zero */
2800 
2801 	/* Register device */
2802 	retval = usb_register_dev(intf, &usb_sisusb_class);
2803 	if (retval) {
2804 		dev_err(&sisusb->sisusb_dev->dev,
2805 				"Failed to get a minor for device %d\n",
2806 				dev->devnum);
2807 		retval = -ENODEV;
2808 		goto error_1;
2809 	}
2810 
2811 	sisusb->minor = intf->minor;
2812 
2813 	/* Allocate buffers */
2814 	sisusb->ibufsize = SISUSB_IBUF_SIZE;
2815 	sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL);
2816 	if (!sisusb->ibuf) {
2817 		retval = -ENOMEM;
2818 		goto error_2;
2819 	}
2820 
2821 	sisusb->numobufs = 0;
2822 	sisusb->obufsize = SISUSB_OBUF_SIZE;
2823 	for (i = 0; i < NUMOBUFS; i++) {
2824 		sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL);
2825 		if (!sisusb->obuf[i]) {
2826 			if (i == 0) {
2827 				retval = -ENOMEM;
2828 				goto error_3;
2829 			}
2830 			break;
2831 		}
2832 		sisusb->numobufs++;
2833 	}
2834 
2835 	/* Allocate URBs */
2836 	sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL);
2837 	if (!sisusb->sisurbin) {
2838 		retval = -ENOMEM;
2839 		goto error_3;
2840 	}
2841 	sisusb->completein = 1;
2842 
2843 	for (i = 0; i < sisusb->numobufs; i++) {
2844 		sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL);
2845 		if (!sisusb->sisurbout[i]) {
2846 			retval = -ENOMEM;
2847 			goto error_4;
2848 		}
2849 		sisusb->urbout_context[i].sisusb = (void *)sisusb;
2850 		sisusb->urbout_context[i].urbindex = i;
2851 		sisusb->urbstatus[i] = 0;
2852 	}
2853 
2854 	dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n",
2855 			sisusb->numobufs);
2856 
2857 	/* Do remaining init stuff */
2858 
2859 	init_waitqueue_head(&sisusb->wait_q);
2860 
2861 	usb_set_intfdata(intf, sisusb);
2862 
2863 	usb_get_dev(sisusb->sisusb_dev);
2864 
2865 	sisusb->present = 1;
2866 
2867 	if (dev->speed == USB_SPEED_HIGH || dev->speed >= USB_SPEED_SUPER) {
2868 		int initscreen = 1;
2869 		if (sisusb_init_gfxdevice(sisusb, initscreen))
2870 			dev_err(&sisusb->sisusb_dev->dev,
2871 					"Failed to early initialize device\n");
2872 
2873 	} else
2874 		dev_info(&sisusb->sisusb_dev->dev,
2875 				"Not attached to USB 2.0 hub, deferring init\n");
2876 
2877 	sisusb->ready = 1;
2878 
2879 #ifdef SISUSBENDIANTEST
2880 	dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST ***\n");
2881 	sisusb_testreadwrite(sisusb);
2882 	dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST END ***\n");
2883 #endif
2884 
2885 	return 0;
2886 
2887 error_4:
2888 	sisusb_free_urbs(sisusb);
2889 error_3:
2890 	sisusb_free_buffers(sisusb);
2891 error_2:
2892 	usb_deregister_dev(intf, &usb_sisusb_class);
2893 error_1:
2894 	kfree(sisusb);
2895 	return retval;
2896 }
2897 
2898 static void sisusb_disconnect(struct usb_interface *intf)
2899 {
2900 	struct sisusb_usb_data *sisusb;
2901 
2902 	/* This should *not* happen */
2903 	sisusb = usb_get_intfdata(intf);
2904 	if (!sisusb)
2905 		return;
2906 
2907 	usb_deregister_dev(intf, &usb_sisusb_class);
2908 
2909 	mutex_lock(&sisusb->lock);
2910 
2911 	/* Wait for all URBs to complete and kill them in case (MUST do) */
2912 	if (!sisusb_wait_all_out_complete(sisusb))
2913 		sisusb_kill_all_busy(sisusb);
2914 
2915 	usb_set_intfdata(intf, NULL);
2916 
2917 	sisusb->present = 0;
2918 	sisusb->ready = 0;
2919 
2920 	mutex_unlock(&sisusb->lock);
2921 
2922 	/* decrement our usage count */
2923 	kref_put(&sisusb->kref, sisusb_delete);
2924 }
2925 
2926 static const struct usb_device_id sisusb_table[] = {
2927 	{ USB_DEVICE(0x0711, 0x0550) },
2928 	{ USB_DEVICE(0x0711, 0x0900) },
2929 	{ USB_DEVICE(0x0711, 0x0901) },
2930 	{ USB_DEVICE(0x0711, 0x0902) },
2931 	{ USB_DEVICE(0x0711, 0x0903) },
2932 	{ USB_DEVICE(0x0711, 0x0918) },
2933 	{ USB_DEVICE(0x0711, 0x0920) },
2934 	{ USB_DEVICE(0x0711, 0x0950) },
2935 	{ USB_DEVICE(0x0711, 0x5200) },
2936 	{ USB_DEVICE(0x182d, 0x021c) },
2937 	{ USB_DEVICE(0x182d, 0x0269) },
2938 	{ }
2939 };
2940 
2941 MODULE_DEVICE_TABLE(usb, sisusb_table);
2942 
2943 static struct usb_driver sisusb_driver = {
2944 	.name =		"sisusb",
2945 	.probe =	sisusb_probe,
2946 	.disconnect =	sisusb_disconnect,
2947 	.id_table =	sisusb_table,
2948 };
2949 
2950 module_usb_driver(sisusb_driver);
2951 
2952 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
2953 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
2954 MODULE_LICENSE("GPL");
2955 
2956