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