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