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