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