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