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