1/* 2 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles 3 * 4 * Main part 5 * 6 * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria 7 * 8 * If distributed as part of the Linux kernel, this code is licensed under the 9 * terms of the GPL v2. 10 * 11 * Otherwise, the following license terms apply: 12 * 13 * * Redistribution and use in source and binary forms, with or without 14 * * modification, are permitted provided that the following conditions 15 * * are met: 16 * * 1) Redistributions of source code must retain the above copyright 17 * * notice, this list of conditions and the following disclaimer. 18 * * 2) Redistributions in binary form must reproduce the above copyright 19 * * notice, this list of conditions and the following disclaimer in the 20 * * documentation and/or other materials provided with the distribution. 21 * * 3) The name of the author may not be used to endorse or promote products 22 * * derived from this software without specific psisusbr written permission. 23 * * 24 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR 25 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 28 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 * 35 * Author: Thomas Winischhofer <thomas@winischhofer.net> 36 * 37 */ 38 39#include <linux/mutex.h> 40#include <linux/module.h> 41#include <linux/kernel.h> 42#include <linux/signal.h> 43#include <linux/errno.h> 44#include <linux/poll.h> 45#include <linux/init.h> 46#include <linux/slab.h> 47#include <linux/spinlock.h> 48#include <linux/kref.h> 49#include <linux/usb.h> 50#include <linux/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 64static int sisusb_first_vc = 0; 65static int sisusb_last_vc = 0; 66module_param_named(first, sisusb_first_vc, int, 0); 67module_param_named(last, sisusb_last_vc, int, 0); 68MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)"); 69MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)"); 70#endif 71 72static struct usb_driver sisusb_driver; 73 74static void 75sisusb_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 91static void 92sisusb_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 */ 111static int 112sisusb_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 */ 127static void 128sisusb_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) */ 144static int 145sisusb_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 156static int 157sisusb_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 171static int 172sisusb_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 183static int 184sisusb_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 196static void 197sisusb_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 205static void 206sisusb_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 228static int 229sisusb_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 280static void 281sisusb_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 292static int 293sisusb_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 344static 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 470static 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 551static 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 */ 567 SISUSB_CORRECT_ENDIANNESS_PACKET(packet); 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 587static 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 */ 604 SISUSB_CORRECT_ENDIANNESS_PACKET(packet); 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 636static 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 649static 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 686static 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 727static 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 782static 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, 817 SISUSB_TYPE_MEM, 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, 833 SISUSB_TYPE_MEM, 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, 867 SISUSB_TYPE_MEM, 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, 884 SISUSB_TYPE_MEM, 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, 912 SISUSB_EP_GFX_LBULK_OUT, 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, 919 SISUSB_EP_GFX_LBULK_OUT, 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, 926 SISUSB_EP_GFX_LBULK_OUT, 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, 956 SISUSB_EP_GFX_BULK_OUT, 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, 963 SISUSB_EP_GFX_BULK_OUT, 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, 970 SISUSB_EP_GFX_BULK_OUT, 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 1002static 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 1016static 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 1055static 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 1096static 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 1141static 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 1245int 1246sisusb_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 1251int 1252sisusb_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 1258int 1259sisusb_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 1267int 1268sisusb_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 1276int 1277sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, 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 1291static int 1292sisusb_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 1305int 1306sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor) 1307{ 1308 return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor)); 1309} 1310 1311int 1312sisusb_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 1320int 1321sisusb_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 1326int 1327sisusb_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 1332int 1333sisusb_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 1340int 1341sisusb_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 1350static void 1351sisusb_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 1372static int 1373sisusb_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 1385static int 1386sisusb_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 1400static int 1401sisusb_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 1452static int 1453sisusb_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 1483static int 1484sisusb_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 1596static int 1597sisusb_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 1625static int 1626sisusb_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 1657static int 1658sisusb_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 1680static int 1681sisusb_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 1713static int 1714sisusb_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 1756static int 1757sisusb_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 1796static int 1797sisusb_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 1928static int 1929sisusb_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 2120static void 2121sisusb_get_ramconfig(struct sisusb_usb_data *sisusb) 2122{ 2123 u8 tmp8, tmp82, ramtype; 2124 int bw = 0; 2125 char *ramtypetext1 = NULL; 2126 static const char ram_datarate[4] = {'S', 'S', 'D', 'D'}; 2127 static const char ram_dynamictype[4] = {'D', 'G', 'D', 'G'}; 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 2160 dev_info(&sisusb->sisusb_dev->dev, "%dMB %s %cDR S%cRAM, bus width %d\n", 2161 sisusb->vramsize >> 20, ramtypetext1, 2162 ram_datarate[ramtype], ram_dynamictype[ramtype], bw); 2163} 2164 2165static int 2166sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb) 2167{ 2168 struct sisusb_packet packet; 2169 int ret; 2170 u32 tmp32; 2171 2172 /* Do some magic */ 2173 packet.header = 0x001f; 2174 packet.address = 0x00000324; 2175 packet.data = 0x00000004; 2176 ret = sisusb_send_bridge_packet(sisusb, 10, &packet, 0); 2177 2178 packet.header = 0x001f; 2179 packet.address = 0x00000364; 2180 packet.data = 0x00000004; 2181 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0); 2182 2183 packet.header = 0x001f; 2184 packet.address = 0x00000384; 2185 packet.data = 0x00000004; 2186 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0); 2187 2188 packet.header = 0x001f; 2189 packet.address = 0x00000100; 2190 packet.data = 0x00000700; 2191 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0); 2192 2193 packet.header = 0x000f; 2194 packet.address = 0x00000004; 2195 ret |= sisusb_send_bridge_packet(sisusb, 6, &packet, 0); 2196 packet.data |= 0x17; 2197 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0); 2198 2199 /* Init BAR 0 (VRAM) */ 2200 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32); 2201 ret |= sisusb_write_pci_config(sisusb, 0x10, 0xfffffff0); 2202 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32); 2203 tmp32 &= 0x0f; 2204 tmp32 |= SISUSB_PCI_MEMBASE; 2205 ret |= sisusb_write_pci_config(sisusb, 0x10, tmp32); 2206 2207 /* Init BAR 1 (MMIO) */ 2208 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32); 2209 ret |= sisusb_write_pci_config(sisusb, 0x14, 0xfffffff0); 2210 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32); 2211 tmp32 &= 0x0f; 2212 tmp32 |= SISUSB_PCI_MMIOBASE; 2213 ret |= sisusb_write_pci_config(sisusb, 0x14, tmp32); 2214 2215 /* Init BAR 2 (i/o ports) */ 2216 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32); 2217 ret |= sisusb_write_pci_config(sisusb, 0x18, 0xfffffff0); 2218 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32); 2219 tmp32 &= 0x0f; 2220 tmp32 |= SISUSB_PCI_IOPORTBASE; 2221 ret |= sisusb_write_pci_config(sisusb, 0x18, tmp32); 2222 2223 /* Enable memory and i/o access */ 2224 ret |= sisusb_read_pci_config(sisusb, 0x04, &tmp32); 2225 tmp32 |= 0x3; 2226 ret |= sisusb_write_pci_config(sisusb, 0x04, tmp32); 2227 2228 if (ret == 0) { 2229 /* Some further magic */ 2230 packet.header = 0x001f; 2231 packet.address = 0x00000050; 2232 packet.data = 0x000000ff; 2233 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0); 2234 } 2235 2236 return ret; 2237} 2238 2239/* Initialize the graphics device (return 0 on success) 2240 * This initializes the net2280 as well as the PCI registers 2241 * of the graphics board. 2242 */ 2243 2244static int 2245sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen) 2246{ 2247 int ret = 0, test = 0; 2248 u32 tmp32; 2249 2250 if (sisusb->devinit == 1) { 2251 /* Read PCI BARs and see if they have been set up */ 2252 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32); 2253 if (ret) return ret; 2254 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE) test++; 2255 2256 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32); 2257 if (ret) return ret; 2258 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE) test++; 2259 2260 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32); 2261 if (ret) return ret; 2262 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE) test++; 2263 } 2264 2265 /* No? So reset the device */ 2266 if ((sisusb->devinit == 0) || (test != 3)) { 2267 2268 ret |= sisusb_do_init_gfxdevice(sisusb); 2269 2270 if (ret == 0) 2271 sisusb->devinit = 1; 2272 2273 } 2274 2275 if (sisusb->devinit) { 2276 /* Initialize the graphics core */ 2277 if (sisusb_init_gfxcore(sisusb) == 0) { 2278 sisusb->gfxinit = 1; 2279 sisusb_get_ramconfig(sisusb); 2280 ret |= sisusb_set_default_mode(sisusb, 1); 2281 ret |= sisusb_setup_screen(sisusb, 1, initscreen); 2282 } 2283 } 2284 2285 return ret; 2286} 2287 2288 2289#ifdef INCL_SISUSB_CON 2290 2291/* Set up default text mode: 2292 - Set text mode (0x03) 2293 - Upload default font 2294 - Upload user font (if available) 2295*/ 2296 2297int 2298sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) 2299{ 2300 int ret = 0, slot = sisusb->font_slot, i; 2301 const struct font_desc *myfont; 2302 u8 *tempbuf; 2303 u16 *tempbufb; 2304 size_t written; 2305 static const char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer."; 2306 static const char bootlogo[] = "(o_ //\\ V_/_"; 2307 2308 /* sisusb->lock is down */ 2309 2310 if (!sisusb->SiS_Pr) 2311 return 1; 2312 2313 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30; 2314 sisusb->SiS_Pr->sisusb = (void *)sisusb; 2315 2316 /* Set mode 0x03 */ 2317 SiSUSBSetMode(sisusb->SiS_Pr, 0x03); 2318 2319 if (!(myfont = find_font("VGA8x16"))) 2320 return 1; 2321 2322 if (!(tempbuf = vmalloc(8192))) 2323 return 1; 2324 2325 for (i = 0; i < 256; i++) 2326 memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16); 2327 2328 /* Upload default font */ 2329 ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, 0, 1, NULL, 16, 0); 2330 2331 vfree(tempbuf); 2332 2333 /* Upload user font (and reset current slot) */ 2334 if (sisusb->font_backup) { 2335 ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup, 2336 8192, sisusb->font_backup_512, 1, NULL, 2337 sisusb->font_backup_height, 0); 2338 if (slot != 2) 2339 sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1, 2340 NULL, 16, 0); 2341 } 2342 2343 if (init && !sisusb->scrbuf) { 2344 2345 if ((tempbuf = vmalloc(8192))) { 2346 2347 i = 4096; 2348 tempbufb = (u16 *)tempbuf; 2349 while (i--) 2350 *(tempbufb++) = 0x0720; 2351 2352 i = 0; 2353 tempbufb = (u16 *)tempbuf; 2354 while (bootlogo[i]) { 2355 *(tempbufb++) = 0x0700 | bootlogo[i++]; 2356 if (!(i % 4)) 2357 tempbufb += 76; 2358 } 2359 2360 i = 0; 2361 tempbufb = (u16 *)tempbuf + 6; 2362 while (bootstring[i]) 2363 *(tempbufb++) = 0x0700 | bootstring[i++]; 2364 2365 ret |= sisusb_copy_memory(sisusb, tempbuf, 2366 sisusb->vrambase, 8192, &written); 2367 2368 vfree(tempbuf); 2369 2370 } 2371 2372 } else if (sisusb->scrbuf) { 2373 2374 ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf, 2375 sisusb->vrambase, sisusb->scrbuf_size, &written); 2376 2377 } 2378 2379 if (sisusb->sisusb_cursor_size_from >= 0 && 2380 sisusb->sisusb_cursor_size_to >= 0) { 2381 sisusb_setidxreg(sisusb, SISCR, 0x0a, 2382 sisusb->sisusb_cursor_size_from); 2383 sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0, 2384 sisusb->sisusb_cursor_size_to); 2385 } else { 2386 sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d); 2387 sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e); 2388 sisusb->sisusb_cursor_size_to = -1; 2389 } 2390 2391 slot = sisusb->sisusb_cursor_loc; 2392 if(slot < 0) slot = 0; 2393 2394 sisusb->sisusb_cursor_loc = -1; 2395 sisusb->bad_cursor_pos = 1; 2396 2397 sisusb_set_cursor(sisusb, slot); 2398 2399 sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8)); 2400 sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff)); 2401 2402 sisusb->textmodedestroyed = 0; 2403 2404 /* sisusb->lock is down */ 2405 2406 return ret; 2407} 2408 2409#endif 2410 2411/* fops */ 2412 2413static int 2414sisusb_open(struct inode *inode, struct file *file) 2415{ 2416 struct sisusb_usb_data *sisusb; 2417 struct usb_interface *interface; 2418 int subminor = iminor(inode); 2419 2420 if (!(interface = usb_find_interface(&sisusb_driver, subminor))) { 2421 return -ENODEV; 2422 } 2423 2424 if (!(sisusb = usb_get_intfdata(interface))) { 2425 return -ENODEV; 2426 } 2427 2428 mutex_lock(&sisusb->lock); 2429 2430 if (!sisusb->present || !sisusb->ready) { 2431 mutex_unlock(&sisusb->lock); 2432 return -ENODEV; 2433 } 2434 2435 if (sisusb->isopen) { 2436 mutex_unlock(&sisusb->lock); 2437 return -EBUSY; 2438 } 2439 2440 if (!sisusb->devinit) { 2441 if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH || 2442 sisusb->sisusb_dev->speed == USB_SPEED_SUPER) { 2443 if (sisusb_init_gfxdevice(sisusb, 0)) { 2444 mutex_unlock(&sisusb->lock); 2445 dev_err(&sisusb->sisusb_dev->dev, "Failed to initialize device\n"); 2446 return -EIO; 2447 } 2448 } else { 2449 mutex_unlock(&sisusb->lock); 2450 dev_err(&sisusb->sisusb_dev->dev, "Device not attached to USB 2.0 hub\n"); 2451 return -EIO; 2452 } 2453 } 2454 2455 /* Increment usage count for our sisusb */ 2456 kref_get(&sisusb->kref); 2457 2458 sisusb->isopen = 1; 2459 2460 file->private_data = sisusb; 2461 2462 mutex_unlock(&sisusb->lock); 2463 2464 return 0; 2465} 2466 2467void 2468sisusb_delete(struct kref *kref) 2469{ 2470 struct sisusb_usb_data *sisusb = to_sisusb_dev(kref); 2471 2472 if (!sisusb) 2473 return; 2474 2475 if (sisusb->sisusb_dev) 2476 usb_put_dev(sisusb->sisusb_dev); 2477 2478 sisusb->sisusb_dev = NULL; 2479 sisusb_free_buffers(sisusb); 2480 sisusb_free_urbs(sisusb); 2481#ifdef INCL_SISUSB_CON 2482 kfree(sisusb->SiS_Pr); 2483#endif 2484 kfree(sisusb); 2485} 2486 2487static int 2488sisusb_release(struct inode *inode, struct file *file) 2489{ 2490 struct sisusb_usb_data *sisusb; 2491 2492 if (!(sisusb = file->private_data)) 2493 return -ENODEV; 2494 2495 mutex_lock(&sisusb->lock); 2496 2497 if (sisusb->present) { 2498 /* Wait for all URBs to finish if device still present */ 2499 if (!sisusb_wait_all_out_complete(sisusb)) 2500 sisusb_kill_all_busy(sisusb); 2501 } 2502 2503 sisusb->isopen = 0; 2504 file->private_data = NULL; 2505 2506 mutex_unlock(&sisusb->lock); 2507 2508 /* decrement the usage count on our device */ 2509 kref_put(&sisusb->kref, sisusb_delete); 2510 2511 return 0; 2512} 2513 2514static ssize_t 2515sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) 2516{ 2517 struct sisusb_usb_data *sisusb; 2518 ssize_t bytes_read = 0; 2519 int errno = 0; 2520 u8 buf8; 2521 u16 buf16; 2522 u32 buf32, address; 2523 2524 if (!(sisusb = file->private_data)) 2525 return -ENODEV; 2526 2527 mutex_lock(&sisusb->lock); 2528 2529 /* Sanity check */ 2530 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { 2531 mutex_unlock(&sisusb->lock); 2532 return -ENODEV; 2533 } 2534 2535 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE && 2536 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) { 2537 2538 address = (*ppos) - 2539 SISUSB_PCI_PSEUDO_IOPORTBASE + 2540 SISUSB_PCI_IOPORTBASE; 2541 2542 /* Read i/o ports 2543 * Byte, word and long(32) can be read. As this 2544 * emulates inX instructions, the data returned is 2545 * in machine-endianness. 2546 */ 2547 switch (count) { 2548 2549 case 1: 2550 if (sisusb_read_memio_byte(sisusb, 2551 SISUSB_TYPE_IO, 2552 address, &buf8)) 2553 errno = -EIO; 2554 else if (put_user(buf8, (u8 __user *)buffer)) 2555 errno = -EFAULT; 2556 else 2557 bytes_read = 1; 2558 2559 break; 2560 2561 case 2: 2562 if (sisusb_read_memio_word(sisusb, 2563 SISUSB_TYPE_IO, 2564 address, &buf16)) 2565 errno = -EIO; 2566 else if (put_user(buf16, (u16 __user *)buffer)) 2567 errno = -EFAULT; 2568 else 2569 bytes_read = 2; 2570 2571 break; 2572 2573 case 4: 2574 if (sisusb_read_memio_long(sisusb, 2575 SISUSB_TYPE_IO, 2576 address, &buf32)) 2577 errno = -EIO; 2578 else if (put_user(buf32, (u32 __user *)buffer)) 2579 errno = -EFAULT; 2580 else 2581 bytes_read = 4; 2582 2583 break; 2584 2585 default: 2586 errno = -EIO; 2587 2588 } 2589 2590 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && 2591 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) { 2592 2593 address = (*ppos) - 2594 SISUSB_PCI_PSEUDO_MEMBASE + 2595 SISUSB_PCI_MEMBASE; 2596 2597 /* Read video ram 2598 * Remember: Data delivered is never endian-corrected 2599 */ 2600 errno = sisusb_read_mem_bulk(sisusb, address, 2601 NULL, count, buffer, &bytes_read); 2602 2603 if (bytes_read) 2604 errno = bytes_read; 2605 2606 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE && 2607 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) { 2608 2609 address = (*ppos) - 2610 SISUSB_PCI_PSEUDO_MMIOBASE + 2611 SISUSB_PCI_MMIOBASE; 2612 2613 /* Read MMIO 2614 * Remember: Data delivered is never endian-corrected 2615 */ 2616 errno = sisusb_read_mem_bulk(sisusb, address, 2617 NULL, count, buffer, &bytes_read); 2618 2619 if (bytes_read) 2620 errno = bytes_read; 2621 2622 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE && 2623 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) { 2624 2625 if (count != 4) { 2626 mutex_unlock(&sisusb->lock); 2627 return -EINVAL; 2628 } 2629 2630 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE; 2631 2632 /* Read PCI config register 2633 * Return value delivered in machine endianness. 2634 */ 2635 if (sisusb_read_pci_config(sisusb, address, &buf32)) 2636 errno = -EIO; 2637 else if (put_user(buf32, (u32 __user *)buffer)) 2638 errno = -EFAULT; 2639 else 2640 bytes_read = 4; 2641 2642 } else { 2643 2644 errno = -EBADFD; 2645 2646 } 2647 2648 (*ppos) += bytes_read; 2649 2650 mutex_unlock(&sisusb->lock); 2651 2652 return errno ? errno : bytes_read; 2653} 2654 2655static ssize_t 2656sisusb_write(struct file *file, const char __user *buffer, size_t count, 2657 loff_t *ppos) 2658{ 2659 struct sisusb_usb_data *sisusb; 2660 int errno = 0; 2661 ssize_t bytes_written = 0; 2662 u8 buf8; 2663 u16 buf16; 2664 u32 buf32, address; 2665 2666 if (!(sisusb = file->private_data)) 2667 return -ENODEV; 2668 2669 mutex_lock(&sisusb->lock); 2670 2671 /* Sanity check */ 2672 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { 2673 mutex_unlock(&sisusb->lock); 2674 return -ENODEV; 2675 } 2676 2677 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE && 2678 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) { 2679 2680 address = (*ppos) - 2681 SISUSB_PCI_PSEUDO_IOPORTBASE + 2682 SISUSB_PCI_IOPORTBASE; 2683 2684 /* Write i/o ports 2685 * Byte, word and long(32) can be written. As this 2686 * emulates outX instructions, the data is expected 2687 * in machine-endianness. 2688 */ 2689 switch (count) { 2690 2691 case 1: 2692 if (get_user(buf8, (u8 __user *)buffer)) 2693 errno = -EFAULT; 2694 else if (sisusb_write_memio_byte(sisusb, 2695 SISUSB_TYPE_IO, 2696 address, buf8)) 2697 errno = -EIO; 2698 else 2699 bytes_written = 1; 2700 2701 break; 2702 2703 case 2: 2704 if (get_user(buf16, (u16 __user *)buffer)) 2705 errno = -EFAULT; 2706 else if (sisusb_write_memio_word(sisusb, 2707 SISUSB_TYPE_IO, 2708 address, buf16)) 2709 errno = -EIO; 2710 else 2711 bytes_written = 2; 2712 2713 break; 2714 2715 case 4: 2716 if (get_user(buf32, (u32 __user *)buffer)) 2717 errno = -EFAULT; 2718 else if (sisusb_write_memio_long(sisusb, 2719 SISUSB_TYPE_IO, 2720 address, buf32)) 2721 errno = -EIO; 2722 else 2723 bytes_written = 4; 2724 2725 break; 2726 2727 default: 2728 errno = -EIO; 2729 } 2730 2731 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && 2732 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) { 2733 2734 address = (*ppos) - 2735 SISUSB_PCI_PSEUDO_MEMBASE + 2736 SISUSB_PCI_MEMBASE; 2737 2738 /* Write video ram. 2739 * Buffer is copied 1:1, therefore, on big-endian 2740 * machines, the data must be swapped by userland 2741 * in advance (if applicable; no swapping in 8bpp 2742 * mode or if YUV data is being transferred). 2743 */ 2744 errno = sisusb_write_mem_bulk(sisusb, address, NULL, 2745 count, buffer, 0, &bytes_written); 2746 2747 if (bytes_written) 2748 errno = bytes_written; 2749 2750 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE && 2751 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) { 2752 2753 address = (*ppos) - 2754 SISUSB_PCI_PSEUDO_MMIOBASE + 2755 SISUSB_PCI_MMIOBASE; 2756 2757 /* Write MMIO. 2758 * Buffer is copied 1:1, therefore, on big-endian 2759 * machines, the data must be swapped by userland 2760 * in advance. 2761 */ 2762 errno = sisusb_write_mem_bulk(sisusb, address, NULL, 2763 count, buffer, 0, &bytes_written); 2764 2765 if (bytes_written) 2766 errno = bytes_written; 2767 2768 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE && 2769 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + SISUSB_PCI_PCONFSIZE) { 2770 2771 if (count != 4) { 2772 mutex_unlock(&sisusb->lock); 2773 return -EINVAL; 2774 } 2775 2776 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE; 2777 2778 /* Write PCI config register. 2779 * Given value expected in machine endianness. 2780 */ 2781 if (get_user(buf32, (u32 __user *)buffer)) 2782 errno = -EFAULT; 2783 else if (sisusb_write_pci_config(sisusb, address, buf32)) 2784 errno = -EIO; 2785 else 2786 bytes_written = 4; 2787 2788 2789 } else { 2790 2791 /* Error */ 2792 errno = -EBADFD; 2793 2794 } 2795 2796 (*ppos) += bytes_written; 2797 2798 mutex_unlock(&sisusb->lock); 2799 2800 return errno ? errno : bytes_written; 2801} 2802 2803static loff_t 2804sisusb_lseek(struct file *file, loff_t offset, int orig) 2805{ 2806 struct sisusb_usb_data *sisusb; 2807 loff_t ret; 2808 2809 if (!(sisusb = file->private_data)) 2810 return -ENODEV; 2811 2812 mutex_lock(&sisusb->lock); 2813 2814 /* Sanity check */ 2815 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { 2816 mutex_unlock(&sisusb->lock); 2817 return -ENODEV; 2818 } 2819 2820 switch (orig) { 2821 case 0: 2822 file->f_pos = offset; 2823 ret = file->f_pos; 2824 /* never negative, no force_successful_syscall needed */ 2825 break; 2826 case 1: 2827 file->f_pos += offset; 2828 ret = file->f_pos; 2829 /* never negative, no force_successful_syscall needed */ 2830 break; 2831 default: 2832 /* seeking relative to "end of file" is not supported */ 2833 ret = -EINVAL; 2834 } 2835 2836 mutex_unlock(&sisusb->lock); 2837 return ret; 2838} 2839 2840static int 2841sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y, 2842 unsigned long arg) 2843{ 2844 int retval, port, length; 2845 u32 address; 2846 2847 /* All our commands require the device 2848 * to be initialized. 2849 */ 2850 if (!sisusb->devinit) 2851 return -ENODEV; 2852 2853 port = y->data3 - 2854 SISUSB_PCI_PSEUDO_IOPORTBASE + 2855 SISUSB_PCI_IOPORTBASE; 2856 2857 switch (y->operation) { 2858 case SUCMD_GET: 2859 retval = sisusb_getidxreg(sisusb, port, 2860 y->data0, &y->data1); 2861 if (!retval) { 2862 if (copy_to_user((void __user *)arg, y, 2863 sizeof(*y))) 2864 retval = -EFAULT; 2865 } 2866 break; 2867 2868 case SUCMD_SET: 2869 retval = sisusb_setidxreg(sisusb, port, 2870 y->data0, y->data1); 2871 break; 2872 2873 case SUCMD_SETOR: 2874 retval = sisusb_setidxregor(sisusb, port, 2875 y->data0, y->data1); 2876 break; 2877 2878 case SUCMD_SETAND: 2879 retval = sisusb_setidxregand(sisusb, port, 2880 y->data0, y->data1); 2881 break; 2882 2883 case SUCMD_SETANDOR: 2884 retval = sisusb_setidxregandor(sisusb, port, 2885 y->data0, y->data1, y->data2); 2886 break; 2887 2888 case SUCMD_SETMASK: 2889 retval = sisusb_setidxregmask(sisusb, port, 2890 y->data0, y->data1, y->data2); 2891 break; 2892 2893 case SUCMD_CLRSCR: 2894 /* Gfx core must be initialized */ 2895 if (!sisusb->gfxinit) 2896 return -ENODEV; 2897 2898 length = (y->data0 << 16) | (y->data1 << 8) | y->data2; 2899 address = y->data3 - 2900 SISUSB_PCI_PSEUDO_MEMBASE + 2901 SISUSB_PCI_MEMBASE; 2902 retval = sisusb_clear_vram(sisusb, address, length); 2903 break; 2904 2905 case SUCMD_HANDLETEXTMODE: 2906 retval = 0; 2907#ifdef INCL_SISUSB_CON 2908 /* Gfx core must be initialized, SiS_Pr must exist */ 2909 if (!sisusb->gfxinit || !sisusb->SiS_Pr) 2910 return -ENODEV; 2911 2912 switch (y->data0) { 2913 case 0: 2914 retval = sisusb_reset_text_mode(sisusb, 0); 2915 break; 2916 case 1: 2917 sisusb->textmodedestroyed = 1; 2918 break; 2919 } 2920#endif 2921 break; 2922 2923#ifdef INCL_SISUSB_CON 2924 case SUCMD_SETMODE: 2925 /* Gfx core must be initialized, SiS_Pr must exist */ 2926 if (!sisusb->gfxinit || !sisusb->SiS_Pr) 2927 return -ENODEV; 2928 2929 retval = 0; 2930 2931 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30; 2932 sisusb->SiS_Pr->sisusb = (void *)sisusb; 2933 2934 if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3)) 2935 retval = -EINVAL; 2936 2937 break; 2938 2939 case SUCMD_SETVESAMODE: 2940 /* Gfx core must be initialized, SiS_Pr must exist */ 2941 if (!sisusb->gfxinit || !sisusb->SiS_Pr) 2942 return -ENODEV; 2943 2944 retval = 0; 2945 2946 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30; 2947 sisusb->SiS_Pr->sisusb = (void *)sisusb; 2948 2949 if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3)) 2950 retval = -EINVAL; 2951 2952 break; 2953#endif 2954 2955 default: 2956 retval = -EINVAL; 2957 } 2958 2959 if (retval > 0) 2960 retval = -EIO; 2961 2962 return retval; 2963} 2964 2965static long 2966sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 2967{ 2968 struct sisusb_usb_data *sisusb; 2969 struct sisusb_info x; 2970 struct sisusb_command y; 2971 long retval = 0; 2972 u32 __user *argp = (u32 __user *)arg; 2973 2974 if (!(sisusb = file->private_data)) 2975 return -ENODEV; 2976 2977 mutex_lock(&sisusb->lock); 2978 2979 /* Sanity check */ 2980 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { 2981 retval = -ENODEV; 2982 goto err_out; 2983 } 2984 2985 switch (cmd) { 2986 2987 case SISUSB_GET_CONFIG_SIZE: 2988 2989 if (put_user(sizeof(x), argp)) 2990 retval = -EFAULT; 2991 2992 break; 2993 2994 case SISUSB_GET_CONFIG: 2995 2996 x.sisusb_id = SISUSB_ID; 2997 x.sisusb_version = SISUSB_VERSION; 2998 x.sisusb_revision = SISUSB_REVISION; 2999 x.sisusb_patchlevel = SISUSB_PATCHLEVEL; 3000 x.sisusb_gfxinit = sisusb->gfxinit; 3001 x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE; 3002 x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE; 3003 x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE; 3004 x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE; 3005 x.sisusb_vramsize = sisusb->vramsize; 3006 x.sisusb_minor = sisusb->minor; 3007 x.sisusb_fbdevactive= 0; 3008#ifdef INCL_SISUSB_CON 3009 x.sisusb_conactive = sisusb->haveconsole ? 1 : 0; 3010#else 3011 x.sisusb_conactive = 0; 3012#endif 3013 memset(x.sisusb_reserved, 0, sizeof(x.sisusb_reserved)); 3014 3015 if (copy_to_user((void __user *)arg, &x, sizeof(x))) 3016 retval = -EFAULT; 3017 3018 break; 3019 3020 case SISUSB_COMMAND: 3021 3022 if (copy_from_user(&y, (void __user *)arg, sizeof(y))) 3023 retval = -EFAULT; 3024 else 3025 retval = sisusb_handle_command(sisusb, &y, arg); 3026 3027 break; 3028 3029 default: 3030 retval = -ENOTTY; 3031 break; 3032 } 3033 3034err_out: 3035 mutex_unlock(&sisusb->lock); 3036 return retval; 3037} 3038 3039#ifdef SISUSB_NEW_CONFIG_COMPAT 3040static long 3041sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg) 3042{ 3043 long retval; 3044 3045 switch (cmd) { 3046 case SISUSB_GET_CONFIG_SIZE: 3047 case SISUSB_GET_CONFIG: 3048 case SISUSB_COMMAND: 3049 retval = sisusb_ioctl(f, cmd, arg); 3050 return retval; 3051 3052 default: 3053 return -ENOIOCTLCMD; 3054 } 3055} 3056#endif 3057 3058static const struct file_operations usb_sisusb_fops = { 3059 .owner = THIS_MODULE, 3060 .open = sisusb_open, 3061 .release = sisusb_release, 3062 .read = sisusb_read, 3063 .write = sisusb_write, 3064 .llseek = sisusb_lseek, 3065#ifdef SISUSB_NEW_CONFIG_COMPAT 3066 .compat_ioctl = sisusb_compat_ioctl, 3067#endif 3068 .unlocked_ioctl = sisusb_ioctl 3069}; 3070 3071static struct usb_class_driver usb_sisusb_class = { 3072 .name = "sisusbvga%d", 3073 .fops = &usb_sisusb_fops, 3074 .minor_base = SISUSB_MINOR 3075}; 3076 3077static int sisusb_probe(struct usb_interface *intf, 3078 const struct usb_device_id *id) 3079{ 3080 struct usb_device *dev = interface_to_usbdev(intf); 3081 struct sisusb_usb_data *sisusb; 3082 int retval = 0, i; 3083 3084 dev_info(&dev->dev, "USB2VGA dongle found at address %d\n", 3085 dev->devnum); 3086 3087 /* Allocate memory for our private */ 3088 if (!(sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL))) { 3089 dev_err(&dev->dev, "Failed to allocate memory for private data\n"); 3090 return -ENOMEM; 3091 } 3092 kref_init(&sisusb->kref); 3093 3094 mutex_init(&(sisusb->lock)); 3095 3096 /* Register device */ 3097 if ((retval = usb_register_dev(intf, &usb_sisusb_class))) { 3098 dev_err(&sisusb->sisusb_dev->dev, "Failed to get a minor for device %d\n", 3099 dev->devnum); 3100 retval = -ENODEV; 3101 goto error_1; 3102 } 3103 3104 sisusb->sisusb_dev = dev; 3105 sisusb->minor = intf->minor; 3106 sisusb->vrambase = SISUSB_PCI_MEMBASE; 3107 sisusb->mmiobase = SISUSB_PCI_MMIOBASE; 3108 sisusb->mmiosize = SISUSB_PCI_MMIOSIZE; 3109 sisusb->ioportbase = SISUSB_PCI_IOPORTBASE; 3110 /* Everything else is zero */ 3111 3112 /* Allocate buffers */ 3113 sisusb->ibufsize = SISUSB_IBUF_SIZE; 3114 if (!(sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL))) { 3115 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for input buffer"); 3116 retval = -ENOMEM; 3117 goto error_2; 3118 } 3119 3120 sisusb->numobufs = 0; 3121 sisusb->obufsize = SISUSB_OBUF_SIZE; 3122 for (i = 0; i < NUMOBUFS; i++) { 3123 if (!(sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL))) { 3124 if (i == 0) { 3125 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for output buffer\n"); 3126 retval = -ENOMEM; 3127 goto error_3; 3128 } 3129 break; 3130 } else 3131 sisusb->numobufs++; 3132 3133 } 3134 3135 /* Allocate URBs */ 3136 if (!(sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL))) { 3137 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n"); 3138 retval = -ENOMEM; 3139 goto error_3; 3140 } 3141 sisusb->completein = 1; 3142 3143 for (i = 0; i < sisusb->numobufs; i++) { 3144 if (!(sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL))) { 3145 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n"); 3146 retval = -ENOMEM; 3147 goto error_4; 3148 } 3149 sisusb->urbout_context[i].sisusb = (void *)sisusb; 3150 sisusb->urbout_context[i].urbindex = i; 3151 sisusb->urbstatus[i] = 0; 3152 } 3153 3154 dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n", sisusb->numobufs); 3155 3156#ifdef INCL_SISUSB_CON 3157 /* Allocate our SiS_Pr */ 3158 if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) { 3159 dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate SiS_Pr\n"); 3160 } 3161#endif 3162 3163 /* Do remaining init stuff */ 3164 3165 init_waitqueue_head(&sisusb->wait_q); 3166 3167 usb_set_intfdata(intf, sisusb); 3168 3169 usb_get_dev(sisusb->sisusb_dev); 3170 3171 sisusb->present = 1; 3172 3173 if (dev->speed == USB_SPEED_HIGH || dev->speed == USB_SPEED_SUPER) { 3174 int initscreen = 1; 3175#ifdef INCL_SISUSB_CON 3176 if (sisusb_first_vc > 0 && 3177 sisusb_last_vc > 0 && 3178 sisusb_first_vc <= sisusb_last_vc && 3179 sisusb_last_vc <= MAX_NR_CONSOLES) 3180 initscreen = 0; 3181#endif 3182 if (sisusb_init_gfxdevice(sisusb, initscreen)) 3183 dev_err(&sisusb->sisusb_dev->dev, "Failed to early initialize device\n"); 3184 3185 } else 3186 dev_info(&sisusb->sisusb_dev->dev, "Not attached to USB 2.0 hub, deferring init\n"); 3187 3188 sisusb->ready = 1; 3189 3190#ifdef SISUSBENDIANTEST 3191 dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST ***\n"); 3192 sisusb_testreadwrite(sisusb); 3193 dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST END ***\n"); 3194#endif 3195 3196#ifdef INCL_SISUSB_CON 3197 sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc); 3198#endif 3199 3200 return 0; 3201 3202error_4: 3203 sisusb_free_urbs(sisusb); 3204error_3: 3205 sisusb_free_buffers(sisusb); 3206error_2: 3207 usb_deregister_dev(intf, &usb_sisusb_class); 3208error_1: 3209 kfree(sisusb); 3210 return retval; 3211} 3212 3213static void sisusb_disconnect(struct usb_interface *intf) 3214{ 3215 struct sisusb_usb_data *sisusb; 3216 3217 /* This should *not* happen */ 3218 if (!(sisusb = usb_get_intfdata(intf))) 3219 return; 3220 3221#ifdef INCL_SISUSB_CON 3222 sisusb_console_exit(sisusb); 3223#endif 3224 3225 usb_deregister_dev(intf, &usb_sisusb_class); 3226 3227 mutex_lock(&sisusb->lock); 3228 3229 /* Wait for all URBs to complete and kill them in case (MUST do) */ 3230 if (!sisusb_wait_all_out_complete(sisusb)) 3231 sisusb_kill_all_busy(sisusb); 3232 3233 usb_set_intfdata(intf, NULL); 3234 3235 sisusb->present = 0; 3236 sisusb->ready = 0; 3237 3238 mutex_unlock(&sisusb->lock); 3239 3240 /* decrement our usage count */ 3241 kref_put(&sisusb->kref, sisusb_delete); 3242} 3243 3244static const struct usb_device_id sisusb_table[] = { 3245 { USB_DEVICE(0x0711, 0x0550) }, 3246 { USB_DEVICE(0x0711, 0x0900) }, 3247 { USB_DEVICE(0x0711, 0x0901) }, 3248 { USB_DEVICE(0x0711, 0x0902) }, 3249 { USB_DEVICE(0x0711, 0x0903) }, 3250 { USB_DEVICE(0x0711, 0x0918) }, 3251 { USB_DEVICE(0x0711, 0x0920) }, 3252 { USB_DEVICE(0x0711, 0x0950) }, 3253 { USB_DEVICE(0x0711, 0x5200) }, 3254 { USB_DEVICE(0x182d, 0x021c) }, 3255 { USB_DEVICE(0x182d, 0x0269) }, 3256 { } 3257}; 3258 3259MODULE_DEVICE_TABLE (usb, sisusb_table); 3260 3261static struct usb_driver sisusb_driver = { 3262 .name = "sisusb", 3263 .probe = sisusb_probe, 3264 .disconnect = sisusb_disconnect, 3265 .id_table = sisusb_table, 3266}; 3267 3268static int __init usb_sisusb_init(void) 3269{ 3270 3271#ifdef INCL_SISUSB_CON 3272 sisusb_init_concode(); 3273#endif 3274 3275 return usb_register(&sisusb_driver); 3276} 3277 3278static void __exit usb_sisusb_exit(void) 3279{ 3280 usb_deregister(&sisusb_driver); 3281} 3282 3283module_init(usb_sisusb_init); 3284module_exit(usb_sisusb_exit); 3285 3286MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>"); 3287MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles"); 3288MODULE_LICENSE("GPL"); 3289 3290