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