Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / usb / misc / sisusbvga / sisusb.c
1 /*
2  * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
3  *
4  * Main part
5  *
6  * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
7  *
8  * If distributed as part of the Linux kernel, this code is licensed under the
9  * terms of the GPL v2.
10  *
11  * Otherwise, the following license terms apply:
12  *
13  * * Redistribution and use in source and binary forms, with or without
14  * * modification, are permitted provided that the following conditions
15  * * are met:
16  * * 1) Redistributions of source code must retain the above copyright
17  * *    notice, this list of conditions and the following disclaimer.
18  * * 2) Redistributions in binary form must reproduce the above copyright
19  * *    notice, this list of conditions and the following disclaimer in the
20  * *    documentation and/or other materials provided with the distribution.
21  * * 3) The name of the author may not be used to endorse or promote products
22  * *    derived from this software without specific psisusbr written permission.
23  * *
24  * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
25  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29  * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33  * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  *
35  * Author:      Thomas Winischhofer <thomas@winischhofer.net>
36  *
37  */
38
39 #include <linux/config.h>
40 #include <linux/module.h>
41 #include <linux/kernel.h>
42 #include <linux/signal.h>
43 #include <linux/sched.h>
44 #include <linux/errno.h>
45 #include <linux/poll.h>
46 #include <linux/init.h>
47 #include <linux/slab.h>
48 #include <linux/spinlock.h>
49 #include <linux/kref.h>
50 #include <linux/usb.h>
51 #include <linux/smp_lock.h>
52 #include <linux/vmalloc.h>
53
54 #include "sisusb.h"
55
56 #ifdef INCL_SISUSB_CON
57 #include <linux/font.h>
58 #endif
59
60 #define SISUSB_DONTSYNC
61
62 /* Forward declarations / clean-up routines */
63
64 #ifdef INCL_SISUSB_CON
65 int     sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data);
66 int     sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data);
67 int     sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data);
68 int     sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data);
69 int     sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand, u8 myor);
70 int     sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor);
71 int     sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand);
72
73 int     sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);
74 int     sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data);
75 int     sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data);
76 int     sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data);
77 int     sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
78                         u32 dest, int length, size_t *bytes_written);
79
80 int     sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);
81
82 extern int  SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
83 extern int  SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
84
85 extern void sisusb_init_concode(void);
86 extern int  sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last);
87 extern void sisusb_console_exit(struct sisusb_usb_data *sisusb);
88
89 extern void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location);
90
91 extern int  sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
92                 u8 *arg, int cmapsz, int ch512, int dorecalc,
93                 struct vc_data *c, int fh, int uplock);
94
95 static int sisusb_first_vc = 0;
96 static int sisusb_last_vc = 0;
97 module_param_named(first, sisusb_first_vc, int, 0);
98 module_param_named(last, sisusb_last_vc, int, 0);
99 MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
100 MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
101 #endif
102
103 static struct usb_driver sisusb_driver;
104
105 DECLARE_MUTEX(disconnect_sem);
106
107 static void
108 sisusb_free_buffers(struct sisusb_usb_data *sisusb)
109 {
110         int i;
111
112         for (i = 0; i < NUMOBUFS; i++) {
113                 if (sisusb->obuf[i]) {
114                         usb_buffer_free(sisusb->sisusb_dev, sisusb->obufsize,
115                                 sisusb->obuf[i], sisusb->transfer_dma_out[i]);
116                         sisusb->obuf[i] = NULL;
117                 }
118         }
119         if (sisusb->ibuf) {
120                 usb_buffer_free(sisusb->sisusb_dev, sisusb->ibufsize,
121                         sisusb->ibuf, sisusb->transfer_dma_in);
122                 sisusb->ibuf = NULL;
123         }
124 }
125
126 static void
127 sisusb_free_urbs(struct sisusb_usb_data *sisusb)
128 {
129         int i;
130
131         for (i = 0; i < NUMOBUFS; i++) {
132                 usb_free_urb(sisusb->sisurbout[i]);
133                 sisusb->sisurbout[i] = NULL;
134         }
135         usb_free_urb(sisusb->sisurbin);
136         sisusb->sisurbin = NULL;
137 }
138
139 /* Level 0: USB transport layer */
140
141 /* 1. out-bulks */
142
143 /* out-urb management */
144
145 /* Return 1 if all free, 0 otherwise */
146 static int
147 sisusb_all_free(struct sisusb_usb_data *sisusb)
148 {
149         int i;
150
151         for (i = 0; i < sisusb->numobufs; i++) {
152
153                 if (sisusb->urbstatus[i] & SU_URB_BUSY)
154                         return 0;
155
156         }
157
158         return 1;
159 }
160
161 /* Kill all busy URBs */
162 static void
163 sisusb_kill_all_busy(struct sisusb_usb_data *sisusb)
164 {
165         int i;
166
167         if (sisusb_all_free(sisusb))
168                 return;
169
170         for (i = 0; i < sisusb->numobufs; i++) {
171
172                 if (sisusb->urbstatus[i] & SU_URB_BUSY)
173                         usb_kill_urb(sisusb->sisurbout[i]);
174
175         }
176 }
177
178 /* Return 1 if ok, 0 if error (not all complete within timeout) */
179 static int
180 sisusb_wait_all_out_complete(struct sisusb_usb_data *sisusb)
181 {
182         int timeout = 5 * HZ, i = 1;
183
184         wait_event_timeout(sisusb->wait_q,
185                                 (i = sisusb_all_free(sisusb)),
186                                  timeout);
187
188         return i;
189 }
190
191 static int
192 sisusb_outurb_available(struct sisusb_usb_data *sisusb)
193 {
194         int i;
195
196         for (i = 0; i < sisusb->numobufs; i++) {
197
198                 if ((sisusb->urbstatus[i] & (SU_URB_BUSY|SU_URB_ALLOC)) == 0)
199                         return i;
200
201         }
202
203         return -1;
204 }
205
206 static int
207 sisusb_get_free_outbuf(struct sisusb_usb_data *sisusb)
208 {
209         int i, timeout = 5 * HZ;
210
211         wait_event_timeout(sisusb->wait_q,
212                                 ((i = sisusb_outurb_available(sisusb)) >= 0),
213                                 timeout);
214
215         return i;
216 }
217
218 static int
219 sisusb_alloc_outbuf(struct sisusb_usb_data *sisusb)
220 {
221         int i;
222
223         i = sisusb_outurb_available(sisusb);
224
225         if (i >= 0)
226                 sisusb->urbstatus[i] |= SU_URB_ALLOC;
227
228         return i;
229 }
230
231 static void
232 sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index)
233 {
234         if ((index >= 0) && (index < sisusb->numobufs))
235                 sisusb->urbstatus[index] &= ~SU_URB_ALLOC;
236 }
237
238 /* completion callback */
239
240 static void
241 sisusb_bulk_completeout(struct urb *urb, struct pt_regs *regs)
242 {
243         struct sisusb_urb_context *context = urb->context;
244         struct sisusb_usb_data *sisusb;
245
246         if (!context)
247                 return;
248
249         sisusb = context->sisusb;
250
251         if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
252                 return;
253
254 #ifndef SISUSB_DONTSYNC
255         if (context->actual_length)
256                 *(context->actual_length) += urb->actual_length;
257 #endif
258
259         sisusb->urbstatus[context->urbindex] &= ~SU_URB_BUSY;
260         wake_up(&sisusb->wait_q);
261 }
262
263 static int
264 sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe, void *data,
265                 int len, int *actual_length, int timeout, unsigned int tflags,
266                 dma_addr_t transfer_dma)
267 {
268         struct urb *urb = sisusb->sisurbout[index];
269         int retval, byteswritten = 0;
270
271         /* Set up URB */
272         urb->transfer_flags = 0;
273
274         usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
275                 sisusb_bulk_completeout, &sisusb->urbout_context[index]);
276
277         urb->transfer_flags |= tflags;
278         urb->actual_length = 0;
279
280         if ((urb->transfer_dma = transfer_dma))
281                 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
282
283         /* Set up context */
284         sisusb->urbout_context[index].actual_length = (timeout) ?
285                                                 NULL : actual_length;
286
287         /* Declare this urb/buffer in use */
288         sisusb->urbstatus[index] |= SU_URB_BUSY;
289
290         /* Submit URB */
291         retval = usb_submit_urb(urb, GFP_ATOMIC);
292
293         /* If OK, and if timeout > 0, wait for completion */
294         if ((retval == 0) && timeout) {
295                 wait_event_timeout(sisusb->wait_q,
296                                    (!(sisusb->urbstatus[index] & SU_URB_BUSY)),
297                                    timeout);
298                 if (sisusb->urbstatus[index] & SU_URB_BUSY) {
299                         /* URB timed out... kill it and report error */
300                         usb_kill_urb(urb);
301                         retval = -ETIMEDOUT;
302                 } else {
303                         /* Otherwise, report urb status */
304                         retval = urb->status;
305                         byteswritten = urb->actual_length;
306                 }
307         }
308
309         if (actual_length)
310                 *actual_length = byteswritten;
311
312         return retval;
313 }
314
315 /* 2. in-bulks */
316
317 /* completion callback */
318
319 static void
320 sisusb_bulk_completein(struct urb *urb, struct pt_regs *regs)
321 {
322         struct sisusb_usb_data *sisusb = urb->context;
323
324         if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
325                 return;
326
327         sisusb->completein = 1;
328         wake_up(&sisusb->wait_q);
329 }
330
331 static int
332 sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data, int len,
333                 int *actual_length, int timeout, unsigned int tflags, dma_addr_t transfer_dma)
334 {
335         struct urb *urb = sisusb->sisurbin;
336         int retval, readbytes = 0;
337
338         urb->transfer_flags = 0;
339
340         usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
341                         sisusb_bulk_completein, sisusb);
342
343         urb->transfer_flags |= tflags;
344         urb->actual_length = 0;
345
346         if ((urb->transfer_dma = transfer_dma))
347                 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
348
349         sisusb->completein = 0;
350         retval = usb_submit_urb(urb, GFP_ATOMIC);
351         if (retval == 0) {
352                 wait_event_timeout(sisusb->wait_q, sisusb->completein, timeout);
353                 if (!sisusb->completein) {
354                         /* URB timed out... kill it and report error */
355                         usb_kill_urb(urb);
356                         retval = -ETIMEDOUT;
357                 } else {
358                         /* URB completed within timout */
359                         retval = urb->status;
360                         readbytes = urb->actual_length;
361                 }
362         }
363
364         if (actual_length)
365                 *actual_length = readbytes;
366
367         return retval;
368 }
369
370
371 /* Level 1:  */
372
373 /* Send a bulk message of variable size
374  *
375  * To copy the data from userspace, give pointer to "userbuffer",
376  * to copy from (non-DMA) kernel memory, give "kernbuffer". If
377  * both of these are NULL, it is assumed, that the transfer
378  * buffer "sisusb->obuf[index]" is set up with the data to send.
379  * Index is ignored if either kernbuffer or userbuffer is set.
380  * If async is nonzero, URBs will be sent without waiting for
381  * completion of the previous URB.
382  *
383  * (return 0 on success)
384  */
385
386 static int sisusb_send_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
387                 char *kernbuffer, const char __user *userbuffer, int index,
388                 ssize_t *bytes_written, unsigned int tflags, int async)
389 {
390         int result = 0, retry, count = len;
391         int passsize, thispass, transferred_len = 0;
392         int fromuser = (userbuffer != NULL) ? 1 : 0;
393         int fromkern = (kernbuffer != NULL) ? 1 : 0;
394         unsigned int pipe;
395         char *buffer;
396
397         (*bytes_written) = 0;
398
399         /* Sanity check */
400         if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
401                 return -ENODEV;
402
403         /* If we copy data from kernel or userspace, force the
404          * allocation of a buffer/urb. If we have the data in
405          * the transfer buffer[index] already, reuse the buffer/URB
406          * if the length is > buffer size. (So, transmitting
407          * large data amounts directly from the transfer buffer
408          * treats the buffer as a ring buffer. However, we need
409          * to sync in this case.)
410          */
411         if (fromuser || fromkern)
412                 index = -1;
413         else if (len > sisusb->obufsize)
414                 async = 0;
415
416         pipe = usb_sndbulkpipe(sisusb->sisusb_dev, ep);
417
418         do {
419                 passsize = thispass = (sisusb->obufsize < count) ?
420                                                 sisusb->obufsize : count;
421
422                 if (index < 0)
423                         index = sisusb_get_free_outbuf(sisusb);
424
425                 if (index < 0)
426                         return -EIO;
427
428                 buffer = sisusb->obuf[index];
429
430                 if (fromuser) {
431
432                         if (copy_from_user(buffer, userbuffer, passsize))
433                                 return -EFAULT;
434
435                         userbuffer += passsize;
436
437                 } else if (fromkern) {
438
439                         memcpy(buffer, kernbuffer, passsize);
440                         kernbuffer += passsize;
441
442                 }
443
444                 retry = 5;
445                 while (thispass) {
446
447                         if (!sisusb->sisusb_dev)
448                                 return -ENODEV;
449
450                         result = sisusb_bulkout_msg(sisusb,
451                                                 index,
452                                                 pipe,
453                                                 buffer,
454                                                 thispass,
455                                                 &transferred_len,
456                                                 async ? 0 : 5 * HZ,
457                                                 tflags,
458                                                 sisusb->transfer_dma_out[index]);
459
460                         if (result == -ETIMEDOUT) {
461
462                                 /* Will not happen if async */
463                                 if (!retry--)
464                                         return -ETIME;
465
466                                 continue;
467
468                         } else if ((result == 0) && !async && transferred_len) {
469
470                                 thispass -= transferred_len;
471                                 if (thispass) {
472                                         if (sisusb->transfer_dma_out) {
473                                                 /* If DMA, copy remaining
474                                                  * to beginning of buffer
475                                                  */
476                                                 memcpy(buffer,
477                                                        buffer + transferred_len,
478                                                        thispass);
479                                         } else {
480                                                 /* If not DMA, simply increase
481                                                  * the pointer
482                                                  */
483                                                 buffer += transferred_len;
484                                         }
485                                 }
486
487                         } else
488                                 break;
489                 };
490
491                 if (result)
492                         return result;
493
494                 (*bytes_written) += passsize;
495                 count            -= passsize;
496
497                 /* Force new allocation in next iteration */
498                 if (fromuser || fromkern)
499                         index = -1;
500
501         } while (count > 0);
502
503         if (async) {
504 #ifdef SISUSB_DONTSYNC
505                 (*bytes_written) = len;
506                 /* Some URBs/buffers might be busy */
507 #else
508                 sisusb_wait_all_out_complete(sisusb);
509                 (*bytes_written) = transferred_len;
510                 /* All URBs and all buffers are available */
511 #endif
512         }
513
514         return ((*bytes_written) == len) ? 0 : -EIO;
515 }
516
517 /* Receive a bulk message of variable size
518  *
519  * To copy the data to userspace, give pointer to "userbuffer",
520  * to copy to kernel memory, give "kernbuffer". One of them
521  * MUST be set. (There is no technique for letting the caller
522  * read directly from the ibuf.)
523  *
524  */
525
526 static int sisusb_recv_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
527                 void *kernbuffer, char __user *userbuffer, ssize_t *bytes_read,
528                 unsigned int tflags)
529 {
530         int result = 0, retry, count = len;
531         int bufsize, thispass, transferred_len;
532         unsigned int pipe;
533         char *buffer;
534
535         (*bytes_read) = 0;
536
537         /* Sanity check */
538         if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
539                 return -ENODEV;
540
541         pipe = usb_rcvbulkpipe(sisusb->sisusb_dev, ep);
542         buffer = sisusb->ibuf;
543         bufsize = sisusb->ibufsize;
544
545         retry = 5;
546
547 #ifdef SISUSB_DONTSYNC
548         if (!(sisusb_wait_all_out_complete(sisusb)))
549                 return -EIO;
550 #endif
551
552         while (count > 0) {
553
554                 if (!sisusb->sisusb_dev)
555                         return -ENODEV;
556
557                 thispass = (bufsize < count) ? bufsize : count;
558
559                 result = sisusb_bulkin_msg(sisusb,
560                                            pipe,
561                                            buffer,
562                                            thispass,
563                                            &transferred_len,
564                                            5 * HZ,
565                                            tflags,
566                                            sisusb->transfer_dma_in);
567
568                 if (transferred_len)
569                         thispass = transferred_len;
570
571                 else if (result == -ETIMEDOUT) {
572
573                         if (!retry--)
574                                 return -ETIME;
575
576                         continue;
577
578                 } else
579                         return -EIO;
580
581
582                 if (thispass) {
583
584                         (*bytes_read) += thispass;
585                         count         -= thispass;
586
587                         if (userbuffer) {
588
589                                 if (copy_to_user(userbuffer, buffer, thispass))
590                                         return -EFAULT;
591
592                                 userbuffer += thispass;
593
594                         } else {
595
596                                 memcpy(kernbuffer, buffer, thispass);
597                                 kernbuffer += thispass;
598
599                         }
600
601                 }
602
603         }
604
605         return ((*bytes_read) == len) ? 0 : -EIO;
606 }
607
608 static int sisusb_send_packet(struct sisusb_usb_data *sisusb, int len,
609                                                 struct sisusb_packet *packet)
610 {
611         int ret;
612         ssize_t bytes_transferred = 0;
613         __le32 tmp;
614
615         if (len == 6)
616                 packet->data = 0;
617
618 #ifdef SISUSB_DONTSYNC
619         if (!(sisusb_wait_all_out_complete(sisusb)))
620                 return 1;
621 #endif
622
623         /* Eventually correct endianness */
624         SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
625
626         /* 1. send the packet */
627         ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_OUT, len,
628                         (char *)packet, NULL, 0, &bytes_transferred, 0, 0);
629
630         if ((ret == 0) && (len == 6)) {
631
632                 /* 2. if packet len == 6, it means we read, so wait for 32bit
633                  *    return value and write it to packet->data
634                  */
635                 ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_GFX_IN, 4,
636                                 (char *)&tmp, NULL, &bytes_transferred, 0);
637
638                 packet->data = le32_to_cpu(tmp);
639         }
640
641         return ret;
642 }
643
644 static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
645                                         struct sisusb_packet *packet,
646                                         unsigned int tflags)
647 {
648         int ret;
649         ssize_t bytes_transferred = 0;
650         __le32 tmp;
651
652         if (len == 6)
653                 packet->data = 0;
654
655 #ifdef SISUSB_DONTSYNC
656         if (!(sisusb_wait_all_out_complete(sisusb)))
657                 return 1;
658 #endif
659
660         /* Eventually correct endianness */
661         SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
662
663         /* 1. send the packet */
664         ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_BRIDGE_OUT, len,
665                         (char *)packet, NULL, 0, &bytes_transferred, tflags, 0);
666
667         if ((ret == 0) && (len == 6)) {
668
669                 /* 2. if packet len == 6, it means we read, so wait for 32bit
670                  *    return value and write it to packet->data
671                  */
672                 ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_BRIDGE_IN, 4,
673                                 (char *)&tmp, NULL, &bytes_transferred, 0);
674
675                 packet->data = le32_to_cpu(tmp);
676         }
677
678         return ret;
679 }
680
681 /* access video memory and mmio (return 0 on success) */
682
683 /* Low level */
684
685 /* The following routines assume being used to transfer byte, word,
686  * long etc.
687  * This means that
688  *   - the write routines expect "data" in machine endianness format.
689  *     The data will be converted to leXX in sisusb_xxx_packet.
690  *   - the read routines can expect read data in machine-endianess.
691  */
692
693 static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,
694                                                         u32 addr, u8 data)
695 {
696         struct sisusb_packet packet;
697         int ret;
698
699         packet.header  = (1 << (addr & 3)) | (type << 6);
700         packet.address = addr & ~3;
701         packet.data    = data << ((addr & 3) << 3);
702         ret = sisusb_send_packet(sisusb, 10, &packet);
703         return ret;
704 }
705
706 static int sisusb_write_memio_word(struct sisusb_usb_data *sisusb, int type,
707                                                         u32 addr, u16 data)
708 {
709         struct sisusb_packet packet;
710         int ret = 0;
711
712         packet.address = addr & ~3;
713
714         switch (addr & 3) {
715                 case 0:
716                         packet.header = (type << 6) | 0x0003;
717                         packet.data   = (u32)data;
718                         ret = sisusb_send_packet(sisusb, 10, &packet);
719                         break;
720                 case 1:
721                         packet.header = (type << 6) | 0x0006;
722                         packet.data   = (u32)data << 8;
723                         ret = sisusb_send_packet(sisusb, 10, &packet);
724                         break;
725                 case 2:
726                         packet.header = (type << 6) | 0x000c;
727                         packet.data   = (u32)data << 16;
728                         ret = sisusb_send_packet(sisusb, 10, &packet);
729                         break;
730                 case 3:
731                         packet.header = (type << 6) | 0x0008;
732                         packet.data   = (u32)data << 24;
733                         ret = sisusb_send_packet(sisusb, 10, &packet);
734                         packet.header = (type << 6) | 0x0001;
735                         packet.address = (addr & ~3) + 4;
736                         packet.data   = (u32)data >> 8;
737                         ret |= sisusb_send_packet(sisusb, 10, &packet);
738         }
739
740         return ret;
741 }
742
743 static int sisusb_write_memio_24bit(struct sisusb_usb_data *sisusb, int type,
744                                                         u32 addr, u32 data)
745 {
746         struct sisusb_packet packet;
747         int ret = 0;
748
749         packet.address = addr & ~3;
750
751         switch (addr & 3) {
752                 case 0:
753                         packet.header  = (type << 6) | 0x0007;
754                         packet.data    = data & 0x00ffffff;
755                         ret = sisusb_send_packet(sisusb, 10, &packet);
756                         break;
757                 case 1:
758                         packet.header  = (type << 6) | 0x000e;
759                         packet.data    = data << 8;
760                         ret = sisusb_send_packet(sisusb, 10, &packet);
761                         break;
762                 case 2:
763                         packet.header  = (type << 6) | 0x000c;
764                         packet.data    = data << 16;
765                         ret = sisusb_send_packet(sisusb, 10, &packet);
766                         packet.header  = (type << 6) | 0x0001;
767                         packet.address = (addr & ~3) + 4;
768                         packet.data    = (data >> 16) & 0x00ff;
769                         ret |= sisusb_send_packet(sisusb, 10, &packet);
770                         break;
771                 case 3:
772                         packet.header  = (type << 6) | 0x0008;
773                         packet.data    = data << 24;
774                         ret = sisusb_send_packet(sisusb, 10, &packet);
775                         packet.header  = (type << 6) | 0x0003;
776                         packet.address = (addr & ~3) + 4;
777                         packet.data    = (data >> 8) & 0xffff;
778                         ret |= sisusb_send_packet(sisusb, 10, &packet);
779         }
780
781         return ret;
782 }
783
784 static int sisusb_write_memio_long(struct sisusb_usb_data *sisusb, int type,
785                                                         u32 addr, u32 data)
786 {
787         struct sisusb_packet packet;
788         int ret = 0;
789
790         packet.address = addr & ~3;
791
792         switch (addr & 3) {
793                 case 0:
794                         packet.header  = (type << 6) | 0x000f;
795                         packet.data    = data;
796                         ret = sisusb_send_packet(sisusb, 10, &packet);
797                         break;
798                 case 1:
799                         packet.header  = (type << 6) | 0x000e;
800                         packet.data    = data << 8;
801                         ret = sisusb_send_packet(sisusb, 10, &packet);
802                         packet.header  = (type << 6) | 0x0001;
803                         packet.address = (addr & ~3) + 4;
804                         packet.data    = data >> 24;
805                         ret |= sisusb_send_packet(sisusb, 10, &packet);
806                         break;
807                 case 2:
808                         packet.header  = (type << 6) | 0x000c;
809                         packet.data    = data << 16;
810                         ret = sisusb_send_packet(sisusb, 10, &packet);
811                         packet.header  = (type << 6) | 0x0003;
812                         packet.address = (addr & ~3) + 4;
813                         packet.data    = data >> 16;
814                         ret |= sisusb_send_packet(sisusb, 10, &packet);
815                         break;
816                 case 3:
817                         packet.header  = (type << 6) | 0x0008;
818                         packet.data    = data << 24;
819                         ret = sisusb_send_packet(sisusb, 10, &packet);
820                         packet.header  = (type << 6) | 0x0007;
821                         packet.address = (addr & ~3) + 4;
822                         packet.data    = data >> 8;
823                         ret |= sisusb_send_packet(sisusb, 10, &packet);
824         }
825
826         return ret;
827 }
828
829 /* The xxx_bulk routines copy a buffer of variable size. They treat the
830  * buffer as chars, therefore lsb/msb has to be corrected if using the
831  * byte/word/long/etc routines for speed-up
832  *
833  * If data is from userland, set "userbuffer" (and clear "kernbuffer"),
834  * if data is in kernel space, set "kernbuffer" (and clear "userbuffer");
835  * if neither "kernbuffer" nor "userbuffer" are given, it is assumed
836  * that the data already is in the transfer buffer "sisusb->obuf[index]".
837  */
838
839 static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
840                                 char *kernbuffer, int length,
841                                 const char __user *userbuffer, int index,
842                                 ssize_t *bytes_written)
843 {
844         struct sisusb_packet packet;
845         int  ret = 0;
846         static int msgcount = 0;
847         u8   swap8, fromkern = kernbuffer ? 1 : 0;
848         u16  swap16;
849         u32  swap32, flag = (length >> 28) & 1;
850         char buf[4];
851
852         /* if neither kernbuffer not userbuffer are given, assume
853          * data in obuf
854          */
855         if (!fromkern && !userbuffer)
856                 kernbuffer = sisusb->obuf[index];
857
858         (*bytes_written = 0);
859
860         length &= 0x00ffffff;
861
862         while (length) {
863
864             switch (length) {
865
866                 case 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
887                                 swap16 = *((u16 *)kernbuffer);
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;
903 #ifdef __BIG_ENDIAN
904                                 swap32 = (buf[0] << 16) |
905                                          (buf[1] <<  8) |
906                                          buf[2];
907 #else
908                                 swap32 = (buf[2] << 16) |
909                                          (buf[1] <<  8) |
910                                          buf[0];
911 #endif
912                         } else
913 #ifdef __BIG_ENDIAN
914                                 swap32 = (kernbuffer[0] << 16) |
915                                          (kernbuffer[1] <<  8) |
916                                          kernbuffer[2];
917 #else
918                                 swap32 = (kernbuffer[2] << 16) |
919                                          (kernbuffer[1] <<  8) |
920                                          kernbuffer[0];
921 #endif
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
938                                 swap32 = *((u32 *)kernbuffer);
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
1039                                                 "sisusbvga[%d]: Wrote %zd of "
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
1061 /* Remember: Read data in packet is in machine-endianess! So for
1062  * byte, word, 24bit, long no endian correction is necessary.
1063  */
1064
1065 static 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
1079 static 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
1118 static 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
1159 static 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
1204 static 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
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 {
1248                                         *((u16 *)kernbuffer) = swap16;
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;
1258 #ifdef __BIG_ENDIAN
1259                                 buf[0] = (swap32 >> 16) & 0xff;
1260                                 buf[1] = (swap32 >> 8) & 0xff;
1261                                 buf[2] = swap32 & 0xff;
1262 #else
1263                                 buf[2] = (swap32 >> 16) & 0xff;
1264                                 buf[1] = (swap32 >> 8) & 0xff;
1265                                 buf[0] = swap32 & 0xff;
1266 #endif
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 {
1290                                         *((u32 *)kernbuffer) = swap32;
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
1348 #ifdef INCL_SISUSB_CON
1349 int
1350 sisusb_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
1355 int
1356 sisusb_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
1363 static
1364 #endif
1365 int
1366 sisusb_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
1374 #ifndef INCL_SISUSB_CON
1375 static
1376 #endif
1377 int
1378 sisusb_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
1386 #ifndef INCL_SISUSB_CON
1387 static
1388 #endif
1389 int
1390 sisusb_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
1404 static int
1405 sisusb_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
1418 #ifndef INCL_SISUSB_CON
1419 static
1420 #endif
1421 int
1422 sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor)
1423 {
1424         return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));
1425 }
1426
1427 #ifndef INCL_SISUSB_CON
1428 static
1429 #endif
1430 int
1431 sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand)
1432 {
1433         return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00));
1434 }
1435
1436 /* Write/read video ram */
1437
1438 #ifdef INCL_SISUSB_CON
1439 int
1440 sisusb_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
1445 int
1446 sisusb_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
1451 int
1452 sisusb_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
1457 int
1458 sisusb_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
1463 int
1464 sisusb_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
1471 int
1472 sisusb_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
1481 static void
1482 sisusb_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
1501 /* access pci config registers (reg numbers 0, 4, 8, etc) */
1502
1503 static int
1504 sisusb_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
1516 static int
1517 sisusb_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
1531 static int
1532 sisusb_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
1583 static int
1584 sisusb_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
1614 static int
1615 sisusb_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
1727 static int
1728 sisusb_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
1756 static int
1757 sisusb_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
1788 static int
1789 sisusb_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
1811 static int
1812 sisusb_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
1844 static int
1845 sisusb_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
1887 static int
1888 sisusb_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
1927 static int
1928 sisusb_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
2059 static int
2060 sisusb_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
2256 static void
2257 sisusb_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
2300 static int
2301 sisusb_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
2379 static int
2380 sisusb_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
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
2432 int
2433 sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
2434 {
2435         int ret = 0, slot = sisusb->font_slot, i;
2436         const struct font_desc *myfont;
2437         u8 *tempbuf;
2438         u16 *tempbufb;
2439         size_t written;
2440         static const char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2441         static const char bootlogo[] = "(o_ //\\ V_/_";
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
2546 /* fops */
2547
2548 static int
2549 sisusb_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
2605         /* Increment usage count for our sisusb */
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
2616         return 0;
2617 }
2618
2619 void
2620 sisusb_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);
2633 #ifdef INCL_SISUSB_CON
2634         kfree(sisusb->SiS_Pr);
2635 #endif
2636         kfree(sisusb);
2637 }
2638
2639 static int
2640 sisusb_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
2672         return 0;
2673 }
2674
2675 static ssize_t
2676 sisusb_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
2816 static ssize_t
2817 sisusb_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
2964 static loff_t
2965 sisusb_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
3001 static int
3002 sisusb_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
3008         /* All our commands require the device
3009          * to be initialized.
3010          */
3011         if (!sisusb->devinit)
3012                 return -ENODEV;
3013
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:
3055                         /* Gfx core must be initialized */
3056                         if (!sisusb->gfxinit)
3057                                 return -ENODEV;
3058
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
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
3116                 default:
3117                         retval = -EINVAL;
3118         }
3119
3120         if (retval > 0)
3121                 retval = -EIO;
3122
3123         return retval;
3124 }
3125
3126 static int
3127 sisusb_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;
3170 #ifdef INCL_SISUSB_CON
3171                         x.sisusb_conactive  = sisusb->haveconsole ? 1 : 0;
3172 #else
3173                         x.sisusb_conactive  = 0;
3174 #endif
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:
3191                         retval = -ENOTTY;
3192                         break;
3193         }
3194
3195 err_out:
3196         up(&sisusb->lock);
3197         return retval;
3198 }
3199
3200 #ifdef SISUSB_NEW_CONFIG_COMPAT
3201 static long
3202 sisusb_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
3221 static 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
3234 static struct usb_class_driver usb_sisusb_class = {
3235         .name =         "sisusbvga%d",
3236         .fops =         &usb_sisusb_fops,
3237         .minor_base =   SISUSB_MINOR
3238 };
3239
3240 static 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 */
3254         if (!(sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL))) {
3255                 printk(KERN_ERR
3256                         "sisusb: Failed to allocate memory for private data\n");
3257                 return -ENOMEM;
3258         }
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
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
3341         /* Do remaining init stuff */
3342
3343         init_waitqueue_head(&sisusb->wait_q);
3344
3345         usb_set_intfdata(intf, sisusb);
3346
3347         usb_get_dev(sisusb->sisusb_dev);
3348
3349         sisusb->present = 1;
3350
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;
3365         }
3366 #endif
3367
3368         if (dev->speed == USB_SPEED_HIGH) {
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))
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
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
3401         return 0;
3402
3403 error_4:
3404         sisusb_free_urbs(sisusb);
3405 error_3:
3406         sisusb_free_buffers(sisusb);
3407 error_2:
3408         usb_deregister_dev(intf, &usb_sisusb_class);
3409 error_1:
3410         kfree(sisusb);
3411         return retval;
3412 }
3413
3414 static void sisusb_disconnect(struct usb_interface *intf)
3415 {
3416         struct sisusb_usb_data *sisusb;
3417         int minor;
3418
3419         /* This should *not* happen */
3420         if (!(sisusb = usb_get_intfdata(intf)))
3421                 return;
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);
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
3475 static struct usb_device_id sisusb_table [] = {
3476         { USB_DEVICE(0x0711, 0x0900) },
3477         { USB_DEVICE(0x182d, 0x021c) },
3478         { USB_DEVICE(0x182d, 0x0269) },
3479         { }
3480 };
3481
3482 MODULE_DEVICE_TABLE (usb, sisusb_table);
3483
3484 static struct usb_driver sisusb_driver = {
3485         .name =         "sisusb",
3486         .probe =        sisusb_probe,
3487         .disconnect =   sisusb_disconnect,
3488         .id_table =     sisusb_table,
3489 };
3490
3491 static int __init usb_sisusb_init(void)
3492 {
3493         int retval;
3494
3495 #ifdef INCL_SISUSB_CON
3496         sisusb_init_concode();
3497 #endif
3498
3499         if (!(retval = usb_register(&sisusb_driver))) {
3500
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");
3505
3506         }
3507
3508         return retval;
3509 }
3510
3511 static void __exit usb_sisusb_exit(void)
3512 {
3513         usb_deregister(&sisusb_driver);
3514 }
3515
3516 module_init(usb_sisusb_init);
3517 module_exit(usb_sisusb_exit);
3518
3519 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3520 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3521 MODULE_LICENSE("GPL");
3522