0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 #include <linux/mutex.h>
0041 #include <linux/module.h>
0042 #include <linux/kernel.h>
0043 #include <linux/signal.h>
0044 #include <linux/errno.h>
0045 #include <linux/poll.h>
0046 #include <linux/init.h>
0047 #include <linux/slab.h>
0048 #include <linux/spinlock.h>
0049 #include <linux/kref.h>
0050 #include <linux/usb.h>
0051 #include <linux/vmalloc.h>
0052
0053 #include "sisusb.h"
0054 #include "sisusb_init.h"
0055
0056 #ifdef CONFIG_USB_SISUSBVGA_CON
0057 #include <linux/font.h>
0058 #endif
0059
0060 #define SISUSB_DONTSYNC
0061
0062
0063
0064 #ifdef CONFIG_USB_SISUSBVGA_CON
0065 static int sisusb_first_vc;
0066 static int sisusb_last_vc;
0067 module_param_named(first, sisusb_first_vc, int, 0);
0068 module_param_named(last, sisusb_last_vc, int, 0);
0069 MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
0070 MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
0071 #endif
0072
0073 static struct usb_driver sisusb_driver;
0074
0075 static void sisusb_free_buffers(struct sisusb_usb_data *sisusb)
0076 {
0077 int i;
0078
0079 for (i = 0; i < NUMOBUFS; i++) {
0080 kfree(sisusb->obuf[i]);
0081 sisusb->obuf[i] = NULL;
0082 }
0083 kfree(sisusb->ibuf);
0084 sisusb->ibuf = NULL;
0085 }
0086
0087 static void sisusb_free_urbs(struct sisusb_usb_data *sisusb)
0088 {
0089 int i;
0090
0091 for (i = 0; i < NUMOBUFS; i++) {
0092 usb_free_urb(sisusb->sisurbout[i]);
0093 sisusb->sisurbout[i] = NULL;
0094 }
0095 usb_free_urb(sisusb->sisurbin);
0096 sisusb->sisurbin = NULL;
0097 }
0098
0099
0100
0101
0102
0103
0104
0105
0106 static int sisusb_all_free(struct sisusb_usb_data *sisusb)
0107 {
0108 int i;
0109
0110 for (i = 0; i < sisusb->numobufs; i++) {
0111
0112 if (sisusb->urbstatus[i] & SU_URB_BUSY)
0113 return 0;
0114
0115 }
0116
0117 return 1;
0118 }
0119
0120
0121 static void sisusb_kill_all_busy(struct sisusb_usb_data *sisusb)
0122 {
0123 int i;
0124
0125 if (sisusb_all_free(sisusb))
0126 return;
0127
0128 for (i = 0; i < sisusb->numobufs; i++) {
0129
0130 if (sisusb->urbstatus[i] & SU_URB_BUSY)
0131 usb_kill_urb(sisusb->sisurbout[i]);
0132
0133 }
0134 }
0135
0136
0137 static int sisusb_wait_all_out_complete(struct sisusb_usb_data *sisusb)
0138 {
0139 int timeout = 5 * HZ, i = 1;
0140
0141 wait_event_timeout(sisusb->wait_q, (i = sisusb_all_free(sisusb)),
0142 timeout);
0143
0144 return i;
0145 }
0146
0147 static int sisusb_outurb_available(struct sisusb_usb_data *sisusb)
0148 {
0149 int i;
0150
0151 for (i = 0; i < sisusb->numobufs; i++) {
0152
0153 if ((sisusb->urbstatus[i] & (SU_URB_BUSY|SU_URB_ALLOC)) == 0)
0154 return i;
0155
0156 }
0157
0158 return -1;
0159 }
0160
0161 static int sisusb_get_free_outbuf(struct sisusb_usb_data *sisusb)
0162 {
0163 int i, timeout = 5 * HZ;
0164
0165 wait_event_timeout(sisusb->wait_q,
0166 ((i = sisusb_outurb_available(sisusb)) >= 0), timeout);
0167
0168 return i;
0169 }
0170
0171 static int sisusb_alloc_outbuf(struct sisusb_usb_data *sisusb)
0172 {
0173 int i;
0174
0175 i = sisusb_outurb_available(sisusb);
0176
0177 if (i >= 0)
0178 sisusb->urbstatus[i] |= SU_URB_ALLOC;
0179
0180 return i;
0181 }
0182
0183 static void sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index)
0184 {
0185 if ((index >= 0) && (index < sisusb->numobufs))
0186 sisusb->urbstatus[index] &= ~SU_URB_ALLOC;
0187 }
0188
0189
0190
0191 static void sisusb_bulk_completeout(struct urb *urb)
0192 {
0193 struct sisusb_urb_context *context = urb->context;
0194 struct sisusb_usb_data *sisusb;
0195
0196 if (!context)
0197 return;
0198
0199 sisusb = context->sisusb;
0200
0201 if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
0202 return;
0203
0204 #ifndef SISUSB_DONTSYNC
0205 if (context->actual_length)
0206 *(context->actual_length) += urb->actual_length;
0207 #endif
0208
0209 sisusb->urbstatus[context->urbindex] &= ~SU_URB_BUSY;
0210 wake_up(&sisusb->wait_q);
0211 }
0212
0213 static int sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index,
0214 unsigned int pipe, void *data, int len, int *actual_length,
0215 int timeout, unsigned int tflags)
0216 {
0217 struct urb *urb = sisusb->sisurbout[index];
0218 int retval, byteswritten = 0;
0219
0220
0221 urb->transfer_flags = 0;
0222
0223 usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
0224 sisusb_bulk_completeout,
0225 &sisusb->urbout_context[index]);
0226
0227 urb->transfer_flags |= tflags;
0228 urb->actual_length = 0;
0229
0230
0231 sisusb->urbout_context[index].actual_length = (timeout) ?
0232 NULL : actual_length;
0233
0234
0235 sisusb->urbstatus[index] |= SU_URB_BUSY;
0236
0237
0238 retval = usb_submit_urb(urb, GFP_KERNEL);
0239
0240
0241 if ((retval == 0) && timeout) {
0242 wait_event_timeout(sisusb->wait_q,
0243 (!(sisusb->urbstatus[index] & SU_URB_BUSY)),
0244 timeout);
0245 if (sisusb->urbstatus[index] & SU_URB_BUSY) {
0246
0247 usb_kill_urb(urb);
0248 retval = -ETIMEDOUT;
0249 } else {
0250
0251 retval = urb->status;
0252 byteswritten = urb->actual_length;
0253 }
0254 }
0255
0256 if (actual_length)
0257 *actual_length = byteswritten;
0258
0259 return retval;
0260 }
0261
0262
0263
0264
0265
0266 static void sisusb_bulk_completein(struct urb *urb)
0267 {
0268 struct sisusb_usb_data *sisusb = urb->context;
0269
0270 if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
0271 return;
0272
0273 sisusb->completein = 1;
0274 wake_up(&sisusb->wait_q);
0275 }
0276
0277 static int sisusb_bulkin_msg(struct sisusb_usb_data *sisusb,
0278 unsigned int pipe, void *data, int len,
0279 int *actual_length, int timeout, unsigned int tflags)
0280 {
0281 struct urb *urb = sisusb->sisurbin;
0282 int retval, readbytes = 0;
0283
0284 urb->transfer_flags = 0;
0285
0286 usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
0287 sisusb_bulk_completein, sisusb);
0288
0289 urb->transfer_flags |= tflags;
0290 urb->actual_length = 0;
0291
0292 sisusb->completein = 0;
0293 retval = usb_submit_urb(urb, GFP_KERNEL);
0294 if (retval == 0) {
0295 wait_event_timeout(sisusb->wait_q, sisusb->completein, timeout);
0296 if (!sisusb->completein) {
0297
0298 usb_kill_urb(urb);
0299 retval = -ETIMEDOUT;
0300 } else {
0301
0302 retval = urb->status;
0303 readbytes = urb->actual_length;
0304 }
0305 }
0306
0307 if (actual_length)
0308 *actual_length = readbytes;
0309
0310 return retval;
0311 }
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329 static int sisusb_send_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
0330 char *kernbuffer, const char __user *userbuffer, int index,
0331 ssize_t *bytes_written, unsigned int tflags, int async)
0332 {
0333 int result = 0, retry, count = len;
0334 int passsize, thispass, transferred_len = 0;
0335 int fromuser = (userbuffer != NULL) ? 1 : 0;
0336 int fromkern = (kernbuffer != NULL) ? 1 : 0;
0337 unsigned int pipe;
0338 char *buffer;
0339
0340 (*bytes_written) = 0;
0341
0342
0343 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
0344 return -ENODEV;
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354 if (fromuser || fromkern)
0355 index = -1;
0356 else if (len > sisusb->obufsize)
0357 async = 0;
0358
0359 pipe = usb_sndbulkpipe(sisusb->sisusb_dev, ep);
0360
0361 do {
0362 passsize = thispass = (sisusb->obufsize < count) ?
0363 sisusb->obufsize : count;
0364
0365 if (index < 0)
0366 index = sisusb_get_free_outbuf(sisusb);
0367
0368 if (index < 0)
0369 return -EIO;
0370
0371 buffer = sisusb->obuf[index];
0372
0373 if (fromuser) {
0374
0375 if (copy_from_user(buffer, userbuffer, passsize))
0376 return -EFAULT;
0377
0378 userbuffer += passsize;
0379
0380 } else if (fromkern) {
0381
0382 memcpy(buffer, kernbuffer, passsize);
0383 kernbuffer += passsize;
0384
0385 }
0386
0387 retry = 5;
0388 while (thispass) {
0389
0390 if (!sisusb->sisusb_dev)
0391 return -ENODEV;
0392
0393 result = sisusb_bulkout_msg(sisusb, index, pipe,
0394 buffer, thispass, &transferred_len,
0395 async ? 0 : 5 * HZ, tflags);
0396
0397 if (result == -ETIMEDOUT) {
0398
0399
0400 if (!retry--)
0401 return -ETIME;
0402
0403 continue;
0404 }
0405
0406 if ((result == 0) && !async && transferred_len) {
0407
0408 thispass -= transferred_len;
0409 buffer += transferred_len;
0410
0411 } else
0412 break;
0413 }
0414
0415 if (result)
0416 return result;
0417
0418 (*bytes_written) += passsize;
0419 count -= passsize;
0420
0421
0422 if (fromuser || fromkern)
0423 index = -1;
0424
0425 } while (count > 0);
0426
0427 if (async) {
0428 #ifdef SISUSB_DONTSYNC
0429 (*bytes_written) = len;
0430
0431 #else
0432 sisusb_wait_all_out_complete(sisusb);
0433 (*bytes_written) = transferred_len;
0434
0435 #endif
0436 }
0437
0438 return ((*bytes_written) == len) ? 0 : -EIO;
0439 }
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450 static int sisusb_recv_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
0451 void *kernbuffer, char __user *userbuffer, ssize_t *bytes_read,
0452 unsigned int tflags)
0453 {
0454 int result = 0, retry, count = len;
0455 int bufsize, thispass, transferred_len;
0456 unsigned int pipe;
0457 char *buffer;
0458
0459 (*bytes_read) = 0;
0460
0461
0462 if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
0463 return -ENODEV;
0464
0465 pipe = usb_rcvbulkpipe(sisusb->sisusb_dev, ep);
0466 buffer = sisusb->ibuf;
0467 bufsize = sisusb->ibufsize;
0468
0469 retry = 5;
0470
0471 #ifdef SISUSB_DONTSYNC
0472 if (!(sisusb_wait_all_out_complete(sisusb)))
0473 return -EIO;
0474 #endif
0475
0476 while (count > 0) {
0477
0478 if (!sisusb->sisusb_dev)
0479 return -ENODEV;
0480
0481 thispass = (bufsize < count) ? bufsize : count;
0482
0483 result = sisusb_bulkin_msg(sisusb, pipe, buffer, thispass,
0484 &transferred_len, 5 * HZ, tflags);
0485
0486 if (transferred_len)
0487 thispass = transferred_len;
0488
0489 else if (result == -ETIMEDOUT) {
0490
0491 if (!retry--)
0492 return -ETIME;
0493
0494 continue;
0495
0496 } else
0497 return -EIO;
0498
0499
0500 if (thispass) {
0501
0502 (*bytes_read) += thispass;
0503 count -= thispass;
0504
0505 if (userbuffer) {
0506
0507 if (copy_to_user(userbuffer, buffer, thispass))
0508 return -EFAULT;
0509
0510 userbuffer += thispass;
0511
0512 } else {
0513
0514 memcpy(kernbuffer, buffer, thispass);
0515 kernbuffer += thispass;
0516
0517 }
0518
0519 }
0520
0521 }
0522
0523 return ((*bytes_read) == len) ? 0 : -EIO;
0524 }
0525
0526 static int sisusb_send_packet(struct sisusb_usb_data *sisusb, int len,
0527 struct sisusb_packet *packet)
0528 {
0529 int ret;
0530 ssize_t bytes_transferred = 0;
0531 __le32 tmp;
0532
0533 if (len == 6)
0534 packet->data = 0;
0535
0536 #ifdef SISUSB_DONTSYNC
0537 if (!(sisusb_wait_all_out_complete(sisusb)))
0538 return 1;
0539 #endif
0540
0541
0542 SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
0543
0544
0545 ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_OUT, len,
0546 (char *)packet, NULL, 0, &bytes_transferred, 0, 0);
0547
0548 if ((ret == 0) && (len == 6)) {
0549
0550
0551
0552
0553 ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_GFX_IN, 4,
0554 (char *)&tmp, NULL, &bytes_transferred, 0);
0555
0556 packet->data = le32_to_cpu(tmp);
0557 }
0558
0559 return ret;
0560 }
0561
0562 static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
0563 struct sisusb_packet *packet, unsigned int tflags)
0564 {
0565 int ret;
0566 ssize_t bytes_transferred = 0;
0567 __le32 tmp;
0568
0569 if (len == 6)
0570 packet->data = 0;
0571
0572 #ifdef SISUSB_DONTSYNC
0573 if (!(sisusb_wait_all_out_complete(sisusb)))
0574 return 1;
0575 #endif
0576
0577
0578 SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
0579
0580
0581 ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_BRIDGE_OUT, len,
0582 (char *)packet, NULL, 0, &bytes_transferred, tflags, 0);
0583
0584 if ((ret == 0) && (len == 6)) {
0585
0586
0587
0588
0589 ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_BRIDGE_IN, 4,
0590 (char *)&tmp, NULL, &bytes_transferred, 0);
0591
0592 packet->data = le32_to_cpu(tmp);
0593 }
0594
0595 return ret;
0596 }
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610 static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,
0611 u32 addr, u8 data)
0612 {
0613 struct sisusb_packet packet;
0614
0615 packet.header = (1 << (addr & 3)) | (type << 6);
0616 packet.address = addr & ~3;
0617 packet.data = data << ((addr & 3) << 3);
0618 return sisusb_send_packet(sisusb, 10, &packet);
0619 }
0620
0621 static int sisusb_write_memio_word(struct sisusb_usb_data *sisusb, int type,
0622 u32 addr, u16 data)
0623 {
0624 struct sisusb_packet packet;
0625 int ret = 0;
0626
0627 packet.address = addr & ~3;
0628
0629 switch (addr & 3) {
0630 case 0:
0631 packet.header = (type << 6) | 0x0003;
0632 packet.data = (u32)data;
0633 ret = sisusb_send_packet(sisusb, 10, &packet);
0634 break;
0635 case 1:
0636 packet.header = (type << 6) | 0x0006;
0637 packet.data = (u32)data << 8;
0638 ret = sisusb_send_packet(sisusb, 10, &packet);
0639 break;
0640 case 2:
0641 packet.header = (type << 6) | 0x000c;
0642 packet.data = (u32)data << 16;
0643 ret = sisusb_send_packet(sisusb, 10, &packet);
0644 break;
0645 case 3:
0646 packet.header = (type << 6) | 0x0008;
0647 packet.data = (u32)data << 24;
0648 ret = sisusb_send_packet(sisusb, 10, &packet);
0649 packet.header = (type << 6) | 0x0001;
0650 packet.address = (addr & ~3) + 4;
0651 packet.data = (u32)data >> 8;
0652 ret |= sisusb_send_packet(sisusb, 10, &packet);
0653 }
0654
0655 return ret;
0656 }
0657
0658 static int sisusb_write_memio_24bit(struct sisusb_usb_data *sisusb, int type,
0659 u32 addr, u32 data)
0660 {
0661 struct sisusb_packet packet;
0662 int ret = 0;
0663
0664 packet.address = addr & ~3;
0665
0666 switch (addr & 3) {
0667 case 0:
0668 packet.header = (type << 6) | 0x0007;
0669 packet.data = data & 0x00ffffff;
0670 ret = sisusb_send_packet(sisusb, 10, &packet);
0671 break;
0672 case 1:
0673 packet.header = (type << 6) | 0x000e;
0674 packet.data = data << 8;
0675 ret = sisusb_send_packet(sisusb, 10, &packet);
0676 break;
0677 case 2:
0678 packet.header = (type << 6) | 0x000c;
0679 packet.data = data << 16;
0680 ret = sisusb_send_packet(sisusb, 10, &packet);
0681 packet.header = (type << 6) | 0x0001;
0682 packet.address = (addr & ~3) + 4;
0683 packet.data = (data >> 16) & 0x00ff;
0684 ret |= sisusb_send_packet(sisusb, 10, &packet);
0685 break;
0686 case 3:
0687 packet.header = (type << 6) | 0x0008;
0688 packet.data = data << 24;
0689 ret = sisusb_send_packet(sisusb, 10, &packet);
0690 packet.header = (type << 6) | 0x0003;
0691 packet.address = (addr & ~3) + 4;
0692 packet.data = (data >> 8) & 0xffff;
0693 ret |= sisusb_send_packet(sisusb, 10, &packet);
0694 }
0695
0696 return ret;
0697 }
0698
0699 static int sisusb_write_memio_long(struct sisusb_usb_data *sisusb, int type,
0700 u32 addr, u32 data)
0701 {
0702 struct sisusb_packet packet;
0703 int ret = 0;
0704
0705 packet.address = addr & ~3;
0706
0707 switch (addr & 3) {
0708 case 0:
0709 packet.header = (type << 6) | 0x000f;
0710 packet.data = data;
0711 ret = sisusb_send_packet(sisusb, 10, &packet);
0712 break;
0713 case 1:
0714 packet.header = (type << 6) | 0x000e;
0715 packet.data = data << 8;
0716 ret = sisusb_send_packet(sisusb, 10, &packet);
0717 packet.header = (type << 6) | 0x0001;
0718 packet.address = (addr & ~3) + 4;
0719 packet.data = data >> 24;
0720 ret |= sisusb_send_packet(sisusb, 10, &packet);
0721 break;
0722 case 2:
0723 packet.header = (type << 6) | 0x000c;
0724 packet.data = data << 16;
0725 ret = sisusb_send_packet(sisusb, 10, &packet);
0726 packet.header = (type << 6) | 0x0003;
0727 packet.address = (addr & ~3) + 4;
0728 packet.data = data >> 16;
0729 ret |= sisusb_send_packet(sisusb, 10, &packet);
0730 break;
0731 case 3:
0732 packet.header = (type << 6) | 0x0008;
0733 packet.data = data << 24;
0734 ret = sisusb_send_packet(sisusb, 10, &packet);
0735 packet.header = (type << 6) | 0x0007;
0736 packet.address = (addr & ~3) + 4;
0737 packet.data = data >> 8;
0738 ret |= sisusb_send_packet(sisusb, 10, &packet);
0739 }
0740
0741 return ret;
0742 }
0743
0744
0745
0746
0747
0748
0749
0750
0751
0752
0753
0754 static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
0755 char *kernbuffer, int length, const char __user *userbuffer,
0756 int index, ssize_t *bytes_written)
0757 {
0758 struct sisusb_packet packet;
0759 int ret = 0;
0760 static int msgcount;
0761 u8 swap8, fromkern = kernbuffer ? 1 : 0;
0762 u16 swap16;
0763 u32 swap32, flag = (length >> 28) & 1;
0764 u8 buf[4];
0765
0766
0767
0768
0769 if (!fromkern && !userbuffer)
0770 kernbuffer = sisusb->obuf[index];
0771
0772 (*bytes_written = 0);
0773
0774 length &= 0x00ffffff;
0775
0776 while (length) {
0777 switch (length) {
0778 case 1:
0779 if (userbuffer) {
0780 if (get_user(swap8, (u8 __user *)userbuffer))
0781 return -EFAULT;
0782 } else
0783 swap8 = kernbuffer[0];
0784
0785 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM,
0786 addr, swap8);
0787
0788 if (!ret)
0789 (*bytes_written)++;
0790
0791 return ret;
0792
0793 case 2:
0794 if (userbuffer) {
0795 if (get_user(swap16, (u16 __user *)userbuffer))
0796 return -EFAULT;
0797 } else
0798 swap16 = *((u16 *)kernbuffer);
0799
0800 ret = sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
0801 addr, swap16);
0802
0803 if (!ret)
0804 (*bytes_written) += 2;
0805
0806 return ret;
0807
0808 case 3:
0809 if (userbuffer) {
0810 if (copy_from_user(&buf, userbuffer, 3))
0811 return -EFAULT;
0812 #ifdef __BIG_ENDIAN
0813 swap32 = (buf[0] << 16) |
0814 (buf[1] << 8) |
0815 buf[2];
0816 #else
0817 swap32 = (buf[2] << 16) |
0818 (buf[1] << 8) |
0819 buf[0];
0820 #endif
0821 } else
0822 #ifdef __BIG_ENDIAN
0823 swap32 = (kernbuffer[0] << 16) |
0824 (kernbuffer[1] << 8) |
0825 kernbuffer[2];
0826 #else
0827 swap32 = (kernbuffer[2] << 16) |
0828 (kernbuffer[1] << 8) |
0829 kernbuffer[0];
0830 #endif
0831
0832 ret = sisusb_write_memio_24bit(sisusb, SISUSB_TYPE_MEM,
0833 addr, swap32);
0834
0835 if (!ret)
0836 (*bytes_written) += 3;
0837
0838 return ret;
0839
0840 case 4:
0841 if (userbuffer) {
0842 if (get_user(swap32, (u32 __user *)userbuffer))
0843 return -EFAULT;
0844 } else
0845 swap32 = *((u32 *)kernbuffer);
0846
0847 ret = sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM,
0848 addr, swap32);
0849 if (!ret)
0850 (*bytes_written) += 4;
0851
0852 return ret;
0853
0854 default:
0855 if ((length & ~3) > 0x10000) {
0856
0857 packet.header = 0x001f;
0858 packet.address = 0x000001d4;
0859 packet.data = addr;
0860 ret = sisusb_send_bridge_packet(sisusb, 10,
0861 &packet, 0);
0862 packet.header = 0x001f;
0863 packet.address = 0x000001d0;
0864 packet.data = (length & ~3);
0865 ret |= sisusb_send_bridge_packet(sisusb, 10,
0866 &packet, 0);
0867 packet.header = 0x001f;
0868 packet.address = 0x000001c0;
0869 packet.data = flag | 0x16;
0870 ret |= sisusb_send_bridge_packet(sisusb, 10,
0871 &packet, 0);
0872 if (userbuffer) {
0873 ret |= sisusb_send_bulk_msg(sisusb,
0874 SISUSB_EP_GFX_LBULK_OUT,
0875 (length & ~3),
0876 NULL, userbuffer, 0,
0877 bytes_written, 0, 1);
0878 userbuffer += (*bytes_written);
0879 } else if (fromkern) {
0880 ret |= sisusb_send_bulk_msg(sisusb,
0881 SISUSB_EP_GFX_LBULK_OUT,
0882 (length & ~3),
0883 kernbuffer, NULL, 0,
0884 bytes_written, 0, 1);
0885 kernbuffer += (*bytes_written);
0886 } else {
0887 ret |= sisusb_send_bulk_msg(sisusb,
0888 SISUSB_EP_GFX_LBULK_OUT,
0889 (length & ~3),
0890 NULL, NULL, index,
0891 bytes_written, 0, 1);
0892 kernbuffer += ((*bytes_written) &
0893 (sisusb->obufsize-1));
0894 }
0895
0896 } else {
0897
0898 packet.header = 0x001f;
0899 packet.address = 0x00000194;
0900 packet.data = addr;
0901 ret = sisusb_send_bridge_packet(sisusb, 10,
0902 &packet, 0);
0903 packet.header = 0x001f;
0904 packet.address = 0x00000190;
0905 packet.data = (length & ~3);
0906 ret |= sisusb_send_bridge_packet(sisusb, 10,
0907 &packet, 0);
0908 if (sisusb->flagb0 != 0x16) {
0909 packet.header = 0x001f;
0910 packet.address = 0x00000180;
0911 packet.data = flag | 0x16;
0912 ret |= sisusb_send_bridge_packet(sisusb,
0913 10, &packet, 0);
0914 sisusb->flagb0 = 0x16;
0915 }
0916 if (userbuffer) {
0917 ret |= sisusb_send_bulk_msg(sisusb,
0918 SISUSB_EP_GFX_BULK_OUT,
0919 (length & ~3),
0920 NULL, userbuffer, 0,
0921 bytes_written, 0, 1);
0922 userbuffer += (*bytes_written);
0923 } else if (fromkern) {
0924 ret |= sisusb_send_bulk_msg(sisusb,
0925 SISUSB_EP_GFX_BULK_OUT,
0926 (length & ~3),
0927 kernbuffer, NULL, 0,
0928 bytes_written, 0, 1);
0929 kernbuffer += (*bytes_written);
0930 } else {
0931 ret |= sisusb_send_bulk_msg(sisusb,
0932 SISUSB_EP_GFX_BULK_OUT,
0933 (length & ~3),
0934 NULL, NULL, index,
0935 bytes_written, 0, 1);
0936 kernbuffer += ((*bytes_written) &
0937 (sisusb->obufsize-1));
0938 }
0939 }
0940 if (ret) {
0941 msgcount++;
0942 if (msgcount < 500)
0943 dev_err(&sisusb->sisusb_dev->dev,
0944 "Wrote %zd of %d bytes, error %d\n",
0945 *bytes_written, length,
0946 ret);
0947 else if (msgcount == 500)
0948 dev_err(&sisusb->sisusb_dev->dev,
0949 "Too many errors, logging stopped\n");
0950 }
0951 addr += (*bytes_written);
0952 length -= (*bytes_written);
0953 }
0954
0955 if (ret)
0956 break;
0957
0958 }
0959
0960 return ret ? -EIO : 0;
0961 }
0962
0963
0964
0965
0966
0967 static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
0968 u32 addr, u8 *data)
0969 {
0970 struct sisusb_packet packet;
0971 int ret;
0972
0973 CLEARPACKET(&packet);
0974 packet.header = (1 << (addr & 3)) | (type << 6);
0975 packet.address = addr & ~3;
0976 ret = sisusb_send_packet(sisusb, 6, &packet);
0977 *data = (u8)(packet.data >> ((addr & 3) << 3));
0978 return ret;
0979 }
0980
0981 static int sisusb_read_memio_word(struct sisusb_usb_data *sisusb, int type,
0982 u32 addr, u16 *data)
0983 {
0984 struct sisusb_packet packet;
0985 int ret = 0;
0986
0987 CLEARPACKET(&packet);
0988
0989 packet.address = addr & ~3;
0990
0991 switch (addr & 3) {
0992 case 0:
0993 packet.header = (type << 6) | 0x0003;
0994 ret = sisusb_send_packet(sisusb, 6, &packet);
0995 *data = (u16)(packet.data);
0996 break;
0997 case 1:
0998 packet.header = (type << 6) | 0x0006;
0999 ret = sisusb_send_packet(sisusb, 6, &packet);
1000 *data = (u16)(packet.data >> 8);
1001 break;
1002 case 2:
1003 packet.header = (type << 6) | 0x000c;
1004 ret = sisusb_send_packet(sisusb, 6, &packet);
1005 *data = (u16)(packet.data >> 16);
1006 break;
1007 case 3:
1008 packet.header = (type << 6) | 0x0008;
1009 ret = sisusb_send_packet(sisusb, 6, &packet);
1010 *data = (u16)(packet.data >> 24);
1011 packet.header = (type << 6) | 0x0001;
1012 packet.address = (addr & ~3) + 4;
1013 ret |= sisusb_send_packet(sisusb, 6, &packet);
1014 *data |= (u16)(packet.data << 8);
1015 }
1016
1017 return ret;
1018 }
1019
1020 static int sisusb_read_memio_24bit(struct sisusb_usb_data *sisusb, int type,
1021 u32 addr, u32 *data)
1022 {
1023 struct sisusb_packet packet;
1024 int ret = 0;
1025
1026 packet.address = addr & ~3;
1027
1028 switch (addr & 3) {
1029 case 0:
1030 packet.header = (type << 6) | 0x0007;
1031 ret = sisusb_send_packet(sisusb, 6, &packet);
1032 *data = packet.data & 0x00ffffff;
1033 break;
1034 case 1:
1035 packet.header = (type << 6) | 0x000e;
1036 ret = sisusb_send_packet(sisusb, 6, &packet);
1037 *data = packet.data >> 8;
1038 break;
1039 case 2:
1040 packet.header = (type << 6) | 0x000c;
1041 ret = sisusb_send_packet(sisusb, 6, &packet);
1042 *data = packet.data >> 16;
1043 packet.header = (type << 6) | 0x0001;
1044 packet.address = (addr & ~3) + 4;
1045 ret |= sisusb_send_packet(sisusb, 6, &packet);
1046 *data |= ((packet.data & 0xff) << 16);
1047 break;
1048 case 3:
1049 packet.header = (type << 6) | 0x0008;
1050 ret = sisusb_send_packet(sisusb, 6, &packet);
1051 *data = packet.data >> 24;
1052 packet.header = (type << 6) | 0x0003;
1053 packet.address = (addr & ~3) + 4;
1054 ret |= sisusb_send_packet(sisusb, 6, &packet);
1055 *data |= ((packet.data & 0xffff) << 8);
1056 }
1057
1058 return ret;
1059 }
1060
1061 static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type,
1062 u32 addr, u32 *data)
1063 {
1064 struct sisusb_packet packet;
1065 int ret = 0;
1066
1067 packet.address = addr & ~3;
1068
1069 switch (addr & 3) {
1070 case 0:
1071 packet.header = (type << 6) | 0x000f;
1072 ret = sisusb_send_packet(sisusb, 6, &packet);
1073 *data = packet.data;
1074 break;
1075 case 1:
1076 packet.header = (type << 6) | 0x000e;
1077 ret = sisusb_send_packet(sisusb, 6, &packet);
1078 *data = packet.data >> 8;
1079 packet.header = (type << 6) | 0x0001;
1080 packet.address = (addr & ~3) + 4;
1081 ret |= sisusb_send_packet(sisusb, 6, &packet);
1082 *data |= (packet.data << 24);
1083 break;
1084 case 2:
1085 packet.header = (type << 6) | 0x000c;
1086 ret = sisusb_send_packet(sisusb, 6, &packet);
1087 *data = packet.data >> 16;
1088 packet.header = (type << 6) | 0x0003;
1089 packet.address = (addr & ~3) + 4;
1090 ret |= sisusb_send_packet(sisusb, 6, &packet);
1091 *data |= (packet.data << 16);
1092 break;
1093 case 3:
1094 packet.header = (type << 6) | 0x0008;
1095 ret = sisusb_send_packet(sisusb, 6, &packet);
1096 *data = packet.data >> 24;
1097 packet.header = (type << 6) | 0x0007;
1098 packet.address = (addr & ~3) + 4;
1099 ret |= sisusb_send_packet(sisusb, 6, &packet);
1100 *data |= (packet.data << 8);
1101 }
1102
1103 return ret;
1104 }
1105
1106 static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1107 char *kernbuffer, int length, char __user *userbuffer,
1108 ssize_t *bytes_read)
1109 {
1110 int ret = 0;
1111 char buf[4];
1112 u16 swap16;
1113 u32 swap32;
1114
1115 (*bytes_read = 0);
1116
1117 length &= 0x00ffffff;
1118
1119 while (length) {
1120 switch (length) {
1121 case 1:
1122 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM,
1123 addr, &buf[0]);
1124 if (!ret) {
1125 (*bytes_read)++;
1126 if (userbuffer) {
1127 if (put_user(buf[0], (u8 __user *)userbuffer))
1128 return -EFAULT;
1129 } else
1130 kernbuffer[0] = buf[0];
1131 }
1132 return ret;
1133
1134 case 2:
1135 ret |= sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM,
1136 addr, &swap16);
1137 if (!ret) {
1138 (*bytes_read) += 2;
1139 if (userbuffer) {
1140 if (put_user(swap16, (u16 __user *)userbuffer))
1141 return -EFAULT;
1142 } else {
1143 *((u16 *)kernbuffer) = swap16;
1144 }
1145 }
1146 return ret;
1147
1148 case 3:
1149 ret |= sisusb_read_memio_24bit(sisusb, SISUSB_TYPE_MEM,
1150 addr, &swap32);
1151 if (!ret) {
1152 (*bytes_read) += 3;
1153 #ifdef __BIG_ENDIAN
1154 buf[0] = (swap32 >> 16) & 0xff;
1155 buf[1] = (swap32 >> 8) & 0xff;
1156 buf[2] = swap32 & 0xff;
1157 #else
1158 buf[2] = (swap32 >> 16) & 0xff;
1159 buf[1] = (swap32 >> 8) & 0xff;
1160 buf[0] = swap32 & 0xff;
1161 #endif
1162 if (userbuffer) {
1163 if (copy_to_user(userbuffer,
1164 &buf[0], 3))
1165 return -EFAULT;
1166 } else {
1167 kernbuffer[0] = buf[0];
1168 kernbuffer[1] = buf[1];
1169 kernbuffer[2] = buf[2];
1170 }
1171 }
1172 return ret;
1173
1174 default:
1175 ret |= sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM,
1176 addr, &swap32);
1177 if (!ret) {
1178 (*bytes_read) += 4;
1179 if (userbuffer) {
1180 if (put_user(swap32, (u32 __user *)userbuffer))
1181 return -EFAULT;
1182
1183 userbuffer += 4;
1184 } else {
1185 *((u32 *)kernbuffer) = swap32;
1186 kernbuffer += 4;
1187 }
1188 addr += 4;
1189 length -= 4;
1190 }
1191 }
1192 if (ret)
1193 break;
1194 }
1195
1196 return ret;
1197 }
1198
1199
1200
1201 #ifdef CONFIG_USB_SISUSBVGA_CON
1202 int sisusb_setreg(struct sisusb_usb_data *sisusb, u32 port, u8 data)
1203 {
1204 return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1205 }
1206
1207 int sisusb_getreg(struct sisusb_usb_data *sisusb, u32 port, u8 *data)
1208 {
1209 return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1210 }
1211 #endif
1212
1213 int sisusb_setidxreg(struct sisusb_usb_data *sisusb, u32 port,
1214 u8 index, u8 data)
1215 {
1216 int ret;
1217
1218 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1219 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1220 return ret;
1221 }
1222
1223 int sisusb_getidxreg(struct sisusb_usb_data *sisusb, u32 port,
1224 u8 index, u8 *data)
1225 {
1226 int ret;
1227
1228 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
1229 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
1230 return ret;
1231 }
1232
1233 int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, u32 port, u8 idx,
1234 u8 myand, u8 myor)
1235 {
1236 int ret;
1237 u8 tmp;
1238
1239 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1240 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1241 tmp &= myand;
1242 tmp |= myor;
1243 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1244 return ret;
1245 }
1246
1247 static int sisusb_setidxregmask(struct sisusb_usb_data *sisusb,
1248 u32 port, u8 idx, u8 data, u8 mask)
1249 {
1250 int ret;
1251 u8 tmp;
1252
1253 ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
1254 ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
1255 tmp &= ~(mask);
1256 tmp |= (data & mask);
1257 ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
1258 return ret;
1259 }
1260
1261 int sisusb_setidxregor(struct sisusb_usb_data *sisusb, u32 port,
1262 u8 index, u8 myor)
1263 {
1264 return sisusb_setidxregandor(sisusb, port, index, 0xff, myor);
1265 }
1266
1267 int sisusb_setidxregand(struct sisusb_usb_data *sisusb, u32 port,
1268 u8 idx, u8 myand)
1269 {
1270 return sisusb_setidxregandor(sisusb, port, idx, myand, 0x00);
1271 }
1272
1273
1274
1275 #ifdef CONFIG_USB_SISUSBVGA_CON
1276 int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data)
1277 {
1278 return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data);
1279 }
1280
1281 int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)
1282 {
1283 return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data);
1284 }
1285
1286 int sisusb_copy_memory(struct sisusb_usb_data *sisusb, u8 *src,
1287 u32 dest, int length)
1288 {
1289 size_t dummy;
1290
1291 return sisusb_write_mem_bulk(sisusb, dest, src, length,
1292 NULL, 0, &dummy);
1293 }
1294
1295 #ifdef SISUSBENDIANTEST
1296 static int sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
1297 u32 src, int length)
1298 {
1299 size_t dummy;
1300
1301 return sisusb_read_mem_bulk(sisusb, src, dest, length,
1302 NULL, &dummy);
1303 }
1304 #endif
1305 #endif
1306
1307 #ifdef SISUSBENDIANTEST
1308 static void sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
1309 {
1310 static u8 srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1311 char destbuffer[10];
1312 int i, j;
1313
1314 sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7);
1315
1316 for (i = 1; i <= 7; i++) {
1317 dev_dbg(&sisusb->sisusb_dev->dev,
1318 "sisusb: rwtest %d bytes\n", i);
1319 sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i);
1320 for (j = 0; j < i; j++) {
1321 dev_dbg(&sisusb->sisusb_dev->dev,
1322 "rwtest read[%d] = %x\n",
1323 j, destbuffer[j]);
1324 }
1325 }
1326 }
1327 #endif
1328
1329
1330
1331 static int sisusb_write_pci_config(struct sisusb_usb_data *sisusb,
1332 int regnum, u32 data)
1333 {
1334 struct sisusb_packet packet;
1335
1336 packet.header = 0x008f;
1337 packet.address = regnum | 0x10000;
1338 packet.data = data;
1339 return sisusb_send_packet(sisusb, 10, &packet);
1340 }
1341
1342 static int sisusb_read_pci_config(struct sisusb_usb_data *sisusb,
1343 int regnum, u32 *data)
1344 {
1345 struct sisusb_packet packet;
1346 int ret;
1347
1348 packet.header = 0x008f;
1349 packet.address = (u32)regnum | 0x10000;
1350 ret = sisusb_send_packet(sisusb, 6, &packet);
1351 *data = packet.data;
1352 return ret;
1353 }
1354
1355
1356
1357 static int sisusb_clear_vram(struct sisusb_usb_data *sisusb,
1358 u32 address, int length)
1359 {
1360 int ret, i;
1361 ssize_t j;
1362
1363 if (address < sisusb->vrambase)
1364 return 1;
1365
1366 if (address >= sisusb->vrambase + sisusb->vramsize)
1367 return 1;
1368
1369 if (address + length > sisusb->vrambase + sisusb->vramsize)
1370 length = sisusb->vrambase + sisusb->vramsize - address;
1371
1372 if (length <= 0)
1373 return 0;
1374
1375
1376 i = sisusb_alloc_outbuf(sisusb);
1377 if (i < 0)
1378 return -EBUSY;
1379
1380 memset(sisusb->obuf[i], 0, sisusb->obufsize);
1381
1382
1383
1384
1385 ret = sisusb_write_mem_bulk(sisusb, address, NULL, length, NULL, i, &j);
1386
1387
1388 sisusb_free_outbuf(sisusb, i);
1389
1390 return ret;
1391 }
1392
1393
1394
1395
1396
1397
1398 #define GETREG(r, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1399 #define SETREG(r, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
1400 #define SETIREG(r, i, d) sisusb_setidxreg(sisusb, r, i, d)
1401 #define GETIREG(r, i, d) sisusb_getidxreg(sisusb, r, i, d)
1402 #define SETIREGOR(r, i, o) sisusb_setidxregor(sisusb, r, i, o)
1403 #define SETIREGAND(r, i, a) sisusb_setidxregand(sisusb, r, i, a)
1404 #define SETIREGANDOR(r, i, a, o) sisusb_setidxregandor(sisusb, r, i, a, o)
1405 #define READL(a, d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1406 #define WRITEL(a, d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
1407 #define READB(a, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1408 #define WRITEB(a, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
1409
1410 static int sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype)
1411 {
1412 int ret;
1413 u8 tmp8;
1414
1415 ret = GETIREG(SISSR, 0x16, &tmp8);
1416 if (ramtype <= 1) {
1417 tmp8 &= 0x3f;
1418 ret |= SETIREG(SISSR, 0x16, tmp8);
1419 tmp8 |= 0x80;
1420 ret |= SETIREG(SISSR, 0x16, tmp8);
1421 } else {
1422 tmp8 |= 0xc0;
1423 ret |= SETIREG(SISSR, 0x16, tmp8);
1424 tmp8 &= 0x0f;
1425 ret |= SETIREG(SISSR, 0x16, tmp8);
1426 tmp8 |= 0x80;
1427 ret |= SETIREG(SISSR, 0x16, tmp8);
1428 tmp8 &= 0x0f;
1429 ret |= SETIREG(SISSR, 0x16, tmp8);
1430 tmp8 |= 0xd0;
1431 ret |= SETIREG(SISSR, 0x16, tmp8);
1432 tmp8 &= 0x0f;
1433 ret |= SETIREG(SISSR, 0x16, tmp8);
1434 tmp8 |= 0xa0;
1435 ret |= SETIREG(SISSR, 0x16, tmp8);
1436 }
1437 return ret;
1438 }
1439
1440 static int sisusb_getbuswidth(struct sisusb_usb_data *sisusb,
1441 int *bw, int *chab)
1442 {
1443 int ret;
1444 u8 ramtype, done = 0;
1445 u32 t0, t1, t2, t3;
1446 u32 ramptr = SISUSB_PCI_MEMBASE;
1447
1448 ret = GETIREG(SISSR, 0x3a, &ramtype);
1449 ramtype &= 3;
1450
1451 ret |= SETIREG(SISSR, 0x13, 0x00);
1452
1453 if (ramtype <= 1) {
1454 ret |= SETIREG(SISSR, 0x14, 0x12);
1455 ret |= SETIREGAND(SISSR, 0x15, 0xef);
1456 } else {
1457 ret |= SETIREG(SISSR, 0x14, 0x02);
1458 }
1459
1460 ret |= sisusb_triggersr16(sisusb, ramtype);
1461 ret |= WRITEL(ramptr + 0, 0x01234567);
1462 ret |= WRITEL(ramptr + 4, 0x456789ab);
1463 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1464 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1465 ret |= WRITEL(ramptr + 16, 0x55555555);
1466 ret |= WRITEL(ramptr + 20, 0x55555555);
1467 ret |= WRITEL(ramptr + 24, 0xffffffff);
1468 ret |= WRITEL(ramptr + 28, 0xffffffff);
1469 ret |= READL(ramptr + 0, &t0);
1470 ret |= READL(ramptr + 4, &t1);
1471 ret |= READL(ramptr + 8, &t2);
1472 ret |= READL(ramptr + 12, &t3);
1473
1474 if (ramtype <= 1) {
1475
1476 *chab = 0; *bw = 64;
1477
1478 if ((t3 != 0xcdef0123) || (t2 != 0x89abcdef)) {
1479 if ((t1 == 0x456789ab) && (t0 == 0x01234567)) {
1480 *chab = 0; *bw = 64;
1481 ret |= SETIREGAND(SISSR, 0x14, 0xfd);
1482 }
1483 }
1484 if ((t1 != 0x456789ab) || (t0 != 0x01234567)) {
1485 *chab = 1; *bw = 64;
1486 ret |= SETIREGANDOR(SISSR, 0x14, 0xfc, 0x01);
1487
1488 ret |= sisusb_triggersr16(sisusb, ramtype);
1489 ret |= WRITEL(ramptr + 0, 0x89abcdef);
1490 ret |= WRITEL(ramptr + 4, 0xcdef0123);
1491 ret |= WRITEL(ramptr + 8, 0x55555555);
1492 ret |= WRITEL(ramptr + 12, 0x55555555);
1493 ret |= WRITEL(ramptr + 16, 0xaaaaaaaa);
1494 ret |= WRITEL(ramptr + 20, 0xaaaaaaaa);
1495 ret |= READL(ramptr + 4, &t1);
1496
1497 if (t1 != 0xcdef0123) {
1498 *bw = 32;
1499 ret |= SETIREGOR(SISSR, 0x15, 0x10);
1500 }
1501 }
1502
1503 } else {
1504
1505 *chab = 0; *bw = 64;
1506
1507 done = 0;
1508
1509 if (t1 == 0x456789ab) {
1510 if (t0 == 0x01234567) {
1511 *chab = 0; *bw = 64;
1512 done = 1;
1513 }
1514 } else {
1515 if (t0 == 0x01234567) {
1516 *chab = 0; *bw = 32;
1517 ret |= SETIREG(SISSR, 0x14, 0x00);
1518 done = 1;
1519 }
1520 }
1521
1522 if (!done) {
1523 ret |= SETIREG(SISSR, 0x14, 0x03);
1524 ret |= sisusb_triggersr16(sisusb, ramtype);
1525
1526 ret |= WRITEL(ramptr + 0, 0x01234567);
1527 ret |= WRITEL(ramptr + 4, 0x456789ab);
1528 ret |= WRITEL(ramptr + 8, 0x89abcdef);
1529 ret |= WRITEL(ramptr + 12, 0xcdef0123);
1530 ret |= WRITEL(ramptr + 16, 0x55555555);
1531 ret |= WRITEL(ramptr + 20, 0x55555555);
1532 ret |= WRITEL(ramptr + 24, 0xffffffff);
1533 ret |= WRITEL(ramptr + 28, 0xffffffff);
1534 ret |= READL(ramptr + 0, &t0);
1535 ret |= READL(ramptr + 4, &t1);
1536
1537 if (t1 == 0x456789ab) {
1538 if (t0 == 0x01234567) {
1539 *chab = 1; *bw = 64;
1540 return ret;
1541 }
1542 } else {
1543 if (t0 == 0x01234567) {
1544 *chab = 1; *bw = 32;
1545 ret |= SETIREG(SISSR, 0x14, 0x01);
1546 }
1547 }
1548 }
1549 }
1550 return ret;
1551 }
1552
1553 static int sisusb_verify_mclk(struct sisusb_usb_data *sisusb)
1554 {
1555 int ret = 0;
1556 u32 ramptr = SISUSB_PCI_MEMBASE;
1557 u8 tmp1, tmp2, i, j;
1558
1559 ret |= WRITEB(ramptr, 0xaa);
1560 ret |= WRITEB(ramptr + 16, 0x55);
1561 ret |= READB(ramptr, &tmp1);
1562 ret |= READB(ramptr + 16, &tmp2);
1563 if ((tmp1 != 0xaa) || (tmp2 != 0x55)) {
1564 for (i = 0, j = 16; i < 2; i++, j += 16) {
1565 ret |= GETIREG(SISSR, 0x21, &tmp1);
1566 ret |= SETIREGAND(SISSR, 0x21, (tmp1 & 0xfb));
1567 ret |= SETIREGOR(SISSR, 0x3c, 0x01);
1568 ret |= SETIREGAND(SISSR, 0x3c, 0xfe);
1569 ret |= SETIREG(SISSR, 0x21, tmp1);
1570 ret |= WRITEB(ramptr + 16 + j, j);
1571 ret |= READB(ramptr + 16 + j, &tmp1);
1572 if (tmp1 == j) {
1573 ret |= WRITEB(ramptr + j, j);
1574 break;
1575 }
1576 }
1577 }
1578 return ret;
1579 }
1580
1581 static int sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret,
1582 int index, u8 rankno, u8 chab, const u8 dramtype[][5], int bw)
1583 {
1584 int ret = 0, ranksize;
1585 u8 tmp;
1586
1587 *iret = 0;
1588
1589 if ((rankno == 2) && (dramtype[index][0] == 2))
1590 return ret;
1591
1592 ranksize = dramtype[index][3] / 2 * bw / 32;
1593
1594 if ((ranksize * rankno) > 128)
1595 return ret;
1596
1597 tmp = 0;
1598 while ((ranksize >>= 1) > 0)
1599 tmp += 0x10;
1600
1601 tmp |= ((rankno - 1) << 2);
1602 tmp |= ((bw / 64) & 0x02);
1603 tmp |= (chab & 0x01);
1604
1605 ret = SETIREG(SISSR, 0x14, tmp);
1606 ret |= sisusb_triggersr16(sisusb, 0);
1607
1608 *iret = 1;
1609
1610 return ret;
1611 }
1612
1613 static int sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret,
1614 u32 inc, int testn)
1615 {
1616 int ret = 0, i;
1617 u32 j, tmp;
1618
1619 *iret = 0;
1620
1621 for (i = 0, j = 0; i < testn; i++) {
1622 ret |= WRITEL(sisusb->vrambase + j, j);
1623 j += inc;
1624 }
1625
1626 for (i = 0, j = 0; i < testn; i++) {
1627 ret |= READL(sisusb->vrambase + j, &tmp);
1628 if (tmp != j)
1629 return ret;
1630
1631 j += inc;
1632 }
1633
1634 *iret = 1;
1635 return ret;
1636 }
1637
1638 static int sisusb_check_ranks(struct sisusb_usb_data *sisusb,
1639 int *iret, int rankno, int idx, int bw, const u8 rtype[][5])
1640 {
1641 int ret = 0, i, i2ret;
1642 u32 inc;
1643
1644 *iret = 0;
1645
1646 for (i = rankno; i >= 1; i--) {
1647 inc = 1 << (rtype[idx][2] + rtype[idx][1] + rtype[idx][0] +
1648 bw / 64 + i);
1649 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1650 if (!i2ret)
1651 return ret;
1652 }
1653
1654 inc = 1 << (rtype[idx][2] + bw / 64 + 2);
1655 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 4);
1656 if (!i2ret)
1657 return ret;
1658
1659 inc = 1 << (10 + bw / 64);
1660 ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
1661 if (!i2ret)
1662 return ret;
1663
1664 *iret = 1;
1665 return ret;
1666 }
1667
1668 static int sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret,
1669 int bw, int chab)
1670 {
1671 int ret = 0, i2ret = 0, i, j;
1672 static const u8 sdramtype[13][5] = {
1673 { 2, 12, 9, 64, 0x35 },
1674 { 1, 13, 9, 64, 0x44 },
1675 { 2, 12, 8, 32, 0x31 },
1676 { 2, 11, 9, 32, 0x25 },
1677 { 1, 12, 9, 32, 0x34 },
1678 { 1, 13, 8, 32, 0x40 },
1679 { 2, 11, 8, 16, 0x21 },
1680 { 1, 12, 8, 16, 0x30 },
1681 { 1, 11, 9, 16, 0x24 },
1682 { 1, 11, 8, 8, 0x20 },
1683 { 2, 9, 8, 4, 0x01 },
1684 { 1, 10, 8, 4, 0x10 },
1685 { 1, 9, 8, 2, 0x00 }
1686 };
1687
1688 *iret = 1;
1689
1690 for (i = 0; i < 13; i++) {
1691 ret |= SETIREGANDOR(SISSR, 0x13, 0x80, sdramtype[i][4]);
1692 for (j = 2; j > 0; j--) {
1693 ret |= sisusb_set_rank(sisusb, &i2ret, i, j, chab,
1694 sdramtype, bw);
1695 if (!i2ret)
1696 continue;
1697
1698 ret |= sisusb_check_ranks(sisusb, &i2ret, j, i, bw,
1699 sdramtype);
1700 if (i2ret) {
1701 *iret = 0;
1702 return ret;
1703 }
1704 }
1705 }
1706
1707 return ret;
1708 }
1709
1710 static int sisusb_setup_screen(struct sisusb_usb_data *sisusb,
1711 int clrall, int drwfr)
1712 {
1713 int ret = 0;
1714 u32 address;
1715 int i, length, modex, modey, bpp;
1716
1717 modex = 640; modey = 480; bpp = 2;
1718
1719 address = sisusb->vrambase;
1720
1721 if (clrall)
1722 length = sisusb->vramsize;
1723 else
1724 length = modex * bpp * modey;
1725
1726 ret = sisusb_clear_vram(sisusb, address, length);
1727
1728 if (!ret && drwfr) {
1729 for (i = 0; i < modex; i++) {
1730 address = sisusb->vrambase + (i * bpp);
1731 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1732 address, 0xf100);
1733 address += (modex * (modey-1) * bpp);
1734 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1735 address, 0xf100);
1736 }
1737 for (i = 0; i < modey; i++) {
1738 address = sisusb->vrambase + ((i * modex) * bpp);
1739 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1740 address, 0xf100);
1741 address += ((modex - 1) * bpp);
1742 ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
1743 address, 0xf100);
1744 }
1745 }
1746
1747 return ret;
1748 }
1749
1750 static void sisusb_set_default_mode(struct sisusb_usb_data *sisusb,
1751 int touchengines)
1752 {
1753 int i, j, modex, bpp, du;
1754 u8 sr31, cr63, tmp8;
1755 static const char attrdata[] = {
1756 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1757 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1758 0x01, 0x00, 0x00, 0x00
1759 };
1760 static const char crtcrdata[] = {
1761 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
1762 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1763 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3,
1764 0xff
1765 };
1766 static const char grcdata[] = {
1767 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
1768 0xff
1769 };
1770 static const char crtcdata[] = {
1771 0x5f, 0x4f, 0x4f, 0x83, 0x55, 0x81, 0x0b, 0x3e,
1772 0xe9, 0x8b, 0xdf, 0xe8, 0x0c, 0x00, 0x00, 0x05,
1773 0x00
1774 };
1775
1776 modex = 640; bpp = 2;
1777
1778 GETIREG(SISSR, 0x31, &sr31);
1779 GETIREG(SISCR, 0x63, &cr63);
1780 SETIREGOR(SISSR, 0x01, 0x20);
1781 SETIREG(SISCR, 0x63, cr63 & 0xbf);
1782 SETIREGOR(SISCR, 0x17, 0x80);
1783 SETIREGOR(SISSR, 0x1f, 0x04);
1784 SETIREGAND(SISSR, 0x07, 0xfb);
1785 SETIREG(SISSR, 0x00, 0x03);
1786 SETIREG(SISSR, 0x01, 0x21);
1787 SETIREG(SISSR, 0x02, 0x0f);
1788 SETIREG(SISSR, 0x03, 0x00);
1789 SETIREG(SISSR, 0x04, 0x0e);
1790 SETREG(SISMISCW, 0x23);
1791 for (i = 0; i <= 0x18; i++) {
1792 SETIREG(SISCR, i, crtcrdata[i]);
1793 }
1794 for (i = 0; i <= 0x13; i++) {
1795 GETREG(SISINPSTAT, &tmp8);
1796 SETREG(SISAR, i);
1797 SETREG(SISAR, attrdata[i]);
1798 }
1799 GETREG(SISINPSTAT, &tmp8);
1800 SETREG(SISAR, 0x14);
1801 SETREG(SISAR, 0x00);
1802 GETREG(SISINPSTAT, &tmp8);
1803 SETREG(SISAR, 0x20);
1804 GETREG(SISINPSTAT, &tmp8);
1805 for (i = 0; i <= 0x08; i++) {
1806 SETIREG(SISGR, i, grcdata[i]);
1807 }
1808 SETIREGAND(SISGR, 0x05, 0xbf);
1809 for (i = 0x0A; i <= 0x0E; i++) {
1810 SETIREG(SISSR, i, 0x00);
1811 }
1812 SETIREGAND(SISSR, 0x37, 0xfe);
1813 SETREG(SISMISCW, 0xef);
1814 SETIREG(SISCR, 0x11, 0x00);
1815 for (j = 0x00, i = 0; i <= 7; i++, j++)
1816 SETIREG(SISCR, j, crtcdata[i]);
1817
1818 for (j = 0x10; i <= 10; i++, j++)
1819 SETIREG(SISCR, j, crtcdata[i]);
1820
1821 for (j = 0x15; i <= 12; i++, j++)
1822 SETIREG(SISCR, j, crtcdata[i]);
1823
1824 for (j = 0x0A; i <= 15; i++, j++)
1825 SETIREG(SISSR, j, crtcdata[i]);
1826
1827 SETIREG(SISSR, 0x0E, (crtcdata[16] & 0xE0));
1828 SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5));
1829 SETIREG(SISCR, 0x14, 0x4f);
1830 du = (modex / 16) * (bpp * 2);
1831 SETIREGANDOR(SISSR, 0x0e, 0xf0, ((du >> 8) & 0x0f));
1832 SETIREG(SISCR, 0x13, (du & 0xff));
1833 du <<= 5;
1834 tmp8 = du >> 8;
1835 SETIREG(SISSR, 0x10, tmp8);
1836 SETIREG(SISSR, 0x31, 0x00);
1837 SETIREG(SISSR, 0x2b, 0x1b);
1838 SETIREG(SISSR, 0x2c, 0xe1);
1839 SETIREG(SISSR, 0x2d, 0x01);
1840 SETIREGAND(SISSR, 0x3d, 0xfe);
1841 SETIREG(SISSR, 0x08, 0xae);
1842 SETIREGAND(SISSR, 0x09, 0xf0);
1843 SETIREG(SISSR, 0x08, 0x34);
1844 SETIREGOR(SISSR, 0x3d, 0x01);
1845 SETIREGAND(SISSR, 0x1f, 0x3f);
1846 SETIREGANDOR(SISSR, 0x06, 0xc0, 0x0a);
1847 SETIREG(SISCR, 0x19, 0x00);
1848 SETIREGAND(SISCR, 0x1a, 0xfc);
1849 SETIREGAND(SISSR, 0x0f, 0xb7);
1850 SETIREGAND(SISSR, 0x31, 0xfb);
1851 SETIREGANDOR(SISSR, 0x21, 0x1f, 0xa0);
1852 SETIREGAND(SISSR, 0x32, 0xf3);
1853 SETIREGANDOR(SISSR, 0x07, 0xf8, 0x03);
1854 SETIREG(SISCR, 0x52, 0x6c);
1855
1856 SETIREG(SISCR, 0x0d, 0x00);
1857 SETIREG(SISCR, 0x0c, 0x00);
1858 SETIREG(SISSR, 0x0d, 0x00);
1859 SETIREGAND(SISSR, 0x37, 0xfe);
1860
1861 SETIREG(SISCR, 0x32, 0x20);
1862 SETIREGAND(SISSR, 0x01, 0xdf);
1863 SETIREG(SISCR, 0x63, (cr63 & 0xbf));
1864 SETIREG(SISSR, 0x31, (sr31 & 0xfb));
1865
1866 if (touchengines) {
1867 SETIREG(SISSR, 0x20, 0xa1);
1868 SETIREGOR(SISSR, 0x1e, 0x5a);
1869
1870 SETIREG(SISSR, 0x26, 0x01);
1871 SETIREG(SISSR, 0x27, 0x1f);
1872 SETIREG(SISSR, 0x26, 0x00);
1873 }
1874
1875 SETIREG(SISCR, 0x34, 0x44);
1876 }
1877
1878 static int sisusb_init_gfxcore(struct sisusb_usb_data *sisusb)
1879 {
1880 int ret = 0, i, j, bw, chab, iret, retry = 3;
1881 u8 tmp8, ramtype;
1882 u32 tmp32;
1883 static const char mclktable[] = {
1884 0x3b, 0x22, 0x01, 143,
1885 0x3b, 0x22, 0x01, 143,
1886 0x3b, 0x22, 0x01, 143,
1887 0x3b, 0x22, 0x01, 143
1888 };
1889 static const char eclktable[] = {
1890 0x3b, 0x22, 0x01, 143,
1891 0x3b, 0x22, 0x01, 143,
1892 0x3b, 0x22, 0x01, 143,
1893 0x3b, 0x22, 0x01, 143
1894 };
1895 static const char ramtypetable1[] = {
1896 0x00, 0x04, 0x60, 0x60,
1897 0x0f, 0x0f, 0x1f, 0x1f,
1898 0xba, 0xba, 0xba, 0xba,
1899 0xa9, 0xa9, 0xac, 0xac,
1900 0xa0, 0xa0, 0xa0, 0xa8,
1901 0x00, 0x00, 0x02, 0x02,
1902 0x30, 0x30, 0x40, 0x40
1903 };
1904 static const char ramtypetable2[] = {
1905 0x77, 0x77, 0x44, 0x44,
1906 0x77, 0x77, 0x44, 0x44,
1907 0x00, 0x00, 0x00, 0x00,
1908 0x5b, 0x5b, 0xab, 0xab,
1909 0x00, 0x00, 0xf0, 0xf8
1910 };
1911
1912 while (retry--) {
1913
1914
1915 ret = GETREG(SISVGAEN, &tmp8);
1916 ret |= SETREG(SISVGAEN, (tmp8 | 0x01));
1917
1918
1919 ret |= GETREG(SISMISCR, &tmp8);
1920 ret |= SETREG(SISMISCW, (tmp8 | 0x01));
1921
1922 if (ret)
1923 continue;
1924
1925
1926 ret |= SETIREGAND(SISCR, 0x5b, 0xdf);
1927 ret |= SETIREG(SISSR, 0x05, 0x86);
1928 ret |= SETIREGOR(SISSR, 0x20, 0x01);
1929
1930 ret |= SETREG(SISMISCW, 0x67);
1931
1932 for (i = 0x06; i <= 0x1f; i++)
1933 ret |= SETIREG(SISSR, i, 0x00);
1934
1935 for (i = 0x21; i <= 0x27; i++)
1936 ret |= SETIREG(SISSR, i, 0x00);
1937
1938 for (i = 0x31; i <= 0x3d; i++)
1939 ret |= SETIREG(SISSR, i, 0x00);
1940
1941 for (i = 0x12; i <= 0x1b; i++)
1942 ret |= SETIREG(SISSR, i, 0x00);
1943
1944 for (i = 0x79; i <= 0x7c; i++)
1945 ret |= SETIREG(SISCR, i, 0x00);
1946
1947 if (ret)
1948 continue;
1949
1950 ret |= SETIREG(SISCR, 0x63, 0x80);
1951
1952 ret |= GETIREG(SISSR, 0x3a, &ramtype);
1953 ramtype &= 0x03;
1954
1955 ret |= SETIREG(SISSR, 0x28, mclktable[ramtype * 4]);
1956 ret |= SETIREG(SISSR, 0x29, mclktable[(ramtype * 4) + 1]);
1957 ret |= SETIREG(SISSR, 0x2a, mclktable[(ramtype * 4) + 2]);
1958
1959 ret |= SETIREG(SISSR, 0x2e, eclktable[ramtype * 4]);
1960 ret |= SETIREG(SISSR, 0x2f, eclktable[(ramtype * 4) + 1]);
1961 ret |= SETIREG(SISSR, 0x30, eclktable[(ramtype * 4) + 2]);
1962
1963 ret |= SETIREG(SISSR, 0x07, 0x18);
1964 ret |= SETIREG(SISSR, 0x11, 0x0f);
1965
1966 if (ret)
1967 continue;
1968
1969 for (i = 0x15, j = 0; i <= 0x1b; i++, j++) {
1970 ret |= SETIREG(SISSR, i,
1971 ramtypetable1[(j*4) + ramtype]);
1972 }
1973 for (i = 0x40, j = 0; i <= 0x44; i++, j++) {
1974 ret |= SETIREG(SISCR, i,
1975 ramtypetable2[(j*4) + ramtype]);
1976 }
1977
1978 ret |= SETIREG(SISCR, 0x49, 0xaa);
1979
1980 ret |= SETIREG(SISSR, 0x1f, 0x00);
1981 ret |= SETIREG(SISSR, 0x20, 0xa0);
1982 ret |= SETIREG(SISSR, 0x23, 0xf6);
1983 ret |= SETIREG(SISSR, 0x24, 0x0d);
1984 ret |= SETIREG(SISSR, 0x25, 0x33);
1985
1986 ret |= SETIREG(SISSR, 0x11, 0x0f);
1987
1988 ret |= SETIREGOR(SISPART1, 0x2f, 0x01);
1989
1990 ret |= SETIREGAND(SISCAP, 0x3f, 0xef);
1991
1992 if (ret)
1993 continue;
1994
1995 ret |= SETIREG(SISPART1, 0x00, 0x00);
1996
1997 ret |= GETIREG(SISSR, 0x13, &tmp8);
1998 tmp8 >>= 4;
1999
2000 ret |= SETIREG(SISPART1, 0x02, 0x00);
2001 ret |= SETIREG(SISPART1, 0x2e, 0x08);
2002
2003 ret |= sisusb_read_pci_config(sisusb, 0x50, &tmp32);
2004 tmp32 &= 0x00f00000;
2005 tmp8 = (tmp32 == 0x100000) ? 0x33 : 0x03;
2006 ret |= SETIREG(SISSR, 0x25, tmp8);
2007 tmp8 = (tmp32 == 0x100000) ? 0xaa : 0x88;
2008 ret |= SETIREG(SISCR, 0x49, tmp8);
2009
2010 ret |= SETIREG(SISSR, 0x27, 0x1f);
2011 ret |= SETIREG(SISSR, 0x31, 0x00);
2012 ret |= SETIREG(SISSR, 0x32, 0x11);
2013 ret |= SETIREG(SISSR, 0x33, 0x00);
2014
2015 if (ret)
2016 continue;
2017
2018 ret |= SETIREG(SISCR, 0x83, 0x00);
2019
2020 sisusb_set_default_mode(sisusb, 0);
2021
2022 ret |= SETIREGAND(SISSR, 0x21, 0xdf);
2023 ret |= SETIREGOR(SISSR, 0x01, 0x20);
2024 ret |= SETIREGOR(SISSR, 0x16, 0x0f);
2025
2026 ret |= sisusb_triggersr16(sisusb, ramtype);
2027
2028
2029 ret |= SETIREGAND(SISSR, 0x17, 0xf8);
2030 ret |= SETIREGOR(SISSR, 0x19, 0x03);
2031
2032 ret |= sisusb_getbuswidth(sisusb, &bw, &chab);
2033 ret |= sisusb_verify_mclk(sisusb);
2034
2035 if (ramtype <= 1) {
2036 ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab);
2037 if (iret) {
2038 dev_err(&sisusb->sisusb_dev->dev,
2039 "RAM size detection failed, assuming 8MB video RAM\n");
2040 ret |= SETIREG(SISSR, 0x14, 0x31);
2041
2042 }
2043 } else {
2044 dev_err(&sisusb->sisusb_dev->dev,
2045 "DDR RAM device found, assuming 8MB video RAM\n");
2046 ret |= SETIREG(SISSR, 0x14, 0x31);
2047
2048 }
2049
2050
2051 ret |= SETIREG(SISSR, 0x16, ramtypetable1[4 + ramtype]);
2052 ret |= SETIREG(SISSR, 0x17, ramtypetable1[8 + ramtype]);
2053 ret |= SETIREG(SISSR, 0x19, ramtypetable1[16 + ramtype]);
2054
2055 ret |= SETIREGOR(SISSR, 0x21, 0x20);
2056
2057 ret |= SETIREG(SISSR, 0x22, 0xfb);
2058 ret |= SETIREG(SISSR, 0x21, 0xa5);
2059
2060 if (ret == 0)
2061 break;
2062 }
2063
2064 return ret;
2065 }
2066
2067 #undef SETREG
2068 #undef GETREG
2069 #undef SETIREG
2070 #undef GETIREG
2071 #undef SETIREGOR
2072 #undef SETIREGAND
2073 #undef SETIREGANDOR
2074 #undef READL
2075 #undef WRITEL
2076
2077 static void sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
2078 {
2079 u8 tmp8, tmp82, ramtype;
2080 int bw = 0;
2081 char *ramtypetext1 = NULL;
2082 static const char ram_datarate[4] = {'S', 'S', 'D', 'D'};
2083 static const char ram_dynamictype[4] = {'D', 'G', 'D', 'G'};
2084 static const int busSDR[4] = {64, 64, 128, 128};
2085 static const int busDDR[4] = {32, 32, 64, 64};
2086 static const int busDDRA[4] = {64+32, 64+32, (64+32)*2, (64+32)*2};
2087
2088 sisusb_getidxreg(sisusb, SISSR, 0x14, &tmp8);
2089 sisusb_getidxreg(sisusb, SISSR, 0x15, &tmp82);
2090 sisusb_getidxreg(sisusb, SISSR, 0x3a, &ramtype);
2091 sisusb->vramsize = (1 << ((tmp8 & 0xf0) >> 4)) * 1024 * 1024;
2092 ramtype &= 0x03;
2093 switch ((tmp8 >> 2) & 0x03) {
2094 case 0:
2095 ramtypetext1 = "1 ch/1 r";
2096 if (tmp82 & 0x10)
2097 bw = 32;
2098 else
2099 bw = busSDR[(tmp8 & 0x03)];
2100
2101 break;
2102 case 1:
2103 ramtypetext1 = "1 ch/2 r";
2104 sisusb->vramsize <<= 1;
2105 bw = busSDR[(tmp8 & 0x03)];
2106 break;
2107 case 2:
2108 ramtypetext1 = "asymmetric";
2109 sisusb->vramsize += sisusb->vramsize/2;
2110 bw = busDDRA[(tmp8 & 0x03)];
2111 break;
2112 case 3:
2113 ramtypetext1 = "2 channel";
2114 sisusb->vramsize <<= 1;
2115 bw = busDDR[(tmp8 & 0x03)];
2116 break;
2117 }
2118
2119 dev_info(&sisusb->sisusb_dev->dev,
2120 "%dMB %s %cDR S%cRAM, bus width %d\n",
2121 sisusb->vramsize >> 20, ramtypetext1,
2122 ram_datarate[ramtype], ram_dynamictype[ramtype], bw);
2123 }
2124
2125 static int sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb)
2126 {
2127 struct sisusb_packet packet;
2128 int ret;
2129 u32 tmp32;
2130
2131
2132 packet.header = 0x001f;
2133 packet.address = 0x00000324;
2134 packet.data = 0x00000004;
2135 ret = sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2136
2137 packet.header = 0x001f;
2138 packet.address = 0x00000364;
2139 packet.data = 0x00000004;
2140 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2141
2142 packet.header = 0x001f;
2143 packet.address = 0x00000384;
2144 packet.data = 0x00000004;
2145 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2146
2147 packet.header = 0x001f;
2148 packet.address = 0x00000100;
2149 packet.data = 0x00000700;
2150 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2151
2152 packet.header = 0x000f;
2153 packet.address = 0x00000004;
2154 ret |= sisusb_send_bridge_packet(sisusb, 6, &packet, 0);
2155 packet.data |= 0x17;
2156 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2157
2158
2159 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2160 ret |= sisusb_write_pci_config(sisusb, 0x10, 0xfffffff0);
2161 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2162 tmp32 &= 0x0f;
2163 tmp32 |= SISUSB_PCI_MEMBASE;
2164 ret |= sisusb_write_pci_config(sisusb, 0x10, tmp32);
2165
2166
2167 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2168 ret |= sisusb_write_pci_config(sisusb, 0x14, 0xfffffff0);
2169 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2170 tmp32 &= 0x0f;
2171 tmp32 |= SISUSB_PCI_MMIOBASE;
2172 ret |= sisusb_write_pci_config(sisusb, 0x14, tmp32);
2173
2174
2175 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2176 ret |= sisusb_write_pci_config(sisusb, 0x18, 0xfffffff0);
2177 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2178 tmp32 &= 0x0f;
2179 tmp32 |= SISUSB_PCI_IOPORTBASE;
2180 ret |= sisusb_write_pci_config(sisusb, 0x18, tmp32);
2181
2182
2183 ret |= sisusb_read_pci_config(sisusb, 0x04, &tmp32);
2184 tmp32 |= 0x3;
2185 ret |= sisusb_write_pci_config(sisusb, 0x04, tmp32);
2186
2187 if (ret == 0) {
2188
2189 packet.header = 0x001f;
2190 packet.address = 0x00000050;
2191 packet.data = 0x000000ff;
2192 ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
2193 }
2194
2195 return ret;
2196 }
2197
2198
2199
2200
2201
2202
2203 static int sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
2204 {
2205 int ret = 0, test = 0;
2206 u32 tmp32;
2207
2208 if (sisusb->devinit == 1) {
2209
2210 ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
2211 if (ret)
2212 return ret;
2213
2214 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE)
2215 test++;
2216
2217 ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
2218 if (ret)
2219 return ret;
2220
2221 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE)
2222 test++;
2223
2224 ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
2225 if (ret)
2226 return ret;
2227
2228 if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE)
2229 test++;
2230 }
2231
2232
2233 if ((sisusb->devinit == 0) || (test != 3)) {
2234
2235 ret |= sisusb_do_init_gfxdevice(sisusb);
2236
2237 if (ret == 0)
2238 sisusb->devinit = 1;
2239
2240 }
2241
2242 if (sisusb->devinit) {
2243
2244 if (sisusb_init_gfxcore(sisusb) == 0) {
2245 sisusb->gfxinit = 1;
2246 sisusb_get_ramconfig(sisusb);
2247 sisusb_set_default_mode(sisusb, 1);
2248 ret |= sisusb_setup_screen(sisusb, 1, initscreen);
2249 }
2250 }
2251
2252 return ret;
2253 }
2254
2255
2256 #ifdef CONFIG_USB_SISUSBVGA_CON
2257
2258
2259
2260
2261
2262
2263
2264 int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
2265 {
2266 int ret = 0, slot = sisusb->font_slot, i;
2267 const struct font_desc *myfont;
2268 u8 *tempbuf;
2269 u16 *tempbufb;
2270 static const char bootstring[] =
2271 "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2272 static const char bootlogo[] = "(o_ //\\ V_/_";
2273
2274
2275
2276 if (!sisusb->SiS_Pr)
2277 return 1;
2278
2279 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2280 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2281
2282
2283 SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
2284
2285 myfont = find_font("VGA8x16");
2286 if (!myfont)
2287 return 1;
2288
2289 tempbuf = vmalloc(8192);
2290 if (!tempbuf)
2291 return 1;
2292
2293 for (i = 0; i < 256; i++)
2294 memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
2295
2296
2297 ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192,
2298 0, 1, NULL, 16, 0);
2299
2300 vfree(tempbuf);
2301
2302
2303 if (sisusb->font_backup) {
2304 ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
2305 8192, sisusb->font_backup_512, 1, NULL,
2306 sisusb->font_backup_height, 0);
2307 if (slot != 2)
2308 sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
2309 NULL, 16, 0);
2310 }
2311
2312 if (init && !sisusb->scrbuf) {
2313
2314 tempbuf = vmalloc(8192);
2315 if (tempbuf) {
2316
2317 i = 4096;
2318 tempbufb = (u16 *)tempbuf;
2319 while (i--)
2320 *(tempbufb++) = 0x0720;
2321
2322 i = 0;
2323 tempbufb = (u16 *)tempbuf;
2324 while (bootlogo[i]) {
2325 *(tempbufb++) = 0x0700 | bootlogo[i++];
2326 if (!(i % 4))
2327 tempbufb += 76;
2328 }
2329
2330 i = 0;
2331 tempbufb = (u16 *)tempbuf + 6;
2332 while (bootstring[i])
2333 *(tempbufb++) = 0x0700 | bootstring[i++];
2334
2335 ret |= sisusb_copy_memory(sisusb, tempbuf,
2336 sisusb->vrambase, 8192);
2337
2338 vfree(tempbuf);
2339
2340 }
2341
2342 } else if (sisusb->scrbuf) {
2343 ret |= sisusb_copy_memory(sisusb, (u8 *)sisusb->scrbuf,
2344 sisusb->vrambase, sisusb->scrbuf_size);
2345 }
2346
2347 if (sisusb->sisusb_cursor_size_from >= 0 &&
2348 sisusb->sisusb_cursor_size_to >= 0) {
2349 sisusb_setidxreg(sisusb, SISCR, 0x0a,
2350 sisusb->sisusb_cursor_size_from);
2351 sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
2352 sisusb->sisusb_cursor_size_to);
2353 } else {
2354 sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
2355 sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
2356 sisusb->sisusb_cursor_size_to = -1;
2357 }
2358
2359 slot = sisusb->sisusb_cursor_loc;
2360 if (slot < 0)
2361 slot = 0;
2362
2363 sisusb->sisusb_cursor_loc = -1;
2364 sisusb->bad_cursor_pos = 1;
2365
2366 sisusb_set_cursor(sisusb, slot);
2367
2368 sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
2369 sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
2370
2371 sisusb->textmodedestroyed = 0;
2372
2373
2374
2375 return ret;
2376 }
2377
2378 #endif
2379
2380
2381
2382 static int sisusb_open(struct inode *inode, struct file *file)
2383 {
2384 struct sisusb_usb_data *sisusb;
2385 struct usb_interface *interface;
2386 int subminor = iminor(inode);
2387
2388 interface = usb_find_interface(&sisusb_driver, subminor);
2389 if (!interface)
2390 return -ENODEV;
2391
2392 sisusb = usb_get_intfdata(interface);
2393 if (!sisusb)
2394 return -ENODEV;
2395
2396 mutex_lock(&sisusb->lock);
2397
2398 if (!sisusb->present || !sisusb->ready) {
2399 mutex_unlock(&sisusb->lock);
2400 return -ENODEV;
2401 }
2402
2403 if (sisusb->isopen) {
2404 mutex_unlock(&sisusb->lock);
2405 return -EBUSY;
2406 }
2407
2408 if (!sisusb->devinit) {
2409 if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH ||
2410 sisusb->sisusb_dev->speed >= USB_SPEED_SUPER) {
2411 if (sisusb_init_gfxdevice(sisusb, 0)) {
2412 mutex_unlock(&sisusb->lock);
2413 dev_err(&sisusb->sisusb_dev->dev,
2414 "Failed to initialize device\n");
2415 return -EIO;
2416 }
2417 } else {
2418 mutex_unlock(&sisusb->lock);
2419 dev_err(&sisusb->sisusb_dev->dev,
2420 "Device not attached to USB 2.0 hub\n");
2421 return -EIO;
2422 }
2423 }
2424
2425
2426 kref_get(&sisusb->kref);
2427
2428 sisusb->isopen = 1;
2429
2430 file->private_data = sisusb;
2431
2432 mutex_unlock(&sisusb->lock);
2433
2434 return 0;
2435 }
2436
2437 void sisusb_delete(struct kref *kref)
2438 {
2439 struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
2440
2441 if (!sisusb)
2442 return;
2443
2444 usb_put_dev(sisusb->sisusb_dev);
2445
2446 sisusb->sisusb_dev = NULL;
2447 sisusb_free_buffers(sisusb);
2448 sisusb_free_urbs(sisusb);
2449 #ifdef CONFIG_USB_SISUSBVGA_CON
2450 kfree(sisusb->SiS_Pr);
2451 #endif
2452 kfree(sisusb);
2453 }
2454
2455 static int sisusb_release(struct inode *inode, struct file *file)
2456 {
2457 struct sisusb_usb_data *sisusb;
2458
2459 sisusb = file->private_data;
2460 if (!sisusb)
2461 return -ENODEV;
2462
2463 mutex_lock(&sisusb->lock);
2464
2465 if (sisusb->present) {
2466
2467 if (!sisusb_wait_all_out_complete(sisusb))
2468 sisusb_kill_all_busy(sisusb);
2469 }
2470
2471 sisusb->isopen = 0;
2472 file->private_data = NULL;
2473
2474 mutex_unlock(&sisusb->lock);
2475
2476
2477 kref_put(&sisusb->kref, sisusb_delete);
2478
2479 return 0;
2480 }
2481
2482 static ssize_t sisusb_read(struct file *file, char __user *buffer,
2483 size_t count, loff_t *ppos)
2484 {
2485 struct sisusb_usb_data *sisusb;
2486 ssize_t bytes_read = 0;
2487 int errno = 0;
2488 u8 buf8;
2489 u16 buf16;
2490 u32 buf32, address;
2491
2492 sisusb = file->private_data;
2493 if (!sisusb)
2494 return -ENODEV;
2495
2496 mutex_lock(&sisusb->lock);
2497
2498
2499 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2500 mutex_unlock(&sisusb->lock);
2501 return -ENODEV;
2502 }
2503
2504 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2505 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2506
2507 address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE +
2508 SISUSB_PCI_IOPORTBASE;
2509
2510
2511
2512
2513
2514
2515 switch (count) {
2516 case 1:
2517 if (sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO,
2518 address, &buf8))
2519 errno = -EIO;
2520 else if (put_user(buf8, (u8 __user *)buffer))
2521 errno = -EFAULT;
2522 else
2523 bytes_read = 1;
2524
2525 break;
2526
2527 case 2:
2528 if (sisusb_read_memio_word(sisusb, SISUSB_TYPE_IO,
2529 address, &buf16))
2530 errno = -EIO;
2531 else if (put_user(buf16, (u16 __user *)buffer))
2532 errno = -EFAULT;
2533 else
2534 bytes_read = 2;
2535
2536 break;
2537
2538 case 4:
2539 if (sisusb_read_memio_long(sisusb, SISUSB_TYPE_IO,
2540 address, &buf32))
2541 errno = -EIO;
2542 else if (put_user(buf32, (u32 __user *)buffer))
2543 errno = -EFAULT;
2544 else
2545 bytes_read = 4;
2546
2547 break;
2548
2549 default:
2550 errno = -EIO;
2551
2552 }
2553
2554 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && (*ppos) <
2555 SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
2556
2557 address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE +
2558 SISUSB_PCI_MEMBASE;
2559
2560
2561
2562
2563 errno = sisusb_read_mem_bulk(sisusb, address,
2564 NULL, count, buffer, &bytes_read);
2565
2566 if (bytes_read)
2567 errno = bytes_read;
2568
2569 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2570 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE +
2571 SISUSB_PCI_MMIOSIZE) {
2572
2573 address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE +
2574 SISUSB_PCI_MMIOBASE;
2575
2576
2577
2578
2579 errno = sisusb_read_mem_bulk(sisusb, address,
2580 NULL, count, buffer, &bytes_read);
2581
2582 if (bytes_read)
2583 errno = bytes_read;
2584
2585 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2586 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
2587
2588 if (count != 4) {
2589 mutex_unlock(&sisusb->lock);
2590 return -EINVAL;
2591 }
2592
2593 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2594
2595
2596
2597
2598 if (sisusb_read_pci_config(sisusb, address, &buf32))
2599 errno = -EIO;
2600 else if (put_user(buf32, (u32 __user *)buffer))
2601 errno = -EFAULT;
2602 else
2603 bytes_read = 4;
2604
2605 } else {
2606
2607 errno = -EBADFD;
2608
2609 }
2610
2611 (*ppos) += bytes_read;
2612
2613 mutex_unlock(&sisusb->lock);
2614
2615 return errno ? errno : bytes_read;
2616 }
2617
2618 static ssize_t sisusb_write(struct file *file, const char __user *buffer,
2619 size_t count, loff_t *ppos)
2620 {
2621 struct sisusb_usb_data *sisusb;
2622 int errno = 0;
2623 ssize_t bytes_written = 0;
2624 u8 buf8;
2625 u16 buf16;
2626 u32 buf32, address;
2627
2628 sisusb = file->private_data;
2629 if (!sisusb)
2630 return -ENODEV;
2631
2632 mutex_lock(&sisusb->lock);
2633
2634
2635 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2636 mutex_unlock(&sisusb->lock);
2637 return -ENODEV;
2638 }
2639
2640 if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
2641 (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
2642
2643 address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE +
2644 SISUSB_PCI_IOPORTBASE;
2645
2646
2647
2648
2649
2650
2651 switch (count) {
2652 case 1:
2653 if (get_user(buf8, (u8 __user *)buffer))
2654 errno = -EFAULT;
2655 else if (sisusb_write_memio_byte(sisusb,
2656 SISUSB_TYPE_IO, address, buf8))
2657 errno = -EIO;
2658 else
2659 bytes_written = 1;
2660
2661 break;
2662
2663 case 2:
2664 if (get_user(buf16, (u16 __user *)buffer))
2665 errno = -EFAULT;
2666 else if (sisusb_write_memio_word(sisusb,
2667 SISUSB_TYPE_IO, address, buf16))
2668 errno = -EIO;
2669 else
2670 bytes_written = 2;
2671
2672 break;
2673
2674 case 4:
2675 if (get_user(buf32, (u32 __user *)buffer))
2676 errno = -EFAULT;
2677 else if (sisusb_write_memio_long(sisusb,
2678 SISUSB_TYPE_IO, address, buf32))
2679 errno = -EIO;
2680 else
2681 bytes_written = 4;
2682
2683 break;
2684
2685 default:
2686 errno = -EIO;
2687 }
2688
2689 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
2690 (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE +
2691 sisusb->vramsize) {
2692
2693 address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE +
2694 SISUSB_PCI_MEMBASE;
2695
2696
2697
2698
2699
2700
2701
2702 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2703 count, buffer, 0, &bytes_written);
2704
2705 if (bytes_written)
2706 errno = bytes_written;
2707
2708 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
2709 (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE +
2710 SISUSB_PCI_MMIOSIZE) {
2711
2712 address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE +
2713 SISUSB_PCI_MMIOBASE;
2714
2715
2716
2717
2718
2719
2720 errno = sisusb_write_mem_bulk(sisusb, address, NULL,
2721 count, buffer, 0, &bytes_written);
2722
2723 if (bytes_written)
2724 errno = bytes_written;
2725
2726 } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
2727 (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE +
2728 SISUSB_PCI_PCONFSIZE) {
2729
2730 if (count != 4) {
2731 mutex_unlock(&sisusb->lock);
2732 return -EINVAL;
2733 }
2734
2735 address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
2736
2737
2738
2739
2740 if (get_user(buf32, (u32 __user *)buffer))
2741 errno = -EFAULT;
2742 else if (sisusb_write_pci_config(sisusb, address, buf32))
2743 errno = -EIO;
2744 else
2745 bytes_written = 4;
2746
2747
2748 } else {
2749
2750
2751 errno = -EBADFD;
2752
2753 }
2754
2755 (*ppos) += bytes_written;
2756
2757 mutex_unlock(&sisusb->lock);
2758
2759 return errno ? errno : bytes_written;
2760 }
2761
2762 static loff_t sisusb_lseek(struct file *file, loff_t offset, int orig)
2763 {
2764 struct sisusb_usb_data *sisusb;
2765 loff_t ret;
2766
2767 sisusb = file->private_data;
2768 if (!sisusb)
2769 return -ENODEV;
2770
2771 mutex_lock(&sisusb->lock);
2772
2773
2774 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2775 mutex_unlock(&sisusb->lock);
2776 return -ENODEV;
2777 }
2778
2779 ret = no_seek_end_llseek(file, offset, orig);
2780
2781 mutex_unlock(&sisusb->lock);
2782 return ret;
2783 }
2784
2785 static int sisusb_handle_command(struct sisusb_usb_data *sisusb,
2786 struct sisusb_command *y, unsigned long arg)
2787 {
2788 int retval, length;
2789 u32 port, address;
2790
2791
2792
2793
2794 if (!sisusb->devinit)
2795 return -ENODEV;
2796
2797 port = y->data3 -
2798 SISUSB_PCI_PSEUDO_IOPORTBASE +
2799 SISUSB_PCI_IOPORTBASE;
2800
2801 switch (y->operation) {
2802 case SUCMD_GET:
2803 retval = sisusb_getidxreg(sisusb, port, y->data0, &y->data1);
2804 if (!retval) {
2805 if (copy_to_user((void __user *)arg, y, sizeof(*y)))
2806 retval = -EFAULT;
2807 }
2808 break;
2809
2810 case SUCMD_SET:
2811 retval = sisusb_setidxreg(sisusb, port, y->data0, y->data1);
2812 break;
2813
2814 case SUCMD_SETOR:
2815 retval = sisusb_setidxregor(sisusb, port, y->data0, y->data1);
2816 break;
2817
2818 case SUCMD_SETAND:
2819 retval = sisusb_setidxregand(sisusb, port, y->data0, y->data1);
2820 break;
2821
2822 case SUCMD_SETANDOR:
2823 retval = sisusb_setidxregandor(sisusb, port, y->data0,
2824 y->data1, y->data2);
2825 break;
2826
2827 case SUCMD_SETMASK:
2828 retval = sisusb_setidxregmask(sisusb, port, y->data0,
2829 y->data1, y->data2);
2830 break;
2831
2832 case SUCMD_CLRSCR:
2833
2834 if (!sisusb->gfxinit)
2835 return -ENODEV;
2836
2837 length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
2838 address = y->data3 - SISUSB_PCI_PSEUDO_MEMBASE +
2839 SISUSB_PCI_MEMBASE;
2840 retval = sisusb_clear_vram(sisusb, address, length);
2841 break;
2842
2843 case SUCMD_HANDLETEXTMODE:
2844 retval = 0;
2845 #ifdef CONFIG_USB_SISUSBVGA_CON
2846
2847 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2848 return -ENODEV;
2849
2850 switch (y->data0) {
2851 case 0:
2852 retval = sisusb_reset_text_mode(sisusb, 0);
2853 break;
2854 case 1:
2855 sisusb->textmodedestroyed = 1;
2856 break;
2857 }
2858 #endif
2859 break;
2860
2861 #ifdef CONFIG_USB_SISUSBVGA_CON
2862 case SUCMD_SETMODE:
2863
2864 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2865 return -ENODEV;
2866
2867 retval = 0;
2868
2869 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2870 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2871
2872 if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
2873 retval = -EINVAL;
2874
2875 break;
2876
2877 case SUCMD_SETVESAMODE:
2878
2879 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
2880 return -ENODEV;
2881
2882 retval = 0;
2883
2884 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2885 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2886
2887 if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
2888 retval = -EINVAL;
2889
2890 break;
2891 #endif
2892
2893 default:
2894 retval = -EINVAL;
2895 }
2896
2897 if (retval > 0)
2898 retval = -EIO;
2899
2900 return retval;
2901 }
2902
2903 static long sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2904 {
2905 struct sisusb_usb_data *sisusb;
2906 struct sisusb_info x;
2907 struct sisusb_command y;
2908 long retval = 0;
2909 u32 __user *argp = (u32 __user *)arg;
2910
2911 sisusb = file->private_data;
2912 if (!sisusb)
2913 return -ENODEV;
2914
2915 mutex_lock(&sisusb->lock);
2916
2917
2918 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
2919 retval = -ENODEV;
2920 goto err_out;
2921 }
2922
2923 switch (cmd) {
2924 case SISUSB_GET_CONFIG_SIZE:
2925
2926 if (put_user(sizeof(x), argp))
2927 retval = -EFAULT;
2928
2929 break;
2930
2931 case SISUSB_GET_CONFIG:
2932
2933 x.sisusb_id = SISUSB_ID;
2934 x.sisusb_version = SISUSB_VERSION;
2935 x.sisusb_revision = SISUSB_REVISION;
2936 x.sisusb_patchlevel = SISUSB_PATCHLEVEL;
2937 x.sisusb_gfxinit = sisusb->gfxinit;
2938 x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE;
2939 x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE;
2940 x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE;
2941 x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE;
2942 x.sisusb_vramsize = sisusb->vramsize;
2943 x.sisusb_minor = sisusb->minor;
2944 x.sisusb_fbdevactive = 0;
2945 #ifdef CONFIG_USB_SISUSBVGA_CON
2946 x.sisusb_conactive = sisusb->haveconsole ? 1 : 0;
2947 #else
2948 x.sisusb_conactive = 0;
2949 #endif
2950 memset(x.sisusb_reserved, 0, sizeof(x.sisusb_reserved));
2951
2952 if (copy_to_user((void __user *)arg, &x, sizeof(x)))
2953 retval = -EFAULT;
2954
2955 break;
2956
2957 case SISUSB_COMMAND:
2958
2959 if (copy_from_user(&y, (void __user *)arg, sizeof(y)))
2960 retval = -EFAULT;
2961 else
2962 retval = sisusb_handle_command(sisusb, &y, arg);
2963
2964 break;
2965
2966 default:
2967 retval = -ENOTTY;
2968 break;
2969 }
2970
2971 err_out:
2972 mutex_unlock(&sisusb->lock);
2973 return retval;
2974 }
2975
2976 #ifdef CONFIG_COMPAT
2977 static long sisusb_compat_ioctl(struct file *f, unsigned int cmd,
2978 unsigned long arg)
2979 {
2980 switch (cmd) {
2981 case SISUSB_GET_CONFIG_SIZE:
2982 case SISUSB_GET_CONFIG:
2983 case SISUSB_COMMAND:
2984 return sisusb_ioctl(f, cmd, arg);
2985
2986 default:
2987 return -ENOIOCTLCMD;
2988 }
2989 }
2990 #endif
2991
2992 static const struct file_operations usb_sisusb_fops = {
2993 .owner = THIS_MODULE,
2994 .open = sisusb_open,
2995 .release = sisusb_release,
2996 .read = sisusb_read,
2997 .write = sisusb_write,
2998 .llseek = sisusb_lseek,
2999 #ifdef CONFIG_COMPAT
3000 .compat_ioctl = sisusb_compat_ioctl,
3001 #endif
3002 .unlocked_ioctl = sisusb_ioctl
3003 };
3004
3005 static struct usb_class_driver usb_sisusb_class = {
3006 .name = "sisusbvga%d",
3007 .fops = &usb_sisusb_fops,
3008 .minor_base = SISUSB_MINOR
3009 };
3010
3011 static int sisusb_probe(struct usb_interface *intf,
3012 const struct usb_device_id *id)
3013 {
3014 struct usb_device *dev = interface_to_usbdev(intf);
3015 struct sisusb_usb_data *sisusb;
3016 int retval = 0, i;
3017
3018 dev_info(&dev->dev, "USB2VGA dongle found at address %d\n",
3019 dev->devnum);
3020
3021
3022 sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL);
3023 if (!sisusb)
3024 return -ENOMEM;
3025
3026 kref_init(&sisusb->kref);
3027
3028 mutex_init(&(sisusb->lock));
3029
3030 sisusb->sisusb_dev = dev;
3031 sisusb->vrambase = SISUSB_PCI_MEMBASE;
3032 sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
3033 sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
3034 sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
3035
3036
3037
3038 retval = usb_register_dev(intf, &usb_sisusb_class);
3039 if (retval) {
3040 dev_err(&sisusb->sisusb_dev->dev,
3041 "Failed to get a minor for device %d\n",
3042 dev->devnum);
3043 retval = -ENODEV;
3044 goto error_1;
3045 }
3046
3047 sisusb->minor = intf->minor;
3048
3049
3050 sisusb->ibufsize = SISUSB_IBUF_SIZE;
3051 sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL);
3052 if (!sisusb->ibuf) {
3053 retval = -ENOMEM;
3054 goto error_2;
3055 }
3056
3057 sisusb->numobufs = 0;
3058 sisusb->obufsize = SISUSB_OBUF_SIZE;
3059 for (i = 0; i < NUMOBUFS; i++) {
3060 sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL);
3061 if (!sisusb->obuf[i]) {
3062 if (i == 0) {
3063 retval = -ENOMEM;
3064 goto error_3;
3065 }
3066 break;
3067 }
3068 sisusb->numobufs++;
3069 }
3070
3071
3072 sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL);
3073 if (!sisusb->sisurbin) {
3074 retval = -ENOMEM;
3075 goto error_3;
3076 }
3077 sisusb->completein = 1;
3078
3079 for (i = 0; i < sisusb->numobufs; i++) {
3080 sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL);
3081 if (!sisusb->sisurbout[i]) {
3082 retval = -ENOMEM;
3083 goto error_4;
3084 }
3085 sisusb->urbout_context[i].sisusb = (void *)sisusb;
3086 sisusb->urbout_context[i].urbindex = i;
3087 sisusb->urbstatus[i] = 0;
3088 }
3089
3090 dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n",
3091 sisusb->numobufs);
3092
3093 #ifdef CONFIG_USB_SISUSBVGA_CON
3094
3095 sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL);
3096 if (!sisusb->SiS_Pr) {
3097 retval = -ENOMEM;
3098 goto error_4;
3099 }
3100 #endif
3101
3102
3103
3104 init_waitqueue_head(&sisusb->wait_q);
3105
3106 usb_set_intfdata(intf, sisusb);
3107
3108 usb_get_dev(sisusb->sisusb_dev);
3109
3110 sisusb->present = 1;
3111
3112 if (dev->speed == USB_SPEED_HIGH || dev->speed >= USB_SPEED_SUPER) {
3113 int initscreen = 1;
3114 #ifdef CONFIG_USB_SISUSBVGA_CON
3115 if (sisusb_first_vc > 0 && sisusb_last_vc > 0 &&
3116 sisusb_first_vc <= sisusb_last_vc &&
3117 sisusb_last_vc <= MAX_NR_CONSOLES)
3118 initscreen = 0;
3119 #endif
3120 if (sisusb_init_gfxdevice(sisusb, initscreen))
3121 dev_err(&sisusb->sisusb_dev->dev,
3122 "Failed to early initialize device\n");
3123
3124 } else
3125 dev_info(&sisusb->sisusb_dev->dev,
3126 "Not attached to USB 2.0 hub, deferring init\n");
3127
3128 sisusb->ready = 1;
3129
3130 #ifdef SISUSBENDIANTEST
3131 dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST ***\n");
3132 sisusb_testreadwrite(sisusb);
3133 dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST END ***\n");
3134 #endif
3135
3136 #ifdef CONFIG_USB_SISUSBVGA_CON
3137 sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
3138 #endif
3139
3140 return 0;
3141
3142 error_4:
3143 sisusb_free_urbs(sisusb);
3144 error_3:
3145 sisusb_free_buffers(sisusb);
3146 error_2:
3147 usb_deregister_dev(intf, &usb_sisusb_class);
3148 error_1:
3149 kfree(sisusb);
3150 return retval;
3151 }
3152
3153 static void sisusb_disconnect(struct usb_interface *intf)
3154 {
3155 struct sisusb_usb_data *sisusb;
3156
3157
3158 sisusb = usb_get_intfdata(intf);
3159 if (!sisusb)
3160 return;
3161
3162 #ifdef CONFIG_USB_SISUSBVGA_CON
3163 sisusb_console_exit(sisusb);
3164 #endif
3165
3166 usb_deregister_dev(intf, &usb_sisusb_class);
3167
3168 mutex_lock(&sisusb->lock);
3169
3170
3171 if (!sisusb_wait_all_out_complete(sisusb))
3172 sisusb_kill_all_busy(sisusb);
3173
3174 usb_set_intfdata(intf, NULL);
3175
3176 sisusb->present = 0;
3177 sisusb->ready = 0;
3178
3179 mutex_unlock(&sisusb->lock);
3180
3181
3182 kref_put(&sisusb->kref, sisusb_delete);
3183 }
3184
3185 static const struct usb_device_id sisusb_table[] = {
3186 { USB_DEVICE(0x0711, 0x0550) },
3187 { USB_DEVICE(0x0711, 0x0900) },
3188 { USB_DEVICE(0x0711, 0x0901) },
3189 { USB_DEVICE(0x0711, 0x0902) },
3190 { USB_DEVICE(0x0711, 0x0903) },
3191 { USB_DEVICE(0x0711, 0x0918) },
3192 { USB_DEVICE(0x0711, 0x0920) },
3193 { USB_DEVICE(0x0711, 0x0950) },
3194 { USB_DEVICE(0x0711, 0x5200) },
3195 { USB_DEVICE(0x182d, 0x021c) },
3196 { USB_DEVICE(0x182d, 0x0269) },
3197 { }
3198 };
3199
3200 MODULE_DEVICE_TABLE(usb, sisusb_table);
3201
3202 static struct usb_driver sisusb_driver = {
3203 .name = "sisusb",
3204 .probe = sisusb_probe,
3205 .disconnect = sisusb_disconnect,
3206 .id_table = sisusb_table,
3207 };
3208
3209 static int __init usb_sisusb_init(void)
3210 {
3211
3212 #ifdef CONFIG_USB_SISUSBVGA_CON
3213 sisusb_init_concode();
3214 #endif
3215
3216 return usb_register(&sisusb_driver);
3217 }
3218
3219 static void __exit usb_sisusb_exit(void)
3220 {
3221 usb_deregister(&sisusb_driver);
3222 }
3223
3224 module_init(usb_sisusb_init);
3225 module_exit(usb_sisusb_exit);
3226
3227 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3228 MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3229 MODULE_LICENSE("GPL");
3230