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