1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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
63
64#ifdef INCL_SISUSB_CON
65static int sisusb_first_vc = 0;
66static int sisusb_last_vc = 0;
67module_param_named(first, sisusb_first_vc, int, 0);
68module_param_named(last, sisusb_last_vc, int, 0);
69MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
70MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
71#endif
72
73static struct usb_driver sisusb_driver;
74
75static void
76sisusb_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
94static void
95sisusb_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
108
109
110
111
112
113
114static int
115sisusb_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
130static void
131sisusb_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
147static int
148sisusb_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
159static int
160sisusb_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
174static int
175sisusb_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
186static int
187sisusb_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
199static void
200sisusb_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
207
208static void
209sisusb_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
231static int
232sisusb_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
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
252 sisusb->urbout_context[index].actual_length = (timeout) ?
253 NULL : actual_length;
254
255
256 sisusb->urbstatus[index] |= SU_URB_BUSY;
257
258
259 retval = usb_submit_urb(urb, GFP_ATOMIC);
260
261
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
268 usb_kill_urb(urb);
269 retval = -ETIMEDOUT;
270 } else {
271
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
284
285
286
287static void
288sisusb_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
299static int
300sisusb_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
323 usb_kill_urb(urb);
324 retval = -ETIMEDOUT;
325 } else {
326
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
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354static 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
368 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
369 return -ENODEV;
370
371
372
373
374
375
376
377
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
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
442
443
444 memcpy(buffer,
445 buffer + transferred_len,
446 thispass);
447 } else {
448
449
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
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
475#else
476 sisusb_wait_all_out_complete(sisusb);
477 (*bytes_written) = transferred_len;
478
479#endif
480 }
481
482 return ((*bytes_written) == len) ? 0 : -EIO;
483}
484
485
486
487
488
489
490
491
492
493
494static 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
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
576static 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
592 SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
593
594
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
601
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
612static 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
629 SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
630
631
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
638
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
650
651
652
653
654
655
656
657
658
659
660
661static 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
674static 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
711static 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
752static 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
798
799
800
801
802
803
804
805
806
807static 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
821
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
1024
1025
1026
1027static 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
1041static 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
1080static 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
1121static 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
1166static 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
1268
1269#ifdef INCL_SISUSB_CON
1270int
1271sisusb_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
1276int
1277sisusb_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
1283int
1284sisusb_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
1292int
1293sisusb_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
1301int
1302sisusb_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
1316static int
1317sisusb_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
1330int
1331sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor)
1332{
1333 return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));
1334}
1335
1336int
1337sisusb_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
1343
1344#ifdef INCL_SISUSB_CON
1345int
1346sisusb_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
1351int
1352sisusb_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
1357int
1358sisusb_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
1365int
1366sisusb_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
1375static void
1376sisusb_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
1396
1397static int
1398sisusb_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
1410static int
1411sisusb_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
1424
1425static int
1426sisusb_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
1444 if ((i = sisusb_alloc_outbuf(sisusb)) < 0)
1445 return -EBUSY;
1446
1447 memset(sisusb->obuf[i], 0, sisusb->obufsize);
1448
1449
1450
1451
1452 ret = sisusb_write_mem_bulk(sisusb, address, NULL, length, NULL, i, &j);
1453
1454
1455 sisusb_free_outbuf(sisusb, i);
1456
1457 return ret;
1458}
1459
1460
1461
1462
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
1477static int
1478sisusb_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
1508static int
1509sisusb_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;
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 }
1610 } else {
1611 if (t0 == 0x01234567) {
1612 *chab = 1; *bw = 32;
1613 ret |= SETIREG(SISSR, 0x14, 0x01);
1614 }
1615 }
1616 }
1617 }
1618 return ret;
1619}
1620
1621static int
1622sisusb_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);
1637 ret |= SETIREGAND(SISSR, 0x3c, 0xfe);
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
1650static int
1651sisusb_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);
1676
1677 *iret = 1;
1678
1679 return ret;
1680}
1681
1682static int
1683sisusb_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
1705static int
1706sisusb_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
1738static int
1739sisusb_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;
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;
1773 return ret;
1774 }
1775 }
1776 }
1777
1778 return ret;
1779}
1780
1781static int
1782sisusb_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;
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
1821static int
1822sisusb_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);
1857 SETIREG(SISSR, 0x01, 0x21);
1858 SETIREG(SISSR, 0x02, 0x0f);
1859 SETIREG(SISSR, 0x03, 0x00);
1860 SETIREG(SISSR, 0x04, 0x0e);
1861 SETREG(SISMISCW, 0x23);
1862 for (i = 0; i <= 0x18; i++) {
1863 SETIREG(SISCR, i, crtcrdata[i]);
1864 }
1865 for (i = 0; i <= 0x13; i++) {
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++) {
1877 SETIREG(SISGR, i, grcdata[i]);
1878 }
1879 SETIREGAND(SISGR, 0x05, 0xbf);
1880 for (i = 0x0A; i <= 0x0E; i++) {
1881 SETIREG(SISSR, i, 0x00);
1882 }
1883 SETIREGAND(SISSR, 0x37, 0xfe);
1884 SETREG(SISMISCW, 0xef);
1885 SETIREG(SISCR, 0x11, 0x00);
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);
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);
1910 SETIREG(SISSR, 0x2b, 0x1b);
1911 SETIREG(SISSR, 0x2c, 0xe1);
1912 SETIREG(SISSR, 0x2d, 0x01);
1913 SETIREGAND(SISSR, 0x3d, 0xfe);
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);
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);
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);
1936 SETIREG(SISCR, 0x63, (cr63 & 0xbf));
1937 SETIREG(SISSR, 0x31, (sr31 & 0xfb));
1938
1939 if (touchengines) {
1940 SETIREG(SISSR, 0x20, 0xa1);
1941 SETIREGOR(SISSR, 0x1e, 0x5a);
1942
1943 SETIREG(SISSR, 0x26, 0x01);
1944 SETIREG(SISSR, 0x27, 0x1f);
1945 SETIREG(SISSR, 0x26, 0x00);
1946 }
1947
1948 SETIREG(SISCR, 0x34, 0x44);
1949
1950 return ret;
1951}
1952
1953static int
1954sisusb_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
1991 ret = GETREG(SISVGAEN, &tmp8);
1992 ret |= SETREG(SISVGAEN, (tmp8 | 0x01));
1993
1994
1995 ret |= GETREG(SISMISCR, &tmp8);
1996 ret |= SETREG(SISMISCW, (tmp8 | 0x01));
1997
1998 if (ret) continue;
1999
2000
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
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
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
2116 }
2117
2118
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
2145static void
2146sisusb_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
2188static int
2189sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb)
2190{
2191 struct sisusb_packet packet;
2192 int ret;
2193 u32 tmp32;
2194
2195
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
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
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
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
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
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
2263
2264
2265
2266
2267static int
2268sisusb_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
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
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
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
2315
2316
2317
2318
2319
2320int
2321sisusb_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
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
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
2352 ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, 0, 1, NULL, 16, 0);
2353
2354 vfree(tempbuf);
2355
2356
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
2428
2429 return ret;
2430}
2431
2432#endif
2433
2434
2435
2436static int
2437sisusb_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
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
2487void
2488sisusb_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
2507static int
2508sisusb_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
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
2529 kref_put(&sisusb->kref, sisusb_delete);
2530
2531 return 0;
2532}
2533
2534static ssize_t
2535sisusb_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
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
2563
2564
2565
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
2618
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
2634
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
2653
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
2675static ssize_t
2676sisusb_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
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
2705
2706
2707
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
2759
2760
2761
2762
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
2778
2779
2780
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
2799
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
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
2823static loff_t
2824sisusb_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
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
2845 break;
2846 case 1:
2847 file->f_pos += offset;
2848 ret = file->f_pos;
2849
2850 break;
2851 default:
2852
2853 ret = -EINVAL;
2854 }
2855
2856 mutex_unlock(&sisusb->lock);
2857 return ret;
2858}
2859
2860static int
2861sisusb_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
2868
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
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
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
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
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
2985static int
2986sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
2987 unsigned long arg)
2988{
2989 struct sisusb_usb_data *sisusb;
2990 struct sisusb_info x;
2991 struct sisusb_command y;
2992 int retval = 0;
2993 u32 __user *argp = (u32 __user *)arg;
2994
2995 if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
2996 return -ENODEV;
2997
2998 mutex_lock(&sisusb->lock);
2999
3000
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
3054err_out:
3055 mutex_unlock(&sisusb->lock);
3056 return retval;
3057}
3058
3059#ifdef SISUSB_NEW_CONFIG_COMPAT
3060static long
3061sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
3062{
3063 long retval;
3064
3065 switch (cmd) {
3066 case SISUSB_GET_CONFIG_SIZE:
3067 case SISUSB_GET_CONFIG:
3068 case SISUSB_COMMAND:
3069 lock_kernel();
3070 retval = sisusb_ioctl(f->f_path.dentry->d_inode, f, cmd, arg);
3071 unlock_kernel();
3072 return retval;
3073
3074 default:
3075 return -ENOIOCTLCMD;
3076 }
3077}
3078#endif
3079
3080static const struct file_operations usb_sisusb_fops = {
3081 .owner = THIS_MODULE,
3082 .open = sisusb_open,
3083 .release = sisusb_release,
3084 .read = sisusb_read,
3085 .write = sisusb_write,
3086 .llseek = sisusb_lseek,
3087#ifdef SISUSB_NEW_CONFIG_COMPAT
3088 .compat_ioctl = sisusb_compat_ioctl,
3089#endif
3090 .ioctl = sisusb_ioctl
3091};
3092
3093static struct usb_class_driver usb_sisusb_class = {
3094 .name = "sisusbvga%d",
3095 .fops = &usb_sisusb_fops,
3096 .minor_base = SISUSB_MINOR
3097};
3098
3099static int sisusb_probe(struct usb_interface *intf,
3100 const struct usb_device_id *id)
3101{
3102 struct usb_device *dev = interface_to_usbdev(intf);
3103 struct sisusb_usb_data *sisusb;
3104 int retval = 0, i;
3105
3106 dev_info(&dev->dev, "USB2VGA dongle found at address %d\n",
3107 dev->devnum);
3108
3109
3110 if (!(sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL))) {
3111 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for private data\n");
3112 return -ENOMEM;
3113 }
3114 kref_init(&sisusb->kref);
3115
3116 mutex_init(&(sisusb->lock));
3117
3118
3119 if ((retval = usb_register_dev(intf, &usb_sisusb_class))) {
3120 dev_err(&sisusb->sisusb_dev->dev, "Failed to get a minor for device %d\n",
3121 dev->devnum);
3122 retval = -ENODEV;
3123 goto error_1;
3124 }
3125
3126 sisusb->sisusb_dev = dev;
3127 sisusb->minor = intf->minor;
3128 sisusb->vrambase = SISUSB_PCI_MEMBASE;
3129 sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
3130 sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
3131 sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
3132
3133
3134
3135 sisusb->ibufsize = SISUSB_IBUF_SIZE;
3136 if (!(sisusb->ibuf = usb_buffer_alloc(dev, SISUSB_IBUF_SIZE,
3137 GFP_KERNEL, &sisusb->transfer_dma_in))) {
3138 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for input buffer");
3139 retval = -ENOMEM;
3140 goto error_2;
3141 }
3142
3143 sisusb->numobufs = 0;
3144 sisusb->obufsize = SISUSB_OBUF_SIZE;
3145 for (i = 0; i < NUMOBUFS; i++) {
3146 if (!(sisusb->obuf[i] = usb_buffer_alloc(dev, SISUSB_OBUF_SIZE,
3147 GFP_KERNEL,
3148 &sisusb->transfer_dma_out[i]))) {
3149 if (i == 0) {
3150 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for output buffer\n");
3151 retval = -ENOMEM;
3152 goto error_3;
3153 }
3154 break;
3155 } else
3156 sisusb->numobufs++;
3157
3158 }
3159
3160
3161 if (!(sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL))) {
3162 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n");
3163 retval = -ENOMEM;
3164 goto error_3;
3165 }
3166 sisusb->completein = 1;
3167
3168 for (i = 0; i < sisusb->numobufs; i++) {
3169 if (!(sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL))) {
3170 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n");
3171 retval = -ENOMEM;
3172 goto error_4;
3173 }
3174 sisusb->urbout_context[i].sisusb = (void *)sisusb;
3175 sisusb->urbout_context[i].urbindex = i;
3176 sisusb->urbstatus[i] = 0;
3177 }
3178
3179 dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n", sisusb->numobufs);
3180
3181#ifdef INCL_SISUSB_CON
3182
3183 if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) {
3184 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate SiS_Pr\n");
3185 }
3186#endif
3187
3188
3189
3190 init_waitqueue_head(&sisusb->wait_q);
3191
3192 usb_set_intfdata(intf, sisusb);
3193
3194 usb_get_dev(sisusb->sisusb_dev);
3195
3196 sisusb->present = 1;
3197
3198#ifdef SISUSB_OLD_CONFIG_COMPAT
3199 {
3200 int ret;
3201
3202 ret = register_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE, NULL);
3203 ret |= register_ioctl32_conversion(SISUSB_GET_CONFIG, NULL);
3204 ret |= register_ioctl32_conversion(SISUSB_COMMAND, NULL);
3205 if (ret)
3206 dev_err(&sisusb->sisusb_dev->dev, "Error registering ioctl32 translations\n");
3207 else
3208 sisusb->ioctl32registered = 1;
3209 }
3210#endif
3211
3212 if (dev->speed == USB_SPEED_HIGH) {
3213 int initscreen = 1;
3214#ifdef INCL_SISUSB_CON
3215 if (sisusb_first_vc > 0 &&
3216 sisusb_last_vc > 0 &&
3217 sisusb_first_vc <= sisusb_last_vc &&
3218 sisusb_last_vc <= MAX_NR_CONSOLES)
3219 initscreen = 0;
3220#endif
3221 if (sisusb_init_gfxdevice(sisusb, initscreen))
3222 dev_err(&sisusb->sisusb_dev->dev, "Failed to early initialize device\n");
3223
3224 } else
3225 dev_info(&sisusb->sisusb_dev->dev, "Not attached to USB 2.0 hub, deferring init\n");
3226
3227 sisusb->ready = 1;
3228
3229#ifdef SISUSBENDIANTEST
3230 dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST ***\n");
3231 sisusb_testreadwrite(sisusb);
3232 dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST END ***\n");
3233#endif
3234
3235#ifdef INCL_SISUSB_CON
3236 sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
3237#endif
3238
3239 return 0;
3240
3241error_4:
3242 sisusb_free_urbs(sisusb);
3243error_3:
3244 sisusb_free_buffers(sisusb);
3245error_2:
3246 usb_deregister_dev(intf, &usb_sisusb_class);
3247error_1:
3248 kfree(sisusb);
3249 return retval;
3250}
3251
3252static void sisusb_disconnect(struct usb_interface *intf)
3253{
3254 struct sisusb_usb_data *sisusb;
3255
3256
3257 if (!(sisusb = usb_get_intfdata(intf)))
3258 return;
3259
3260#ifdef INCL_SISUSB_CON
3261 sisusb_console_exit(sisusb);
3262#endif
3263
3264 usb_deregister_dev(intf, &usb_sisusb_class);
3265
3266 mutex_lock(&sisusb->lock);
3267
3268
3269 if (!sisusb_wait_all_out_complete(sisusb))
3270 sisusb_kill_all_busy(sisusb);
3271
3272 usb_set_intfdata(intf, NULL);
3273
3274#ifdef SISUSB_OLD_CONFIG_COMPAT
3275 if (sisusb->ioctl32registered) {
3276 int ret;
3277 sisusb->ioctl32registered = 0;
3278 ret = unregister_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE);
3279 ret |= unregister_ioctl32_conversion(SISUSB_GET_CONFIG);
3280 ret |= unregister_ioctl32_conversion(SISUSB_COMMAND);
3281 if (ret) {
3282 dev_err(&sisusb->sisusb_dev->dev, "Error unregistering ioctl32 translations\n");
3283 }
3284 }
3285#endif
3286
3287 sisusb->present = 0;
3288 sisusb->ready = 0;
3289
3290 mutex_unlock(&sisusb->lock);
3291
3292
3293 kref_put(&sisusb->kref, sisusb_delete);
3294
3295 dev_info(&sisusb->sisusb_dev->dev, "Disconnected\n");
3296}
3297
3298static struct usb_device_id sisusb_table [] = {
3299 { USB_DEVICE(0x0711, 0x0550) },
3300 { USB_DEVICE(0x0711, 0x0900) },
3301 { USB_DEVICE(0x0711, 0x0901) },
3302 { USB_DEVICE(0x0711, 0x0902) },
3303 { USB_DEVICE(0x182d, 0x021c) },
3304 { USB_DEVICE(0x182d, 0x0269) },
3305 { }
3306};
3307
3308MODULE_DEVICE_TABLE (usb, sisusb_table);
3309
3310static struct usb_driver sisusb_driver = {
3311 .name = "sisusb",
3312 .probe = sisusb_probe,
3313 .disconnect = sisusb_disconnect,
3314 .id_table = sisusb_table,
3315};
3316
3317static int __init usb_sisusb_init(void)
3318{
3319
3320#ifdef INCL_SISUSB_CON
3321 sisusb_init_concode();
3322#endif
3323
3324 return usb_register(&sisusb_driver);
3325}
3326
3327static void __exit usb_sisusb_exit(void)
3328{
3329 usb_deregister(&sisusb_driver);
3330}
3331
3332module_init(usb_sisusb_init);
3333module_exit(usb_sisusb_exit);
3334
3335MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3336MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3337MODULE_LICENSE("GPL");
3338
3339