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