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