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