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