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