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