]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blob - drivers/usb/misc/sisusbvga/sisusb.c
Merge Linux 2.6.23
[mirror_ubuntu-hirsute-kernel.git] / drivers / usb / misc / sisusbvga / sisusb.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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 timout */
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
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
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
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
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
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
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
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
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
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 printk(KERN_ERR
1007 "sisusbvga[%d]: Wrote %zd of "
1008 "%d bytes, error %d\n",
1009 sisusb->minor, *bytes_written,
1010 length, ret);
1011 else if (msgcount == 500)
1012 printk(KERN_ERR
1013 "sisusbvga[%d]: Too many errors"
1014 ", logging stopped\n",
1015 sisusb->minor);
1016 }
1017 addr += (*bytes_written);
1018 length -= (*bytes_written);
1019 }
1020
1021 if (ret)
1022 break;
1023
1024 }
1025
1026 return ret ? -EIO : 0;
1027 }
1028
1029 /* Remember: Read data in packet is in machine-endianess! So for
1030 * byte, word, 24bit, long no endian correction is necessary.
1031 */
1032
1033 static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
1034 u32 addr, u8 *data)
1035 {
1036 struct sisusb_packet packet;
1037 int ret;
1038
1039 CLEARPACKET(&packet);
1040 packet.header = (1 << (addr & 3)) | (type << 6);
1041 packet.address = addr & ~3;
1042 ret = sisusb_send_packet(sisusb, 6, &packet);
1043 *data = (u8)(packet.data >> ((addr & 3) << 3));
1044 return ret;
1045 }
1046
1047 static int sisusb_read_memio_word(struct sisusb_usb_data *sisusb, int type,
1048 u32 addr, u16 *data)
1049 {
1050 struct sisusb_packet packet;
1051 int ret = 0;
1052
1053 CLEARPACKET(&packet);
1054
1055 packet.address = addr & ~3;
1056
1057 switch (addr & 3) {
1058 case 0:
1059 packet.header = (type << 6) | 0x0003;
1060 ret = sisusb_send_packet(sisusb, 6, &packet);
1061 *data = (u16)(packet.data);
1062 break;
1063 case 1:
1064 packet.header = (type << 6) | 0x0006;
1065 ret = sisusb_send_packet(sisusb, 6, &packet);
1066 *data = (u16)(packet.data >> 8);
1067 break;
1068 case 2:
1069 packet.header = (type << 6) | 0x000c;
1070 ret = sisusb_send_packet(sisusb, 6, &packet);
1071 *data = (u16)(packet.data >> 16);
1072 break;
1073 case 3:
1074 packet.header = (type << 6) | 0x0008;
1075 ret = sisusb_send_packet(sisusb, 6, &packet);
1076 *data = (u16)(packet.data >> 24);
1077 packet.header = (type << 6) | 0x0001;
1078 packet.address = (addr & ~3) + 4;
1079 ret |= sisusb_send_packet(sisusb, 6, &packet);
1080 *data |= (u16)(packet.data << 8);
1081 }
1082
1083 return ret;
1084 }
1085
1086 static int sisusb_read_memio_24bit(struct sisusb_usb_data *sisusb, int type,
1087 u32 addr, u32 *data)
1088 {
1089 struct sisusb_packet packet;
1090 int ret = 0;
1091
1092 packet.address = addr & ~3;
1093
1094 switch (addr & 3) {
1095 case 0:
1096 packet.header = (type << 6) | 0x0007;
1097 ret = sisusb_send_packet(sisusb, 6, &packet);
1098 *data = packet.data & 0x00ffffff;
1099 break;
1100 case 1:
1101 packet.header = (type << 6) | 0x000e;
1102 ret = sisusb_send_packet(sisusb, 6, &packet);
1103 *data = packet.data >> 8;
1104 break;
1105 case 2:
1106 packet.header = (type << 6) | 0x000c;
1107 ret = sisusb_send_packet(sisusb, 6, &packet);
1108 *data = packet.data >> 16;
1109 packet.header = (type << 6) | 0x0001;
1110 packet.address = (addr & ~3) + 4;
1111 ret |= sisusb_send_packet(sisusb, 6, &packet);
1112 *data |= ((packet.data & 0xff) << 16);
1113 break;
1114 case 3:
1115 packet.header = (type << 6) | 0x0008;
1116 ret = sisusb_send_packet(sisusb, 6, &packet);
1117 *data = packet.data >> 24;
1118 packet.header = (type << 6) | 0x0003;
1119 packet.address = (addr & ~3) + 4;
1120 ret |= sisusb_send_packet(sisusb, 6, &packet);
1121 *data |= ((packet.data & 0xffff) << 8);
1122 }
1123
1124 return ret;
1125 }
1126
1127 static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type,
1128 u32 addr, u32 *data)
1129 {
1130 struct sisusb_packet packet;
1131 int ret = 0;
1132
1133 packet.address = addr & ~3;
1134
1135 switch (addr & 3) {
1136 case 0:
1137 packet.header = (type << 6) | 0x000f;
1138 ret = sisusb_send_packet(sisusb, 6, &packet);
1139 *data = packet.data;
1140 break;
1141 case 1:
1142 packet.header = (type << 6) | 0x000e;
1143 ret = sisusb_send_packet(sisusb, 6, &packet);
1144 *data = packet.data >> 8;
1145 packet.header = (type << 6) | 0x0001;
1146 packet.address = (addr & ~3) + 4;
1147 ret |= sisusb_send_packet(sisusb, 6, &packet);
1148 *data |= (packet.data << 24);
1149 break;
1150 case 2:
1151 packet.header = (type << 6) | 0x000c;
1152 ret = sisusb_send_packet(sisusb, 6, &packet);
1153 *data = packet.data >> 16;
1154 packet.header = (type << 6) | 0x0003;
1155 packet.address = (addr & ~3) + 4;
1156 ret |= sisusb_send_packet(sisusb, 6, &packet);
1157 *data |= (packet.data << 16);
1158 break;
1159 case 3:
1160 packet.header = (type << 6) | 0x0008;
1161 ret = sisusb_send_packet(sisusb, 6, &packet);
1162 *data = packet.data >> 24;
1163 packet.header = (type << 6) | 0x0007;
1164 packet.address = (addr & ~3) + 4;
1165 ret |= sisusb_send_packet(sisusb, 6, &packet);
1166 *data |= (packet.data << 8);
1167 }
1168
1169 return ret;
1170 }
1171
1172 static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1173 char *kernbuffer, int length,
1174 char __user *userbuffer, ssize_t *bytes_read)
1175 {
1176 int ret = 0;
1177 char buf[4];
1178 u16 swap16;
1179 u32 swap32;
1180
1181 (*bytes_read = 0);
1182
1183 length &= 0x00ffffff;
1184
1185 while (length) {
1186
1187 switch (length) {
1188
1189 case 1:
1190
1191 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM,
1192 addr, &buf[0]);
1193 if (!ret) {
1194 (*bytes_read)++;
1195 if (userbuffer) {
1196 if (put_user(buf[0],
1197 (u8 __user *)userbuffer)) {
1198 return -EFAULT;
1199 }
1200 } else {
1201 kernbuffer[0] = buf[0];
1202 }
1203 }
1204 return ret;
1205
1206 case 2:
1207 ret |= sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM,
1208 addr, &swap16);
1209 if (!ret) {
1210 (*bytes_read) += 2;
1211 if (userbuffer) {
1212 if (put_user(swap16,
1213 (u16 __user *)userbuffer))
1214 return -EFAULT;
1215 } else {
1216 *((u16 *)kernbuffer) = swap16;
1217 }
1218 }
1219 return ret;
1220
1221 case 3:
1222 ret |= sisusb_read_memio_24bit(sisusb, SISUSB_TYPE_MEM,
1223 addr, &swap32);
1224 if (!ret) {
1225 (*bytes_read) += 3;
1226 #ifdef __BIG_ENDIAN
1227 buf[0] = (swap32 >> 16) & 0xff;
1228 buf[1] = (swap32 >> 8) & 0xff;
1229 buf[2] = swap32 & 0xff;
1230 #else
1231 buf[2] = (swap32 >> 16) & 0xff;
1232 buf[1] = (swap32 >> 8) & 0xff;
1233 buf[0] = swap32 & 0xff;
1234 #endif
1235 if (userbuffer) {
1236 if (copy_to_user(userbuffer, &buf[0], 3))
1237 return -EFAULT;
1238 } else {
1239 kernbuffer[0] = buf[0];
1240 kernbuffer[1] = buf[1];
1241 kernbuffer[2] = buf[2];
1242 }
1243 }
1244 return ret;
1245
1246 default:
1247 ret |= sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM,
1248 addr, &swap32);
1249 if (!ret) {
1250 (*bytes_read) += 4;
1251 if (userbuffer) {
1252 if (put_user(swap32,
1253 (u32 __user *)userbuffer))
1254 return -EFAULT;
1255
1256 userbuffer += 4;
1257 } else {
1258 *((u32 *)kernbuffer) = swap32;
1259 kernbuffer += 4;
1260 }
1261 addr += 4;
1262 length -= 4;
1263 }
1264 #if 0 /* That does not work, as EP 2 is an OUT EP! */
1265 default:
1266 CLEARPACKET(&packet);
1267 packet.header = 0x001f;
1268 packet.address = 0x000001a0;
1269 packet.data = 0x00000006;
1270 ret |= sisusb_send_bridge_packet(sisusb, 10,
1271 &packet, 0);
1272 packet.header = 0x001f;
1273 packet.address = 0x000001b0;
1274 packet.data = (length & ~3) | 0x40000000;
1275 ret |= sisusb_send_bridge_packet(sisusb, 10,
1276 &packet, 0);
1277 packet.header = 0x001f;
1278 packet.address = 0x000001b4;
1279 packet.data = addr;
1280 ret |= sisusb_send_bridge_packet(sisusb, 10,
1281 &packet, 0);
1282 packet.header = 0x001f;
1283 packet.address = 0x000001a4;
1284 packet.data = 0x00000001;
1285 ret |= sisusb_send_bridge_packet(sisusb, 10,
1286 &packet, 0);
1287 if (userbuffer) {
1288 ret |= sisusb_recv_bulk_msg(sisusb,
1289 SISUSB_EP_GFX_BULK_IN,
1290 (length & ~3),
1291 NULL, userbuffer,
1292 bytes_read, 0);
1293 if (!ret) userbuffer += (*bytes_read);
1294 } else {
1295 ret |= sisusb_recv_bulk_msg(sisusb,
1296 SISUSB_EP_GFX_BULK_IN,
1297 (length & ~3),
1298 kernbuffer, NULL,
1299 bytes_read, 0);
1300 if (!ret) kernbuffer += (*bytes_read);
1301 }
1302 addr += (*bytes_read);
1303 length -= (*bytes_read);
1304 #endif
1305 }
1306
1307 if (ret)
1308 break;
1309 }
1310
1311 return ret;
1312 }
1313
1314 /* High level: Gfx (indexed) register access */
1315
1316 #ifdef INCL_SISUSB_CON
1317 int
1318 sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data)
1319 {
1320 return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1321 }
1322
1323 int
1324 sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data)
1325 {
1326 return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1327 }
1328 #endif
1329
1330 int
1331 sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
1332 {
1333 int ret;
1334 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1335 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1336 return ret;
1337 }
1338
1339 int
1340 sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
1341 {
1342 int ret;
1343 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1344 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1345 return ret;
1346 }
1347
1348 int
1349 sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
1350 u8 myand, u8 myor)
1351 {
1352 int ret;
1353 u8 tmp;
1354
1355 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1356 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1357 tmp &= myand;
1358 tmp |= myor;
1359 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1360 return ret;
1361 }
1362
1363 static int
1364 sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx,
1365 u8 data, u8 mask)
1366 {
1367 int ret;
1368 u8 tmp;
1369 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1370 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1371 tmp &= ~(mask);
1372 tmp |= (data & mask);
1373 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1374 return ret;
1375 }
1376
1377 int
1378 sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor)
1379 {
1380 return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));
1381 }
1382
1383 int
1384 sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand)
1385 {
1386 return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00));
1387 }
1388
1389 /* Write/read video ram */
1390
1391 #ifdef INCL_SISUSB_CON
1392 int
1393 sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data)
1394 {
1395 return(sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
1396 }
1397
1398 int
1399 sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)
1400 {
1401 return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
1402 }
1403
1404 #if 0
1405
1406 int
1407 sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data)
1408 {
1409 return(sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
1410 }
1411
1412 int
1413 sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data)
1414 {
1415 return(sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
1416 }
1417
1418 #endif /* 0 */
1419
1420 int
1421 sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
1422 u32 dest, int length, size_t *bytes_written)
1423 {
1424 return(sisusb_write_mem_bulk(sisusb, dest, src, length, NULL, 0, bytes_written));
1425 }
1426
1427 #ifdef SISUSBENDIANTEST
1428 int
1429 sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
1430 u32 src, int length, size_t *bytes_written)
1431 {
1432 return(sisusb_read_mem_bulk(sisusb, src, dest, length, NULL, bytes_written));
1433 }
1434 #endif
1435 #endif
1436
1437 #ifdef SISUSBENDIANTEST
1438 static void
1439 sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
1440 {
1441 static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1442 char destbuffer[10];
1443 size_t dummy;
1444 int i,j;
1445
1446 sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy);
1447
1448 for(i = 1; i <= 7; i++) {
1449 printk(KERN_DEBUG "sisusb: rwtest %d bytes\n", i);
1450 sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy);
1451 for(j = 0; j < i; j++) {
1452 printk(KERN_DEBUG "sisusb: rwtest read[%d] = %x\n", j, destbuffer[j]);
1453 }
1454 }
1455 }
1456 #endif
1457
1458 /* access pci config registers (reg numbers 0, 4, 8, etc) */
1459
1460 static int
1461 sisusb_write_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 data)
1462 {
1463 struct sisusb_packet packet;
1464 int ret;
1465
1466 packet.header = 0x008f;
1467 packet.address = regnum | 0x10000;
1468 packet.data = data;
1469 ret = sisusb_send_packet(sisusb, 10, &packet);
1470 return ret;
1471 }
1472
1473 static int
1474 sisusb_read_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 *data)
1475 {
1476 struct sisusb_packet packet;
1477 int ret;
1478
1479 packet.header = 0x008f;
1480 packet.address = (u32)regnum | 0x10000;
1481 ret = sisusb_send_packet(sisusb, 6, &packet);
1482 *data = packet.data;
1483 return ret;
1484 }
1485
1486 /* Clear video RAM */
1487
1488 static int
1489 sisusb_clear_vram(struct sisusb_usb_data *sisusb, u32 address, int length)
1490 {
1491 int ret, i;
1492 ssize_t j;
1493
1494 if (address < sisusb->vrambase)
1495 return 1;
1496
1497 if (address >= sisusb->vrambase + sisusb->vramsize)
1498 return 1;
1499
1500 if (address + length > sisusb->vrambase + sisusb->vramsize)
1501 length = sisusb->vrambase + sisusb->vramsize - address;
1502
1503 if (length <= 0)
1504 return 0;
1505
1506 /* allocate free buffer/urb and clear the buffer */
1507 if ((i = sisusb_alloc_outbuf(sisusb)) < 0)
1508 return -EBUSY;
1509
1510 memset(sisusb->obuf[i], 0, sisusb->obufsize);
1511
1512 /* We can write a length > buffer size here. The buffer
1513 * data will simply be re-used (like a ring-buffer).
1514 */
1515 ret = sisusb_write_mem_bulk(sisusb, address, NULL, length, NULL, i, &j);
1516
1517 /* Free the buffer/urb */
1518 sisusb_free_outbuf(sisusb, i);
1519
1520 return ret;
1521 }
1522
1523 /* Initialize the graphics core (return 0 on success)
1524 * This resets the graphics hardware and puts it into
1525 * a defined mode (640x480@60Hz)
1526 */
1527
1528 #define GETREG(r,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1529 #define SETREG(r,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1530 #define SETIREG(r,i,d) sisusb_setidxreg(sisusb, r, i, d)
1531 #define GETIREG(r,i,d) sisusb_getidxreg(sisusb, r, i, d)
1532 #define SETIREGOR(r,i,o) sisusb_setidxregor(sisusb, r, i, o)
1533 #define SETIREGAND(r,i,a) sisusb_setidxregand(sisusb, r, i, a)
1534 #define SETIREGANDOR(r,i,a,o) sisusb_setidxregandor(sisusb, r, i, a, o)
1535 #define READL(a,d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1536 #define WRITEL(a,d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1537 #define READB(a,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1538 #define WRITEB(a,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1539
1540 static int
1541 sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype)
1542 {
1543 int ret;
1544 u8 tmp8;
1545
1546 ret = GETIREG(SISSR, 0x16, &tmp8);
1547 if (ramtype <= 1) {
1548 tmp8 &= 0x3f;
1549 ret |= SETIREG(SISSR, 0x16, tmp8);
1550 tmp8 |= 0x80;
1551 ret |= SETIREG(SISSR, 0x16, tmp8);
1552 } else {
1553 tmp8 |= 0xc0;
1554 ret |= SETIREG(SISSR, 0x16, tmp8);
1555 tmp8 &= 0x0f;
1556 ret |= SETIREG(SISSR, 0x16, tmp8);
1557 tmp8 |= 0x80;
1558 ret |= SETIREG(SISSR, 0x16, tmp8);
1559 tmp8 &= 0x0f;
1560 ret |= SETIREG(SISSR, 0x16, tmp8);
1561 tmp8 |= 0xd0;
1562 ret |= SETIREG(SISSR, 0x16, tmp8);
1563 tmp8 &= 0x0f;
1564 ret |= SETIREG(SISSR, 0x16, tmp8);
1565 tmp8 |= 0xa0;
1566 ret |= SETIREG(SISSR, 0x16, tmp8);
1567 }
1568 return ret;
1569 }
1570
1571 static int
1572 sisusb_getbuswidth(struct sisusb_usb_data *sisusb, int *bw, int *chab)
1573 {
1574 int ret;
1575 u8 ramtype, done = 0;
1576 u32 t0, t1, t2, t3;
1577 u32 ramptr = SISUSB_PCI_MEMBASE;
1578
1579 ret = GETIREG(SISSR, 0x3a, &ramtype);
1580 ramtype &= 3;
1581
1582 ret |= SETIREG(SISSR, 0x13, 0x00);
1583
1584 if (ramtype <= 1) {
1585 ret |= SETIREG(SISSR, 0x14, 0x12);
1586 ret |= SETIREGAND(SISSR, 0x15, 0xef);
1587 } else {
1588 ret |= SETIREG(SISSR, 0x14, 0x02);
1589 }
1590
1591 ret |= sisusb_triggersr16(sisusb, ramtype);
1592 ret |= WRITEL(ramptr + 0, 0x01234567);
1593 ret |= WRITEL(ramptr + 4, 0x456789ab);
1594 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1595 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1596 ret |= WRITEL(ramptr + 16, 0x55555555);
1597 ret |= WRITEL(ramptr + 20, 0x55555555);
1598 ret |= WRITEL(ramptr + 24, 0xffffffff);
1599 ret |= WRITEL(ramptr + 28, 0xffffffff);
1600 ret |= READL(ramptr + 0, &t0);
1601 ret |= READL(ramptr + 4, &t1);
1602 ret |= READL(ramptr + 8, &t2);
1603 ret |= READL(ramptr + 12, &t3);
1604
1605 if (ramtype <= 1) {
1606
1607 *chab = 0; *bw = 64;
1608
1609 if ((t3 != 0xcdef0123) || (t2 != 0x89abcdef)) {
1610 if ((t1 == 0x456789ab) && (t0 == 0x01234567)) {
1611 *chab = 0; *bw = 64;
1612 ret |= SETIREGAND(SISSR, 0x14, 0xfd);
1613 }
1614 }
1615 if ((t1 != 0x456789ab) || (t0 != 0x01234567)) {
1616 *chab = 1; *bw = 64;
1617 ret |= SETIREGANDOR(SISSR, 0x14, 0xfc,0x01);
1618
1619 ret |= sisusb_triggersr16(sisusb, ramtype);
1620 ret |= WRITEL(ramptr + 0, 0x89abcdef);
1621 ret |= WRITEL(ramptr + 4, 0xcdef0123);
1622 ret |= WRITEL(ramptr + 8, 0x55555555);
1623 ret |= WRITEL(ramptr + 12, 0x55555555);
1624 ret |= WRITEL(ramptr + 16, 0xaaaaaaaa);
1625 ret |= WRITEL(ramptr + 20, 0xaaaaaaaa);
1626 ret |= READL(ramptr + 4, &t1);
1627
1628 if (t1 != 0xcdef0123) {
1629 *bw = 32;
1630 ret |= SETIREGOR(SISSR, 0x15, 0x10);
1631 }
1632 }
1633
1634 } else {
1635
1636 *chab = 0; *bw = 64; /* default: cha, bw = 64 */
1637
1638 done = 0;
1639
1640 if (t1 == 0x456789ab) {
1641 if (t0 == 0x01234567) {
1642 *chab = 0; *bw = 64;
1643 done = 1;
1644 }
1645 } else {
1646 if (t0 == 0x01234567) {
1647 *chab = 0; *bw = 32;
1648 ret |= SETIREG(SISSR, 0x14, 0x00);
1649 done = 1;
1650 }
1651 }
1652
1653 if (!done) {
1654 ret |= SETIREG(SISSR, 0x14, 0x03);
1655 ret |= sisusb_triggersr16(sisusb, ramtype);
1656
1657 ret |= WRITEL(ramptr + 0, 0x01234567);
1658 ret |= WRITEL(ramptr + 4, 0x456789ab);
1659 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1660 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1661 ret |= WRITEL(ramptr + 16, 0x55555555);
1662 ret |= WRITEL(ramptr + 20, 0x55555555);
1663 ret |= WRITEL(ramptr + 24, 0xffffffff);
1664 ret |= WRITEL(ramptr + 28, 0xffffffff);
1665 ret |= READL(ramptr + 0, &t0);
1666 ret |= READL(ramptr + 4, &t1);
1667
1668 if (t1 == 0x456789ab) {
1669 if (t0 == 0x01234567) {
1670 *chab = 1; *bw = 64;
1671 return ret;
1672 } /* else error */
1673 } else {
1674 if (t0 == 0x01234567) {
1675 *chab = 1; *bw = 32;
1676 ret |= SETIREG(SISSR, 0x14, 0x01);
1677 } /* else error */
1678 }
1679 }
1680 }
1681 return ret;
1682 }
1683
1684 static int
1685 sisusb_verify_mclk(struct sisusb_usb_data *sisusb)
1686 {
1687 int ret = 0;
1688 u32 ramptr = SISUSB_PCI_MEMBASE;
1689 u8 tmp1, tmp2, i, j;
1690
1691 ret |= WRITEB(ramptr, 0xaa);
1692 ret |= WRITEB(ramptr + 16, 0x55);
1693 ret |= READB(ramptr, &tmp1);
1694 ret |= READB(ramptr + 16, &tmp2);
1695 if ((tmp1 != 0xaa) || (tmp2 != 0x55)) {
1696 for (i = 0, j = 16; i < 2; i++, j += 16) {
1697 ret |= GETIREG(SISSR, 0x21, &tmp1);
1698 ret |= SETIREGAND(SISSR, 0x21, (tmp1 & 0xfb));
1699 ret |= SETIREGOR(SISSR, 0x3c, 0x01); /* not on 330 */
1700 ret |= SETIREGAND(SISSR, 0x3c, 0xfe); /* not on 330 */
1701 ret |= SETIREG(SISSR, 0x21, tmp1);
1702 ret |= WRITEB(ramptr + 16 + j, j);
1703 ret |= READB(ramptr + 16 + j, &tmp1);
1704 if (tmp1 == j) {
1705 ret |= WRITEB(ramptr + j, j);
1706 break;
1707 }
1708 }
1709 }
1710 return ret;
1711 }
1712
1713 static int
1714 sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret, int index,
1715 u8 rankno, u8 chab, const u8 dramtype[][5],
1716 int bw)
1717 {
1718 int ret = 0, ranksize;
1719 u8 tmp;
1720
1721 *iret = 0;
1722
1723 if ((rankno == 2) && (dramtype[index][0] == 2))
1724 return ret;
1725
1726 ranksize = dramtype[index][3] / 2 * bw / 32;
1727
1728 if ((ranksize * rankno) > 128)
1729 return ret;
1730
1731 tmp = 0;
1732 while ((ranksize >>= 1) > 0) tmp += 0x10;
1733 tmp |= ((rankno - 1) << 2);
1734 tmp |= ((bw / 64) & 0x02);
1735 tmp |= (chab & 0x01);
1736
1737 ret = SETIREG(SISSR, 0x14, tmp);
1738 ret |= sisusb_triggersr16(sisusb, 0); /* sic! */
1739
1740 *iret = 1;
1741
1742 return ret;
1743 }
1744
1745 static int
1746 sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret, u32 inc, int testn)
1747 {
1748 int ret = 0, i;
1749 u32 j, tmp;
1750
1751 *iret = 0;
1752
1753 for (i = 0, j = 0; i < testn; i++) {
1754 ret |= WRITEL(sisusb->vrambase + j, j);
1755 j += inc;
1756 }
1757
1758 for (i = 0, j = 0; i < testn; i++) {
1759 ret |= READL(sisusb->vrambase + j, &tmp);
1760 if (tmp != j) return ret;
1761 j += inc;
1762 }
1763
1764 *iret = 1;
1765 return ret;
1766 }
1767
1768 static int
1769 sisusb_check_ranks(struct sisusb_usb_data *sisusb, int *iret, int rankno,
1770 int idx, int bw, const u8 rtype[][5])
1771 {
1772 int ret = 0, i, i2ret;
1773 u32 inc;
1774
1775 *iret = 0;
1776
1777 for (i = rankno; i >= 1; i--) {
1778 inc = 1 << (rtype[idx][2] +
1779 rtype[idx][1] +
1780 rtype[idx][0] +
1781 bw / 64 + i);
1782 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1783 if (!i2ret)
1784 return ret;
1785 }
1786
1787 inc = 1 << (rtype[idx][2] + bw / 64 + 2);
1788 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 4);
1789 if (!i2ret)
1790 return ret;
1791
1792 inc = 1 << (10 + bw / 64);
1793 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1794 if (!i2ret)
1795 return ret;
1796
1797 *iret = 1;
1798 return ret;
1799 }
1800
1801 static int
1802 sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret, int bw,
1803 int chab)
1804 {
1805 int ret = 0, i2ret = 0, i, j;
1806 static const u8 sdramtype[13][5] = {
1807 { 2, 12, 9, 64, 0x35 },
1808 { 1, 13, 9, 64, 0x44 },
1809 { 2, 12, 8, 32, 0x31 },
1810 { 2, 11, 9, 32, 0x25 },
1811 { 1, 12, 9, 32, 0x34 },
1812 { 1, 13, 8, 32, 0x40 },
1813 { 2, 11, 8, 16, 0x21 },
1814 { 1, 12, 8, 16, 0x30 },
1815 { 1, 11, 9, 16, 0x24 },
1816 { 1, 11, 8, 8, 0x20 },
1817 { 2, 9, 8, 4, 0x01 },
1818 { 1, 10, 8, 4, 0x10 },
1819 { 1, 9, 8, 2, 0x00 }
1820 };
1821
1822 *iret = 1; /* error */
1823
1824 for (i = 0; i < 13; i++) {
1825 ret |= SETIREGANDOR(SISSR, 0x13, 0x80, sdramtype[i][4]);
1826 for (j = 2; j > 0; j--) {
1827 ret |= sisusb_set_rank(sisusb, &i2ret, i, j,
1828 chab, sdramtype, bw);
1829 if (!i2ret)
1830 continue;
1831
1832 ret |= sisusb_check_ranks(sisusb, &i2ret, j, i,
1833 bw, sdramtype);
1834 if (i2ret) {
1835 *iret = 0; /* ram size found */
1836 return ret;
1837 }
1838 }
1839 }
1840
1841 return ret;
1842 }
1843
1844 static int
1845 sisusb_setup_screen(struct sisusb_usb_data *sisusb, int clrall, int drwfr)
1846 {
1847 int ret = 0;
1848 u32 address;
1849 int i, length, modex, modey, bpp;
1850
1851 modex = 640; modey = 480; bpp = 2;
1852
1853 address = sisusb->vrambase; /* Clear video ram */
1854
1855 if (clrall)
1856 length = sisusb->vramsize;
1857 else
1858 length = modex * bpp * modey;
1859
1860 ret = sisusb_clear_vram(sisusb, address, length);
1861
1862 if (!ret && drwfr) {
1863 for (i = 0; i < modex; i++) {
1864 address = sisusb->vrambase + (i * bpp);
1865 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1866 address, 0xf100);
1867 address += (modex * (modey-1) * bpp);
1868 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1869 address, 0xf100);
1870 }
1871 for (i = 0; i < modey; i++) {
1872 address = sisusb->vrambase + ((i * modex) * bpp);
1873 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1874 address, 0xf100);
1875 address += ((modex - 1) * bpp);
1876 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1877 address, 0xf100);
1878 }
1879 }
1880
1881 return ret;
1882 }
1883
1884 static int
1885 sisusb_set_default_mode(struct sisusb_usb_data *sisusb, int touchengines)
1886 {
1887 int ret = 0, i, j, modex, modey, bpp, du;
1888 u8 sr31, cr63, tmp8;
1889 static const char attrdata[] = {
1890 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
1891 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
1892 0x01,0x00,0x00,0x00
1893 };
1894 static const char crtcrdata[] = {
1895 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
1896 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
1897 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
1898 0xff
1899 };
1900 static const char grcdata[] = {
1901 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
1902 0xff
1903 };
1904 static const char crtcdata[] = {
1905 0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
1906 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
1907 0x00
1908 };
1909
1910 modex = 640; modey = 480; bpp = 2;
1911
1912 GETIREG(SISSR, 0x31, &sr31);
1913 GETIREG(SISCR, 0x63, &cr63);
1914 SETIREGOR(SISSR, 0x01, 0x20);
1915 SETIREG(SISCR, 0x63, cr63 & 0xbf);
1916 SETIREGOR(SISCR, 0x17, 0x80);
1917 SETIREGOR(SISSR, 0x1f, 0x04);
1918 SETIREGAND(SISSR, 0x07, 0xfb);
1919 SETIREG(SISSR, 0x00, 0x03); /* seq */
1920 SETIREG(SISSR, 0x01, 0x21);
1921 SETIREG(SISSR, 0x02, 0x0f);
1922 SETIREG(SISSR, 0x03, 0x00);
1923 SETIREG(SISSR, 0x04, 0x0e);
1924 SETREG(SISMISCW, 0x23); /* misc */
1925 for (i = 0; i <= 0x18; i++) { /* crtc */
1926 SETIREG(SISCR, i, crtcrdata[i]);
1927 }
1928 for (i = 0; i <= 0x13; i++) { /* att */
1929 GETREG(SISINPSTAT, &tmp8);
1930 SETREG(SISAR, i);
1931 SETREG(SISAR, attrdata[i]);
1932 }
1933 GETREG(SISINPSTAT, &tmp8);
1934 SETREG(SISAR, 0x14);
1935 SETREG(SISAR, 0x00);
1936 GETREG(SISINPSTAT, &tmp8);
1937 SETREG(SISAR, 0x20);
1938 GETREG(SISINPSTAT, &tmp8);
1939 for (i = 0; i <= 0x08; i++) { /* grc */
1940 SETIREG(SISGR, i, grcdata[i]);
1941 }
1942 SETIREGAND(SISGR, 0x05, 0xbf);
1943 for (i = 0x0A; i <= 0x0E; i++) { /* clr ext */
1944 SETIREG(SISSR, i, 0x00);
1945 }
1946 SETIREGAND(SISSR, 0x37, 0xfe);
1947 SETREG(SISMISCW, 0xef); /* sync */
1948 SETIREG(SISCR, 0x11, 0x00); /* crtc */
1949 for (j = 0x00, i = 0; i <= 7; i++, j++) {
1950 SETIREG(SISCR, j, crtcdata[i]);
1951 }
1952 for (j = 0x10; i <= 10; i++, j++) {
1953 SETIREG(SISCR, j, crtcdata[i]);
1954 }
1955 for (j = 0x15; i <= 12; i++, j++) {
1956 SETIREG(SISCR, j, crtcdata[i]);
1957 }
1958 for (j = 0x0A; i <= 15; i++, j++) {
1959 SETIREG(SISSR, j, crtcdata[i]);
1960 }
1961 SETIREG(SISSR, 0x0E, (crtcdata[16] & 0xE0));
1962 SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5));
1963 SETIREG(SISCR, 0x14, 0x4f);
1964 du = (modex / 16) * (bpp * 2); /* offset/pitch */
1965 if (modex % 16) du += bpp;
1966 SETIREGANDOR(SISSR, 0x0e, 0xf0, ((du >> 8) & 0x0f));
1967 SETIREG(SISCR, 0x13, (du & 0xff));
1968 du <<= 5;
1969 tmp8 = du >> 8;
1970 if (du & 0xff) tmp8++;
1971 SETIREG(SISSR, 0x10, tmp8);
1972 SETIREG(SISSR, 0x31, 0x00); /* VCLK */
1973 SETIREG(SISSR, 0x2b, 0x1b);
1974 SETIREG(SISSR, 0x2c, 0xe1);
1975 SETIREG(SISSR, 0x2d, 0x01);
1976 SETIREGAND(SISSR, 0x3d, 0xfe); /* FIFO */
1977 SETIREG(SISSR, 0x08, 0xae);
1978 SETIREGAND(SISSR, 0x09, 0xf0);
1979 SETIREG(SISSR, 0x08, 0x34);
1980 SETIREGOR(SISSR, 0x3d, 0x01);
1981 SETIREGAND(SISSR, 0x1f, 0x3f); /* mode regs */
1982 SETIREGANDOR(SISSR, 0x06, 0xc0, 0x0a);
1983 SETIREG(SISCR, 0x19, 0x00);
1984 SETIREGAND(SISCR, 0x1a, 0xfc);
1985 SETIREGAND(SISSR, 0x0f, 0xb7);
1986 SETIREGAND(SISSR, 0x31, 0xfb);
1987 SETIREGANDOR(SISSR, 0x21, 0x1f, 0xa0);
1988 SETIREGAND(SISSR, 0x32, 0xf3);
1989 SETIREGANDOR(SISSR, 0x07, 0xf8, 0x03);
1990 SETIREG(SISCR, 0x52, 0x6c);
1991
1992 SETIREG(SISCR, 0x0d, 0x00); /* adjust frame */
1993 SETIREG(SISCR, 0x0c, 0x00);
1994 SETIREG(SISSR, 0x0d, 0x00);
1995 SETIREGAND(SISSR, 0x37, 0xfe);
1996
1997 SETIREG(SISCR, 0x32, 0x20);
1998 SETIREGAND(SISSR, 0x01, 0xdf); /* enable display */
1999 SETIREG(SISCR, 0x63, (cr63 & 0xbf));
2000 SETIREG(SISSR, 0x31, (sr31 & 0xfb));
2001
2002 if (touchengines) {
2003 SETIREG(SISSR, 0x20, 0xa1); /* enable engines */
2004 SETIREGOR(SISSR, 0x1e, 0x5a);
2005
2006 SETIREG(SISSR, 0x26, 0x01); /* disable cmdqueue */
2007 SETIREG(SISSR, 0x27, 0x1f);
2008 SETIREG(SISSR, 0x26, 0x00);
2009 }
2010
2011 SETIREG(SISCR, 0x34, 0x44); /* we just set std mode #44 */
2012
2013 return ret;
2014 }
2015
2016 static int
2017 sisusb_init_gfxcore(struct sisusb_usb_data *sisusb)
2018 {
2019 int ret = 0, i, j, bw, chab, iret, retry = 3;
2020 u8 tmp8, ramtype;
2021 u32 tmp32;
2022 static const char mclktable[] = {
2023 0x3b, 0x22, 0x01, 143,
2024 0x3b, 0x22, 0x01, 143,
2025 0x3b, 0x22, 0x01, 143,
2026 0x3b, 0x22, 0x01, 143
2027 };
2028 static const char eclktable[] = {
2029 0x3b, 0x22, 0x01, 143,
2030 0x3b, 0x22, 0x01, 143,
2031 0x3b, 0x22, 0x01, 143,
2032 0x3b, 0x22, 0x01, 143
2033 };
2034 static const char ramtypetable1[] = {
2035 0x00, 0x04, 0x60, 0x60,
2036 0x0f, 0x0f, 0x1f, 0x1f,
2037 0xba, 0xba, 0xba, 0xba,
2038 0xa9, 0xa9, 0xac, 0xac,
2039 0xa0, 0xa0, 0xa0, 0xa8,
2040 0x00, 0x00, 0x02, 0x02,
2041 0x30, 0x30, 0x40, 0x40
2042 };
2043 static const char ramtypetable2[] = {
2044 0x77, 0x77, 0x44, 0x44,
2045 0x77, 0x77, 0x44, 0x44,
2046 0x00, 0x00, 0x00, 0x00,
2047 0x5b, 0x5b, 0xab, 0xab,
2048 0x00, 0x00, 0xf0, 0xf8
2049 };
2050
2051 while (retry--) {
2052
2053 /* Enable VGA */
2054 ret = GETREG(SISVGAEN, &tmp8);
2055 ret |= SETREG(SISVGAEN, (tmp8 | 0x01));
2056
2057 /* Enable GPU access to VRAM */
2058 ret |= GETREG(SISMISCR, &tmp8);
2059 ret |= SETREG(SISMISCW, (tmp8 | 0x01));
2060
2061 if (ret) continue;
2062
2063 /* Reset registers */
2064 ret |= SETIREGAND(SISCR, 0x5b, 0xdf);
2065 ret |= SETIREG(SISSR, 0x05, 0x86);
2066 ret |= SETIREGOR(SISSR, 0x20, 0x01);
2067
2068 ret |= SETREG(SISMISCW, 0x67);
2069
2070 for (i = 0x06; i <= 0x1f; i++) {
2071 ret |= SETIREG(SISSR, i, 0x00);
2072 }
2073 for (i = 0x21; i <= 0x27; i++) {
2074 ret |= SETIREG(SISSR, i, 0x00);
2075 }
2076 for (i = 0x31; i <= 0x3d; i++) {
2077 ret |= SETIREG(SISSR, i, 0x00);
2078 }
2079 for (i = 0x12; i <= 0x1b; i++) {
2080 ret |= SETIREG(SISSR, i, 0x00);
2081 }
2082 for (i = 0x79; i <= 0x7c; i++) {
2083 ret |= SETIREG(SISCR, i, 0x00);
2084 }
2085
2086 if (ret) continue;
2087
2088 ret |= SETIREG(SISCR, 0x63, 0x80);
2089
2090 ret |= GETIREG(SISSR, 0x3a, &ramtype);
2091 ramtype &= 0x03;
2092
2093 ret |= SETIREG(SISSR, 0x28, mclktable[ramtype * 4]);
2094 ret |= SETIREG(SISSR, 0x29, mclktable[(ramtype * 4) + 1]);
2095 ret |= SETIREG(SISSR, 0x2a, mclktable[(ramtype * 4) + 2]);
2096
2097 ret |= SETIREG(SISSR, 0x2e, eclktable[ramtype * 4]);
2098 ret |= SETIREG(SISSR, 0x2f, eclktable[(ramtype * 4) + 1]);
2099 ret |= SETIREG(SISSR, 0x30, eclktable[(ramtype * 4) + 2]);
2100
2101 ret |= SETIREG(SISSR, 0x07, 0x18);
2102 ret |= SETIREG(SISSR, 0x11, 0x0f);
2103
2104 if (ret) continue;
2105
2106 for (i = 0x15, j = 0; i <= 0x1b; i++, j++) {
2107 ret |= SETIREG(SISSR, i, ramtypetable1[(j*4) + ramtype]);
2108 }
2109 for (i = 0x40, j = 0; i <= 0x44; i++, j++) {
2110 ret |= SETIREG(SISCR, i, ramtypetable2[(j*4) + ramtype]);
2111 }
2112
2113 ret |= SETIREG(SISCR, 0x49, 0xaa);
2114
2115 ret |= SETIREG(SISSR, 0x1f, 0x00);
2116 ret |= SETIREG(SISSR, 0x20, 0xa0);
2117 ret |= SETIREG(SISSR, 0x23, 0xf6);
2118 ret |= SETIREG(SISSR, 0x24, 0x0d);
2119 ret |= SETIREG(SISSR, 0x25, 0x33);
2120
2121 ret |= SETIREG(SISSR, 0x11, 0x0f);
2122
2123 ret |= SETIREGOR(SISPART1, 0x2f, 0x01);
2124
2125 ret |= SETIREGAND(SISCAP, 0x3f, 0xef);
2126
2127 if (ret) continue;
2128
2129 ret |= SETIREG(SISPART1, 0x00, 0x00);
2130
2131 ret |= GETIREG(SISSR, 0x13, &tmp8);
2132 tmp8 >>= 4;
2133
2134 ret |= SETIREG(SISPART1, 0x02, 0x00);
2135 ret |= SETIREG(SISPART1, 0x2e, 0x08);
2136
2137 ret |= sisusb_read_pci_config(sisusb, 0x50, &tmp32);
2138 tmp32 &= 0x00f00000;
2139 tmp8 = (tmp32 == 0x100000) ? 0x33 : 0x03;
2140 ret |= SETIREG(SISSR, 0x25, tmp8);
2141 tmp8 = (tmp32 == 0x100000) ? 0xaa : 0x88;
2142 ret |= SETIREG(SISCR, 0x49, tmp8);
2143
2144 ret |= SETIREG(SISSR, 0x27, 0x1f);
2145 ret |= SETIREG(SISSR, 0x31, 0x00);
2146 ret |= SETIREG(SISSR, 0x32, 0x11);
2147 ret |= SETIREG(SISSR, 0x33, 0x00);
2148
2149 if (ret) continue;
2150
2151 ret |= SETIREG(SISCR, 0x83, 0x00);
2152
2153 ret |= sisusb_set_default_mode(sisusb, 0);
2154
2155 ret |= SETIREGAND(SISSR, 0x21, 0xdf);
2156 ret |= SETIREGOR(SISSR, 0x01, 0x20);
2157 ret |= SETIREGOR(SISSR, 0x16, 0x0f);
2158
2159 ret |= sisusb_triggersr16(sisusb, ramtype);
2160
2161 /* Disable refresh */
2162 ret |= SETIREGAND(SISSR, 0x17, 0xf8);
2163 ret |= SETIREGOR(SISSR, 0x19, 0x03);
2164
2165 ret |= sisusb_getbuswidth(sisusb, &bw, &chab);
2166 ret |= sisusb_verify_mclk(sisusb);
2167
2168 if (ramtype <= 1) {
2169 ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab);
2170 if (iret) {
2171 printk(KERN_ERR "sisusbvga[%d]: RAM size "
2172 "detection failed, "
2173 "assuming 8MB video RAM\n",
2174 sisusb->minor);
2175 ret |= SETIREG(SISSR,0x14,0x31);
2176 /* TODO */
2177 }
2178 } else {
2179 printk(KERN_ERR "sisusbvga[%d]: DDR RAM device found, "
2180 "assuming 8MB video RAM\n",
2181 sisusb->minor);
2182 ret |= SETIREG(SISSR,0x14,0x31);
2183 /* *** TODO *** */
2184 }
2185
2186 /* Enable refresh */
2187 ret |= SETIREG(SISSR, 0x16, ramtypetable1[4 + ramtype]);
2188 ret |= SETIREG(SISSR, 0x17, ramtypetable1[8 + ramtype]);
2189 ret |= SETIREG(SISSR, 0x19, ramtypetable1[16 + ramtype]);
2190
2191 ret |= SETIREGOR(SISSR, 0x21, 0x20);
2192
2193 ret |= SETIREG(SISSR, 0x22, 0xfb);
2194 ret |= SETIREG(SISSR, 0x21, 0xa5);
2195
2196 if (ret == 0)
2197 break;
2198 }
2199
2200 return ret;
2201 }
2202
2203 #undef SETREG
2204 #undef GETREG
2205 #undef SETIREG
2206 #undef GETIREG
2207 #undef SETIREGOR
2208 #undef SETIREGAND
2209 #undef SETIREGANDOR
2210 #undef READL
2211 #undef WRITEL
2212
2213 static void
2214 sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
2215 {
2216 u8 tmp8, tmp82, ramtype;
2217 int bw = 0;
2218 char *ramtypetext1 = NULL;
2219 const char *ramtypetext2[] = { "SDR SDRAM", "SDR SGRAM",
2220 "DDR SDRAM", "DDR SGRAM" };
2221 static const int busSDR[4] = {64, 64, 128, 128};
2222 static const int busDDR[4] = {32, 32, 64, 64};
2223 static const int busDDRA[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2};
2224
2225 sisusb_getidxreg(sisusb, SISSR, 0x14, &tmp8);
2226 sisusb_getidxreg(sisusb, SISSR, 0x15, &tmp82);
2227 sisusb_getidxreg(sisusb, SISSR, 0x3a, &ramtype);
2228 sisusb->vramsize = (1 << ((tmp8 & 0xf0) >> 4)) * 1024 * 1024;
2229 ramtype &= 0x03;
2230 switch ((tmp8 >> 2) & 0x03) {
2231 case 0: ramtypetext1 = "1 ch/1 r";
2232 if (tmp82 & 0x10) {
2233 bw = 32;
2234 } else {
2235 bw = busSDR[(tmp8 & 0x03)];
2236 }
2237 break;
2238 case 1: ramtypetext1 = "1 ch/2 r";
2239 sisusb->vramsize <<= 1;
2240 bw = busSDR[(tmp8 & 0x03)];
2241 break;
2242 case 2: ramtypetext1 = "asymmeric";
2243 sisusb->vramsize += sisusb->vramsize/2;
2244 bw = busDDRA[(tmp8 & 0x03)];
2245 break;
2246 case 3: ramtypetext1 = "2 channel";
2247 sisusb->vramsize <<= 1;
2248 bw = busDDR[(tmp8 & 0x03)];
2249 break;
2250 }
2251
2252 printk(KERN_INFO "sisusbvga[%d]: %dMB %s %s, bus width %d\n",
2253 sisusb->minor, (sisusb->vramsize >> 20), ramtypetext1,
2254 ramtypetext2[ramtype], bw);
2255 }
2256
2257 static int
2258 sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb)
2259 {
2260 struct sisusb_packet packet;
2261 int ret;
2262 u32 tmp32;
2263
2264 /* Do some magic */
2265 packet.header = 0x001f;
2266 packet.address = 0x00000324;
2267 packet.data = 0x00000004;
2268 ret = sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2269
2270 packet.header = 0x001f;
2271 packet.address = 0x00000364;
2272 packet.data = 0x00000004;
2273 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2274
2275 packet.header = 0x001f;
2276 packet.address = 0x00000384;
2277 packet.data = 0x00000004;
2278 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2279
2280 packet.header = 0x001f;
2281 packet.address = 0x00000100;
2282 packet.data = 0x00000700;
2283 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2284
2285 packet.header = 0x000f;
2286 packet.address = 0x00000004;
2287 ret |= sisusb_send_bridge_packet(sisusb, 6, &packet, 0);
2288 packet.data |= 0x17;
2289 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2290
2291 /* Init BAR 0 (VRAM) */
2292 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2293 ret |= sisusb_write_pci_config(sisusb, 0x10, 0xfffffff0);
2294 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2295 tmp32 &= 0x0f;
2296 tmp32 |= SISUSB_PCI_MEMBASE;
2297 ret |= sisusb_write_pci_config(sisusb, 0x10, tmp32);
2298
2299 /* Init BAR 1 (MMIO) */
2300 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2301 ret |= sisusb_write_pci_config(sisusb, 0x14, 0xfffffff0);
2302 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2303 tmp32 &= 0x0f;
2304 tmp32 |= SISUSB_PCI_MMIOBASE;
2305 ret |= sisusb_write_pci_config(sisusb, 0x14, tmp32);
2306
2307 /* Init BAR 2 (i/o ports) */
2308 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2309 ret |= sisusb_write_pci_config(sisusb, 0x18, 0xfffffff0);
2310 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2311 tmp32 &= 0x0f;
2312 tmp32 |= SISUSB_PCI_IOPORTBASE;
2313 ret |= sisusb_write_pci_config(sisusb, 0x18, tmp32);
2314
2315 /* Enable memory and i/o access */
2316 ret |= sisusb_read_pci_config(sisusb, 0x04, &tmp32);
2317 tmp32 |= 0x3;
2318 ret |= sisusb_write_pci_config(sisusb, 0x04, tmp32);
2319
2320 if (ret == 0) {
2321 /* Some further magic */
2322 packet.header = 0x001f;
2323 packet.address = 0x00000050;
2324 packet.data = 0x000000ff;
2325 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2326 }
2327
2328 return ret;
2329 }
2330
2331 /* Initialize the graphics device (return 0 on success)
2332 * This initializes the net2280 as well as the PCI registers
2333 * of the graphics board.
2334 */
2335
2336 static int
2337 sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
2338 {
2339 int ret = 0, test = 0;
2340 u32 tmp32;
2341
2342 if (sisusb->devinit == 1) {
2343 /* Read PCI BARs and see if they have been set up */
2344 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2345 if (ret) return ret;
2346 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE) test++;
2347
2348 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2349 if (ret) return ret;
2350 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE) test++;
2351
2352 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2353 if (ret) return ret;
2354 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE) test++;
2355 }
2356
2357 /* No? So reset the device */
2358 if ((sisusb->devinit == 0) || (test != 3)) {
2359
2360 ret |= sisusb_do_init_gfxdevice(sisusb);
2361
2362 if (ret == 0)
2363 sisusb->devinit = 1;
2364
2365 }
2366
2367 if (sisusb->devinit) {
2368 /* Initialize the graphics core */
2369 if (sisusb_init_gfxcore(sisusb) == 0) {
2370 sisusb->gfxinit = 1;
2371 sisusb_get_ramconfig(sisusb);
2372 ret |= sisusb_set_default_mode(sisusb, 1);
2373 ret |= sisusb_setup_screen(sisusb, 1, initscreen);
2374 }
2375 }
2376
2377 return ret;
2378 }
2379
2380
2381 #ifdef INCL_SISUSB_CON
2382
2383 /* Set up default text mode:
2384 - Set text mode (0x03)
2385 - Upload default font
2386 - Upload user font (if available)
2387 */
2388
2389 int
2390 sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
2391 {
2392 int ret = 0, slot = sisusb->font_slot, i;
2393 const struct font_desc *myfont;
2394 u8 *tempbuf;
2395 u16 *tempbufb;
2396 size_t written;
2397 static const char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2398 static const char bootlogo[] = "(o_ //\\ V_/_";
2399
2400 /* sisusb->lock is down */
2401
2402 if (!sisusb->SiS_Pr)
2403 return 1;
2404
2405 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2406 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2407
2408 /* Set mode 0x03 */
2409 SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
2410
2411 if (!(myfont = find_font("VGA8x16")))
2412 return 1;
2413
2414 if (!(tempbuf = vmalloc(8192)))
2415 return 1;
2416
2417 for (i = 0; i < 256; i++)
2418 memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
2419
2420 /* Upload default font */
2421 ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, 0, 1, NULL, 16, 0);
2422
2423 vfree(tempbuf);
2424
2425 /* Upload user font (and reset current slot) */
2426 if (sisusb->font_backup) {
2427 ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
2428 8192, sisusb->font_backup_512, 1, NULL,
2429 sisusb->font_backup_height, 0);
2430 if (slot != 2)
2431 sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
2432 NULL, 16, 0);
2433 }
2434
2435 if (init && !sisusb->scrbuf) {
2436
2437 if ((tempbuf = vmalloc(8192))) {
2438
2439 i = 4096;
2440 tempbufb = (u16 *)tempbuf;
2441 while (i--)
2442 *(tempbufb++) = 0x0720;
2443
2444 i = 0;
2445 tempbufb = (u16 *)tempbuf;
2446 while (bootlogo[i]) {
2447 *(tempbufb++) = 0x0700 | bootlogo[i++];
2448 if (!(i % 4))
2449 tempbufb += 76;
2450 }
2451
2452 i = 0;
2453 tempbufb = (u16 *)tempbuf + 6;
2454 while (bootstring[i])
2455 *(tempbufb++) = 0x0700 | bootstring[i++];
2456
2457 ret |= sisusb_copy_memory(sisusb, tempbuf,
2458 sisusb->vrambase, 8192, &written);
2459
2460 vfree(tempbuf);
2461
2462 }
2463
2464 } else if (sisusb->scrbuf) {
2465
2466 ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
2467 sisusb->vrambase, sisusb->scrbuf_size, &written);
2468
2469 }
2470
2471 if (sisusb->sisusb_cursor_size_from >= 0 &&
2472 sisusb->sisusb_cursor_size_to >= 0) {
2473 sisusb_setidxreg(sisusb, SISCR, 0x0a,
2474 sisusb->sisusb_cursor_size_from);
2475 sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
2476 sisusb->sisusb_cursor_size_to);
2477 } else {
2478 sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
2479 sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
2480 sisusb->sisusb_cursor_size_to = -1;
2481 }
2482
2483 slot = sisusb->sisusb_cursor_loc;
2484 if(slot < 0) slot = 0;
2485
2486 sisusb->sisusb_cursor_loc = -1;
2487 sisusb->bad_cursor_pos = 1;
2488
2489 sisusb_set_cursor(sisusb, slot);
2490
2491 sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
2492 sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
2493
2494 sisusb->textmodedestroyed = 0;
2495
2496 /* sisusb->lock is down */
2497
2498 return ret;
2499 }
2500
2501 #endif
2502
2503 /* fops */
2504
2505 static int
2506 sisusb_open(struct inode *inode, struct file *file)
2507 {
2508 struct sisusb_usb_data *sisusb;
2509 struct usb_interface *interface;
2510 int subminor = iminor(inode);
2511
2512 if (!(interface = usb_find_interface(&sisusb_driver, subminor))) {
2513 printk(KERN_ERR "sisusb[%d]: Failed to find interface\n",
2514 subminor);
2515 return -ENODEV;
2516 }
2517
2518 if (!(sisusb = usb_get_intfdata(interface)))
2519 return -ENODEV;
2520
2521 mutex_lock(&sisusb->lock);
2522
2523 if (!sisusb->present || !sisusb->ready) {
2524 mutex_unlock(&sisusb->lock);
2525 return -ENODEV;
2526 }
2527
2528 if (sisusb->isopen) {
2529 mutex_unlock(&sisusb->lock);
2530 return -EBUSY;
2531 }
2532
2533 if (!sisusb->devinit) {
2534 if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) {
2535 if (sisusb_init_gfxdevice(sisusb, 0)) {
2536 mutex_unlock(&sisusb->lock);
2537 printk(KERN_ERR
2538 "sisusbvga[%d]: Failed to initialize "
2539 "device\n",
2540 sisusb->minor);
2541 return -EIO;
2542 }
2543 } else {
2544 mutex_unlock(&sisusb->lock);
2545 printk(KERN_ERR
2546 "sisusbvga[%d]: Device not attached to "
2547 "USB 2.0 hub\n",
2548 sisusb->minor);
2549 return -EIO;
2550 }
2551 }
2552
2553 /* Increment usage count for our sisusb */
2554 kref_get(&sisusb->kref);
2555
2556 sisusb->isopen = 1;
2557
2558 file->private_data = sisusb;
2559
2560 mutex_unlock(&sisusb->lock);
2561
2562 return 0;
2563 }
2564
2565 void
2566 sisusb_delete(struct kref *kref)
2567 {
2568 struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
2569
2570 if (!sisusb)
2571 return;
2572
2573 if (sisusb->sisusb_dev)
2574 usb_put_dev(sisusb->sisusb_dev);
2575
2576 sisusb->sisusb_dev = NULL;
2577 sisusb_free_buffers(sisusb);
2578 sisusb_free_urbs(sisusb);
2579 #ifdef INCL_SISUSB_CON
2580 kfree(sisusb->SiS_Pr);
2581 #endif
2582 kfree(sisusb);
2583 }
2584
2585 static int
2586 sisusb_release(struct inode *inode, struct file *file)
2587 {
2588 struct sisusb_usb_data *sisusb;
2589 int myminor;
2590
2591 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2592 return -ENODEV;
2593
2594 mutex_lock(&sisusb->lock);
2595
2596 if (sisusb->present) {
2597 /* Wait for all URBs to finish if device still present */
2598 if (!sisusb_wait_all_out_complete(sisusb))
2599 sisusb_kill_all_busy(sisusb);
2600 }
2601
2602 myminor = sisusb->minor;
2603
2604 sisusb->isopen = 0;
2605 file->private_data = NULL;
2606
2607 mutex_unlock(&sisusb->lock);
2608
2609 /* decrement the usage count on our device */
2610 kref_put(&sisusb->kref, sisusb_delete);
2611
2612 return 0;
2613 }
2614
2615 static ssize_t
2616 sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
2617 {
2618 struct sisusb_usb_data *sisusb;
2619 ssize_t bytes_read = 0;
2620 int errno = 0;
2621 u8 buf8;
2622 u16 buf16;
2623 u32 buf32, address;
2624
2625 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2626 return -ENODEV;
2627
2628 mutex_lock(&sisusb->lock);
2629
2630 /* Sanity check */
2631 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2632 mutex_unlock(&sisusb->lock);
2633 return -ENODEV;
2634 }
2635
2636 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2637 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2638
2639 address = (*ppos) -
2640 SISUSB_PCI_PSEUDO_IOPORTBASE +
2641 SISUSB_PCI_IOPORTBASE;
2642
2643 /* Read i/o ports
2644 * Byte, word and long(32) can be read. As this
2645 * emulates inX instructions, the data returned is
2646 * in machine-endianness.
2647 */
2648 switch (count) {
2649
2650 case 1:
2651 if (sisusb_read_memio_byte(sisusb,
2652 SISUSB_TYPE_IO,
2653 address, &buf8))
2654 errno = -EIO;
2655 else if (put_user(buf8, (u8 __user *)buffer))
2656 errno = -EFAULT;
2657 else
2658 bytes_read = 1;
2659
2660 break;
2661
2662 case 2:
2663 if (sisusb_read_memio_word(sisusb,
2664 SISUSB_TYPE_IO,
2665 address, &buf16))
2666 errno = -EIO;
2667 else if (put_user(buf16, (u16 __user *)buffer))
2668 errno = -EFAULT;
2669 else
2670 bytes_read = 2;
2671
2672 break;
2673
2674 case 4:
2675 if (sisusb_read_memio_long(sisusb,
2676 SISUSB_TYPE_IO,
2677 address, &buf32))
2678 errno = -EIO;
2679 else if (put_user(buf32, (u32 __user *)buffer))
2680 errno = -EFAULT;
2681 else
2682 bytes_read = 4;
2683
2684 break;
2685
2686 default:
2687 errno = -EIO;
2688
2689 }
2690
2691 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2692 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2693
2694 address = (*ppos) -
2695 SISUSB_PCI_PSEUDO_MEMBASE +
2696 SISUSB_PCI_MEMBASE;
2697
2698 /* Read video ram
2699 * Remember: Data delivered is never endian-corrected
2700 */
2701 errno = sisusb_read_mem_bulk(sisusb, address,
2702 NULL, count, buffer, &bytes_read);
2703
2704 if (bytes_read)
2705 errno = bytes_read;
2706
2707 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2708 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) {
2709
2710 address = (*ppos) -
2711 SISUSB_PCI_PSEUDO_MMIOBASE +
2712 SISUSB_PCI_MMIOBASE;
2713
2714 /* Read MMIO
2715 * Remember: Data delivered is never endian-corrected
2716 */
2717 errno = sisusb_read_mem_bulk(sisusb, address,
2718 NULL, count, buffer, &bytes_read);
2719
2720 if (bytes_read)
2721 errno = bytes_read;
2722
2723 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2724 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
2725
2726 if (count != 4) {
2727 mutex_unlock(&sisusb->lock);
2728 return -EINVAL;
2729 }
2730
2731 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2732
2733 /* Read PCI config register
2734 * Return value delivered in machine endianness.
2735 */
2736 if (sisusb_read_pci_config(sisusb, address, &buf32))
2737 errno = -EIO;
2738 else if (put_user(buf32, (u32 __user *)buffer))
2739 errno = -EFAULT;
2740 else
2741 bytes_read = 4;
2742
2743 } else {
2744
2745 errno = -EBADFD;
2746
2747 }
2748
2749 (*ppos) += bytes_read;
2750
2751 mutex_unlock(&sisusb->lock);
2752
2753 return errno ? errno : bytes_read;
2754 }
2755
2756 static ssize_t
2757 sisusb_write(struct file *file, const char __user *buffer, size_t count,
2758 loff_t *ppos)
2759 {
2760 struct sisusb_usb_data *sisusb;
2761 int errno = 0;
2762 ssize_t bytes_written = 0;
2763 u8 buf8;
2764 u16 buf16;
2765 u32 buf32, address;
2766
2767 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2768 return -ENODEV;
2769
2770 mutex_lock(&sisusb->lock);
2771
2772 /* Sanity check */
2773 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2774 mutex_unlock(&sisusb->lock);
2775 return -ENODEV;
2776 }
2777
2778 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2779 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2780
2781 address = (*ppos) -
2782 SISUSB_PCI_PSEUDO_IOPORTBASE +
2783 SISUSB_PCI_IOPORTBASE;
2784
2785 /* Write i/o ports
2786 * Byte, word and long(32) can be written. As this
2787 * emulates outX instructions, the data is expected
2788 * in machine-endianness.
2789 */
2790 switch (count) {
2791
2792 case 1:
2793 if (get_user(buf8, (u8 __user *)buffer))
2794 errno = -EFAULT;
2795 else if (sisusb_write_memio_byte(sisusb,
2796 SISUSB_TYPE_IO,
2797 address, buf8))
2798 errno = -EIO;
2799 else
2800 bytes_written = 1;
2801
2802 break;
2803
2804 case 2:
2805 if (get_user(buf16, (u16 __user *)buffer))
2806 errno = -EFAULT;
2807 else if (sisusb_write_memio_word(sisusb,
2808 SISUSB_TYPE_IO,
2809 address, buf16))
2810 errno = -EIO;
2811 else
2812 bytes_written = 2;
2813
2814 break;
2815
2816 case 4:
2817 if (get_user(buf32, (u32 __user *)buffer))
2818 errno = -EFAULT;
2819 else if (sisusb_write_memio_long(sisusb,
2820 SISUSB_TYPE_IO,
2821 address, buf32))
2822 errno = -EIO;
2823 else
2824 bytes_written = 4;
2825
2826 break;
2827
2828 default:
2829 errno = -EIO;
2830 }
2831
2832 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2833 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2834
2835 address = (*ppos) -
2836 SISUSB_PCI_PSEUDO_MEMBASE +
2837 SISUSB_PCI_MEMBASE;
2838
2839 /* Write video ram.
2840 * Buffer is copied 1:1, therefore, on big-endian
2841 * machines, the data must be swapped by userland
2842 * in advance (if applicable; no swapping in 8bpp
2843 * mode or if YUV data is being transferred).
2844 */
2845 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2846 count, buffer, 0, &bytes_written);
2847
2848 if (bytes_written)
2849 errno = bytes_written;
2850
2851 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2852 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) {
2853
2854 address = (*ppos) -
2855 SISUSB_PCI_PSEUDO_MMIOBASE +
2856 SISUSB_PCI_MMIOBASE;
2857
2858 /* Write MMIO.
2859 * Buffer is copied 1:1, therefore, on big-endian
2860 * machines, the data must be swapped by userland
2861 * in advance.
2862 */
2863 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2864 count, buffer, 0, &bytes_written);
2865
2866 if (bytes_written)
2867 errno = bytes_written;
2868
2869 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2870 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + SISUSB_PCI_PCONFSIZE) {
2871
2872 if (count != 4) {
2873 mutex_unlock(&sisusb->lock);
2874 return -EINVAL;
2875 }
2876
2877 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2878
2879 /* Write PCI config register.
2880 * Given value expected in machine endianness.
2881 */
2882 if (get_user(buf32, (u32 __user *)buffer))
2883 errno = -EFAULT;
2884 else if (sisusb_write_pci_config(sisusb, address, buf32))
2885 errno = -EIO;
2886 else
2887 bytes_written = 4;
2888
2889
2890 } else {
2891
2892 /* Error */
2893 errno = -EBADFD;
2894
2895 }
2896
2897 (*ppos) += bytes_written;
2898
2899 mutex_unlock(&sisusb->lock);
2900
2901 return errno ? errno : bytes_written;
2902 }
2903
2904 static loff_t
2905 sisusb_lseek(struct file *file, loff_t offset, int orig)
2906 {
2907 struct sisusb_usb_data *sisusb;
2908 loff_t ret;
2909
2910 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2911 return -ENODEV;
2912
2913 mutex_lock(&sisusb->lock);
2914
2915 /* Sanity check */
2916 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2917 mutex_unlock(&sisusb->lock);
2918 return -ENODEV;
2919 }
2920
2921 switch (orig) {
2922 case 0:
2923 file->f_pos = offset;
2924 ret = file->f_pos;
2925 /* never negative, no force_successful_syscall needed */
2926 break;
2927 case 1:
2928 file->f_pos += offset;
2929 ret = file->f_pos;
2930 /* never negative, no force_successful_syscall needed */
2931 break;
2932 default:
2933 /* seeking relative to "end of file" is not supported */
2934 ret = -EINVAL;
2935 }
2936
2937 mutex_unlock(&sisusb->lock);
2938 return ret;
2939 }
2940
2941 static int
2942 sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
2943 unsigned long arg)
2944 {
2945 int retval, port, length;
2946 u32 address;
2947
2948 /* All our commands require the device
2949 * to be initialized.
2950 */
2951 if (!sisusb->devinit)
2952 return -ENODEV;
2953
2954 port = y->data3 -
2955 SISUSB_PCI_PSEUDO_IOPORTBASE +
2956 SISUSB_PCI_IOPORTBASE;
2957
2958 switch (y->operation) {
2959 case SUCMD_GET:
2960 retval = sisusb_getidxreg(sisusb, port,
2961 y->data0, &y->data1);
2962 if (!retval) {
2963 if (copy_to_user((void __user *)arg, y,
2964 sizeof(*y)))
2965 retval = -EFAULT;
2966 }
2967 break;
2968
2969 case SUCMD_SET:
2970 retval = sisusb_setidxreg(sisusb, port,
2971 y->data0, y->data1);
2972 break;
2973
2974 case SUCMD_SETOR:
2975 retval = sisusb_setidxregor(sisusb, port,
2976 y->data0, y->data1);
2977 break;
2978
2979 case SUCMD_SETAND:
2980 retval = sisusb_setidxregand(sisusb, port,
2981 y->data0, y->data1);
2982 break;
2983
2984 case SUCMD_SETANDOR:
2985 retval = sisusb_setidxregandor(sisusb, port,
2986 y->data0, y->data1, y->data2);
2987 break;
2988
2989 case SUCMD_SETMASK:
2990 retval = sisusb_setidxregmask(sisusb, port,
2991 y->data0, y->data1, y->data2);
2992 break;
2993
2994 case SUCMD_CLRSCR:
2995 /* Gfx core must be initialized */
2996 if (!sisusb->gfxinit)
2997 return -ENODEV;
2998
2999 length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
3000 address = y->data3 -
3001 SISUSB_PCI_PSEUDO_MEMBASE +
3002 SISUSB_PCI_MEMBASE;
3003 retval = sisusb_clear_vram(sisusb, address, length);
3004 break;
3005
3006 case SUCMD_HANDLETEXTMODE:
3007 retval = 0;
3008 #ifdef INCL_SISUSB_CON
3009 /* Gfx core must be initialized, SiS_Pr must exist */
3010 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
3011 return -ENODEV;
3012
3013 switch (y->data0) {
3014 case 0:
3015 retval = sisusb_reset_text_mode(sisusb, 0);
3016 break;
3017 case 1:
3018 sisusb->textmodedestroyed = 1;
3019 break;
3020 }
3021 #endif
3022 break;
3023
3024 #ifdef INCL_SISUSB_CON
3025 case SUCMD_SETMODE:
3026 /* Gfx core must be initialized, SiS_Pr must exist */
3027 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
3028 return -ENODEV;
3029
3030 retval = 0;
3031
3032 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
3033 sisusb->SiS_Pr->sisusb = (void *)sisusb;
3034
3035 if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
3036 retval = -EINVAL;
3037
3038 break;
3039
3040 case SUCMD_SETVESAMODE:
3041 /* Gfx core must be initialized, SiS_Pr must exist */
3042 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
3043 return -ENODEV;
3044
3045 retval = 0;
3046
3047 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
3048 sisusb->SiS_Pr->sisusb = (void *)sisusb;
3049
3050 if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
3051 retval = -EINVAL;
3052
3053 break;
3054 #endif
3055
3056 default:
3057 retval = -EINVAL;
3058 }
3059
3060 if (retval > 0)
3061 retval = -EIO;
3062
3063 return retval;
3064 }
3065
3066 static int
3067 sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
3068 unsigned long arg)
3069 {
3070 struct sisusb_usb_data *sisusb;
3071 struct sisusb_info x;
3072 struct sisusb_command y;
3073 int retval = 0;
3074 u32 __user *argp = (u32 __user *)arg;
3075
3076 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
3077 return -ENODEV;
3078
3079 mutex_lock(&sisusb->lock);
3080
3081 /* Sanity check */
3082 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
3083 retval = -ENODEV;
3084 goto err_out;
3085 }
3086
3087 switch (cmd) {
3088
3089 case SISUSB_GET_CONFIG_SIZE:
3090
3091 if (put_user(sizeof(x), argp))
3092 retval = -EFAULT;
3093
3094 break;
3095
3096 case SISUSB_GET_CONFIG:
3097
3098 x.sisusb_id = SISUSB_ID;
3099 x.sisusb_version = SISUSB_VERSION;
3100 x.sisusb_revision = SISUSB_REVISION;
3101 x.sisusb_patchlevel = SISUSB_PATCHLEVEL;
3102 x.sisusb_gfxinit = sisusb->gfxinit;
3103 x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE;
3104 x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE;
3105 x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE;
3106 x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE;
3107 x.sisusb_vramsize = sisusb->vramsize;
3108 x.sisusb_minor = sisusb->minor;
3109 x.sisusb_fbdevactive= 0;
3110 #ifdef INCL_SISUSB_CON
3111 x.sisusb_conactive = sisusb->haveconsole ? 1 : 0;
3112 #else
3113 x.sisusb_conactive = 0;
3114 #endif
3115
3116 if (copy_to_user((void __user *)arg, &x, sizeof(x)))
3117 retval = -EFAULT;
3118
3119 break;
3120
3121 case SISUSB_COMMAND:
3122
3123 if (copy_from_user(&y, (void __user *)arg, sizeof(y)))
3124 retval = -EFAULT;
3125 else
3126 retval = sisusb_handle_command(sisusb, &y, arg);
3127
3128 break;
3129
3130 default:
3131 retval = -ENOTTY;
3132 break;
3133 }
3134
3135 err_out:
3136 mutex_unlock(&sisusb->lock);
3137 return retval;
3138 }
3139
3140 #ifdef SISUSB_NEW_CONFIG_COMPAT
3141 static long
3142 sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
3143 {
3144 long retval;
3145
3146 switch (cmd) {
3147 case SISUSB_GET_CONFIG_SIZE:
3148 case SISUSB_GET_CONFIG:
3149 case SISUSB_COMMAND:
3150 lock_kernel();
3151 retval = sisusb_ioctl(f->f_path.dentry->d_inode, f, cmd, arg);
3152 unlock_kernel();
3153 return retval;
3154
3155 default:
3156 return -ENOIOCTLCMD;
3157 }
3158 }
3159 #endif
3160
3161 static const struct file_operations usb_sisusb_fops = {
3162 .owner = THIS_MODULE,
3163 .open = sisusb_open,
3164 .release = sisusb_release,
3165 .read = sisusb_read,
3166 .write = sisusb_write,
3167 .llseek = sisusb_lseek,
3168 #ifdef SISUSB_NEW_CONFIG_COMPAT
3169 .compat_ioctl = sisusb_compat_ioctl,
3170 #endif
3171 .ioctl = sisusb_ioctl
3172 };
3173
3174 static struct usb_class_driver usb_sisusb_class = {
3175 .name = "sisusbvga%d",
3176 .fops = &usb_sisusb_fops,
3177 .minor_base = SISUSB_MINOR
3178 };
3179
3180 static int sisusb_probe(struct usb_interface *intf,
3181 const struct usb_device_id *id)
3182 {
3183 struct usb_device *dev = interface_to_usbdev(intf);
3184 struct sisusb_usb_data *sisusb;
3185 int retval = 0, i;
3186 const char *memfail =
3187 KERN_ERR
3188 "sisusbvga[%d]: Failed to allocate memory for %s buffer\n";
3189
3190 printk(KERN_INFO "sisusb: USB2VGA dongle found at address %d\n",
3191 dev->devnum);
3192
3193 /* Allocate memory for our private */
3194 if (!(sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL))) {
3195 printk(KERN_ERR
3196 "sisusb: Failed to allocate memory for private data\n");
3197 return -ENOMEM;
3198 }
3199 kref_init(&sisusb->kref);
3200
3201 mutex_init(&(sisusb->lock));
3202
3203 /* Register device */
3204 if ((retval = usb_register_dev(intf, &usb_sisusb_class))) {
3205 printk(KERN_ERR
3206 "sisusb: Failed to get a minor for device %d\n",
3207 dev->devnum);
3208 retval = -ENODEV;
3209 goto error_1;
3210 }
3211
3212 sisusb->sisusb_dev = dev;
3213 sisusb->minor = intf->minor;
3214 sisusb->vrambase = SISUSB_PCI_MEMBASE;
3215 sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
3216 sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
3217 sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
3218 /* Everything else is zero */
3219
3220 /* Allocate buffers */
3221 sisusb->ibufsize = SISUSB_IBUF_SIZE;
3222 if (!(sisusb->ibuf = usb_buffer_alloc(dev, SISUSB_IBUF_SIZE,
3223 GFP_KERNEL, &sisusb->transfer_dma_in))) {
3224 printk(memfail, "input", sisusb->minor);
3225 retval = -ENOMEM;
3226 goto error_2;
3227 }
3228
3229 sisusb->numobufs = 0;
3230 sisusb->obufsize = SISUSB_OBUF_SIZE;
3231 for (i = 0; i < NUMOBUFS; i++) {
3232 if (!(sisusb->obuf[i] = usb_buffer_alloc(dev, SISUSB_OBUF_SIZE,
3233 GFP_KERNEL,
3234 &sisusb->transfer_dma_out[i]))) {
3235 if (i == 0) {
3236 printk(memfail, "output", sisusb->minor);
3237 retval = -ENOMEM;
3238 goto error_3;
3239 }
3240 break;
3241 } else
3242 sisusb->numobufs++;
3243
3244 }
3245
3246 /* Allocate URBs */
3247 if (!(sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL))) {
3248 printk(KERN_ERR
3249 "sisusbvga[%d]: Failed to allocate URBs\n",
3250 sisusb->minor);
3251 retval = -ENOMEM;
3252 goto error_3;
3253 }
3254 sisusb->completein = 1;
3255
3256 for (i = 0; i < sisusb->numobufs; i++) {
3257 if (!(sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL))) {
3258 printk(KERN_ERR
3259 "sisusbvga[%d]: Failed to allocate URBs\n",
3260 sisusb->minor);
3261 retval = -ENOMEM;
3262 goto error_4;
3263 }
3264 sisusb->urbout_context[i].sisusb = (void *)sisusb;
3265 sisusb->urbout_context[i].urbindex = i;
3266 sisusb->urbstatus[i] = 0;
3267 }
3268
3269 printk(KERN_INFO "sisusbvga[%d]: Allocated %d output buffers\n",
3270 sisusb->minor, sisusb->numobufs);
3271
3272 #ifdef INCL_SISUSB_CON
3273 /* Allocate our SiS_Pr */
3274 if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) {
3275 printk(KERN_ERR
3276 "sisusbvga[%d]: Failed to allocate SiS_Pr\n",
3277 sisusb->minor);
3278 }
3279 #endif
3280
3281 /* Do remaining init stuff */
3282
3283 init_waitqueue_head(&sisusb->wait_q);
3284
3285 usb_set_intfdata(intf, sisusb);
3286
3287 usb_get_dev(sisusb->sisusb_dev);
3288
3289 sisusb->present = 1;
3290
3291 #ifdef SISUSB_OLD_CONFIG_COMPAT
3292 {
3293 int ret;
3294 /* Our ioctls are all "32/64bit compatible" */
3295 ret = register_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE, NULL);
3296 ret |= register_ioctl32_conversion(SISUSB_GET_CONFIG, NULL);
3297 ret |= register_ioctl32_conversion(SISUSB_COMMAND, NULL);
3298 if (ret)
3299 printk(KERN_ERR
3300 "sisusbvga[%d]: Error registering ioctl32 "
3301 "translations\n",
3302 sisusb->minor);
3303 else
3304 sisusb->ioctl32registered = 1;
3305 }
3306 #endif
3307
3308 if (dev->speed == USB_SPEED_HIGH) {
3309 int initscreen = 1;
3310 #ifdef INCL_SISUSB_CON
3311 if (sisusb_first_vc > 0 &&
3312 sisusb_last_vc > 0 &&
3313 sisusb_first_vc <= sisusb_last_vc &&
3314 sisusb_last_vc <= MAX_NR_CONSOLES)
3315 initscreen = 0;
3316 #endif
3317 if (sisusb_init_gfxdevice(sisusb, initscreen))
3318 printk(KERN_ERR
3319 "sisusbvga[%d]: Failed to early "
3320 "initialize device\n",
3321 sisusb->minor);
3322
3323 } else
3324 printk(KERN_INFO
3325 "sisusbvga[%d]: Not attached to USB 2.0 hub, "
3326 "deferring init\n",
3327 sisusb->minor);
3328
3329 sisusb->ready = 1;
3330
3331 #ifdef SISUSBENDIANTEST
3332 printk(KERN_DEBUG "sisusb: *** RWTEST ***\n");
3333 sisusb_testreadwrite(sisusb);
3334 printk(KERN_DEBUG "sisusb: *** RWTEST END ***\n");
3335 #endif
3336
3337 #ifdef INCL_SISUSB_CON
3338 sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
3339 #endif
3340
3341 return 0;
3342
3343 error_4:
3344 sisusb_free_urbs(sisusb);
3345 error_3:
3346 sisusb_free_buffers(sisusb);
3347 error_2:
3348 usb_deregister_dev(intf, &usb_sisusb_class);
3349 error_1:
3350 kfree(sisusb);
3351 return retval;
3352 }
3353
3354 static void sisusb_disconnect(struct usb_interface *intf)
3355 {
3356 struct sisusb_usb_data *sisusb;
3357 int minor;
3358
3359 /* This should *not* happen */
3360 if (!(sisusb = usb_get_intfdata(intf)))
3361 return;
3362
3363 #ifdef INCL_SISUSB_CON
3364 sisusb_console_exit(sisusb);
3365 #endif
3366
3367 minor = sisusb->minor;
3368
3369 usb_deregister_dev(intf, &usb_sisusb_class);
3370
3371 mutex_lock(&sisusb->lock);
3372
3373 /* Wait for all URBs to complete and kill them in case (MUST do) */
3374 if (!sisusb_wait_all_out_complete(sisusb))
3375 sisusb_kill_all_busy(sisusb);
3376
3377 usb_set_intfdata(intf, NULL);
3378
3379 #ifdef SISUSB_OLD_CONFIG_COMPAT
3380 if (sisusb->ioctl32registered) {
3381 int ret;
3382 sisusb->ioctl32registered = 0;
3383 ret = unregister_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE);
3384 ret |= unregister_ioctl32_conversion(SISUSB_GET_CONFIG);
3385 ret |= unregister_ioctl32_conversion(SISUSB_COMMAND);
3386 if (ret) {
3387 printk(KERN_ERR
3388 "sisusbvga[%d]: Error unregistering "
3389 "ioctl32 translations\n",
3390 minor);
3391 }
3392 }
3393 #endif
3394
3395 sisusb->present = 0;
3396 sisusb->ready = 0;
3397
3398 mutex_unlock(&sisusb->lock);
3399
3400 /* decrement our usage count */
3401 kref_put(&sisusb->kref, sisusb_delete);
3402
3403 printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor);
3404 }
3405
3406 static struct usb_device_id sisusb_table [] = {
3407 { USB_DEVICE(0x0711, 0x0550) },
3408 { USB_DEVICE(0x0711, 0x0900) },
3409 { USB_DEVICE(0x0711, 0x0901) },
3410 { USB_DEVICE(0x0711, 0x0902) },
3411 { USB_DEVICE(0x182d, 0x021c) },
3412 { USB_DEVICE(0x182d, 0x0269) },
3413 { }
3414 };
3415
3416 MODULE_DEVICE_TABLE (usb, sisusb_table);
3417
3418 static struct usb_driver sisusb_driver = {
3419 .name = "sisusb",
3420 .probe = sisusb_probe,
3421 .disconnect = sisusb_disconnect,
3422 .id_table = sisusb_table,
3423 };
3424
3425 static int __init usb_sisusb_init(void)
3426 {
3427 int retval;
3428
3429 #ifdef INCL_SISUSB_CON
3430 sisusb_init_concode();
3431 #endif
3432
3433 if (!(retval = usb_register(&sisusb_driver))) {
3434
3435 printk(KERN_INFO "sisusb: Driver version %d.%d.%d\n",
3436 SISUSB_VERSION, SISUSB_REVISION, SISUSB_PATCHLEVEL);
3437 printk(KERN_INFO
3438 "sisusb: Copyright (C) 2005 Thomas Winischhofer\n");
3439
3440 }
3441
3442 return retval;
3443 }
3444
3445 static void __exit usb_sisusb_exit(void)
3446 {
3447 usb_deregister(&sisusb_driver);
3448 }
3449
3450 module_init(usb_sisusb_init);
3451 module_exit(usb_sisusb_exit);
3452
3453 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3454 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3455 MODULE_LICENSE("GPL");
3456