Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6

+5279 -350
+84
Documentation/input/appletouch.txt
··· 1 + Apple Touchpad Driver (appletouch) 2 + ---------------------------------- 3 + Copyright (C) 2005 Stelian Pop <stelian@popies.net> 4 + 5 + appletouch is a Linux kernel driver for the USB touchpad found on post 6 + February 2005 Apple Alu Powerbooks. 7 + 8 + This driver is derived from Johannes Berg's appletrackpad driver[1], but it has 9 + been improved in some areas: 10 + * appletouch is a full kernel driver, no userspace program is necessary 11 + * appletouch can be interfaced with the synaptics X11 driver, in order 12 + to have touchpad acceleration, scrolling, etc. 13 + 14 + Credits go to Johannes Berg for reverse-engineering the touchpad protocol, 15 + Frank Arnold for further improvements, and Alex Harper for some additional 16 + information about the inner workings of the touchpad sensors. 17 + 18 + Usage: 19 + ------ 20 + 21 + In order to use the touchpad in the basic mode, compile the driver and load 22 + the module. A new input device will be detected and you will be able to read 23 + the mouse data from /dev/input/mice (using gpm, or X11). 24 + 25 + In X11, you can configure the touchpad to use the synaptics X11 driver, which 26 + will give additional functionalities, like acceleration, scrolling, 2 finger 27 + tap for middle button mouse emulation, 3 finger tap for right button mouse 28 + emulation, etc. In order to do this, make sure you're using a recent version of 29 + the synaptics driver (tested with 0.14.2, available from [2]), and configure a 30 + new input device in your X11 configuration file (take a look below for an 31 + example). For additional configuration, see the synaptics driver documentation. 32 + 33 + Section "InputDevice" 34 + Identifier "Synaptics Touchpad" 35 + Driver "synaptics" 36 + Option "SendCoreEvents" "true" 37 + Option "Device" "/dev/input/mice" 38 + Option "Protocol" "auto-dev" 39 + Option "LeftEdge" "0" 40 + Option "RightEdge" "850" 41 + Option "TopEdge" "0" 42 + Option "BottomEdge" "645" 43 + Option "MinSpeed" "0.4" 44 + Option "MaxSpeed" "1" 45 + Option "AccelFactor" "0.02" 46 + Option "FingerLow" "0" 47 + Option "FingerHigh" "30" 48 + Option "MaxTapMove" "20" 49 + Option "MaxTapTime" "100" 50 + Option "HorizScrollDelta" "0" 51 + Option "VertScrollDelta" "30" 52 + Option "SHMConfig" "on" 53 + EndSection 54 + 55 + Section "ServerLayout" 56 + ... 57 + InputDevice "Mouse" 58 + InputDevice "Synaptics Touchpad" 59 + ... 60 + EndSection 61 + 62 + Fuzz problems: 63 + -------------- 64 + 65 + The touchpad sensors are very sensitive to heat, and will generate a lot of 66 + noise when the temperature changes. This is especially true when you power-on 67 + the laptop for the first time. 68 + 69 + The appletouch driver tries to handle this noise and auto adapt itself, but it 70 + is not perfect. If finger movements are not recognized anymore, try reloading 71 + the driver. 72 + 73 + You can activate debugging using the 'debug' module parameter. A value of 0 74 + deactivates any debugging, 1 activates tracing of invalid samples, 2 activates 75 + full tracing (each sample is being traced): 76 + modprobe appletouch debug=1 77 + or 78 + echo "1" > /sys/module/appletouch/parameters/debug 79 + 80 + Links: 81 + ------ 82 + 83 + [1]: http://johannes.sipsolutions.net/PowerBook/touchpad/ 84 + [2]: http://web.telia.com/~u89404340/touchpad/index.html
+8 -5
Documentation/usb/proc_usb_info.txt
··· 20 20 21 21 to /etc/fstab. This will mount usbfs at each reboot. 22 22 You can then issue `cat /proc/bus/usb/devices` to extract 23 - USB device information, and user mode drivers can use usbfs 23 + USB device information, and user mode drivers can use usbfs 24 24 to interact with USB devices. 25 25 26 26 There are a number of mount options supported by usbfs. ··· 32 32 still see references to the older "usbdevfs" name. 33 33 34 34 For more information on mounting the usbfs file system, see the 35 - "USB Device Filesystem" section of the USB Guide. The latest copy 35 + "USB Device Filesystem" section of the USB Guide. The latest copy 36 36 of the USB Guide can be found at http://www.linux-usb.org/ 37 37 38 38 ··· 133 133 are the only transfers that reserve bandwidth. Control and bulk 134 134 transfers use all other bandwidth, including reserved bandwidth that 135 135 is not used for transfers (such as for short packets). 136 - 136 + 137 137 The percentage is how much of the "reserved" bandwidth is scheduled by 138 138 those transfers. For a low or full speed bus (loosely, "USB 1.1"), 139 139 90% of the bus bandwidth is reserved. For a high speed bus (loosely, ··· 197 197 | | |__NumberOfInterfaces 198 198 | |__ "*" indicates the active configuration (others are " ") 199 199 |__Config info tag 200 - 200 + 201 201 USB devices may have multiple configurations, each of which act 202 202 rather differently. For example, a bus-powered configuration 203 203 might be much less capable than one that is self-powered. Only ··· 228 228 For example, default settings may not use more than a small 229 229 amount of periodic bandwidth. To use significant fractions 230 230 of bus bandwidth, drivers must select a non-default altsetting. 231 - 231 + 232 232 Only one setting for an interface may be active at a time, and 233 233 only one driver may bind to an interface at a time. Most devices 234 234 have only one alternate setting per interface. ··· 297 297 C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA 298 298 I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub 299 299 E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms 300 + 300 301 T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4 301 302 D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 302 303 P: Vendor=0451 ProdID=1446 Rev= 1.00 303 304 C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA 304 305 I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub 305 306 E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms 307 + 306 308 T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0 307 309 D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 308 310 P: Vendor=04b4 ProdID=0001 Rev= 0.00 309 311 C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA 310 312 I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=mouse 311 313 E: Ad=81(I) Atr=03(Int.) MxPS= 3 Ivl= 10ms 314 + 312 315 T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 313 316 D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 314 317 P: Vendor=0565 ProdID=0001 Rev= 1.08
+8 -4
drivers/usb/class/audio.c
··· 631 631 i = u->flags; 632 632 spin_unlock_irqrestore(&as->lock, flags); 633 633 while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) { 634 - set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); 635 - schedule_timeout(1); 634 + if (notkilled) 635 + schedule_timeout_interruptible(1); 636 + else 637 + schedule_timeout_uninterruptible(1); 636 638 spin_lock_irqsave(&as->lock, flags); 637 639 i = u->flags; 638 640 spin_unlock_irqrestore(&as->lock, flags); ··· 1104 1102 i = u->flags; 1105 1103 spin_unlock_irqrestore(&as->lock, flags); 1106 1104 while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) { 1107 - set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); 1108 - schedule_timeout(1); 1105 + if (notkilled) 1106 + schedule_timeout_interruptible(1); 1107 + else 1108 + schedule_timeout_uninterruptible(1); 1109 1109 spin_lock_irqsave(&as->lock, flags); 1110 1110 i = u->flags; 1111 1111 spin_unlock_irqrestore(&as->lock, flags);
+1 -2
drivers/usb/core/hcd.c
··· 1606 1606 return IRQ_NONE; 1607 1607 1608 1608 hcd->saw_irq = 1; 1609 - if (hcd->state != start && hcd->state == HC_STATE_HALT) 1609 + if (hcd->state == HC_STATE_HALT) 1610 1610 usb_hc_died (hcd); 1611 1611 return IRQ_HANDLED; 1612 1612 } ··· 1630 1630 spin_lock_irqsave (&hcd_root_hub_lock, flags); 1631 1631 if (hcd->rh_registered) { 1632 1632 hcd->poll_rh = 0; 1633 - del_timer(&hcd->rh_timer); 1634 1633 1635 1634 /* make khubd clean up old urbs and devices */ 1636 1635 usb_set_device_state (hcd->self.root_hub,
+6 -5
drivers/usb/core/hub.c
··· 435 435 static void hub_power_on(struct usb_hub *hub) 436 436 { 437 437 int port1; 438 + unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2; 438 439 439 440 /* if hub supports power switching, enable power on each port */ 440 441 if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) < 2) { ··· 445 444 USB_PORT_FEAT_POWER); 446 445 } 447 446 448 - /* Wait for power to be enabled */ 449 - msleep(hub->descriptor->bPwrOn2PwrGood * 2); 447 + /* Wait at least 100 msec for power to become stable */ 448 + msleep(max(pgood_delay, (unsigned) 100)); 450 449 } 451 450 452 451 static void hub_quiesce(struct usb_hub *hub) ··· 1461 1460 port1, status); 1462 1461 else { 1463 1462 status = hub_port_wait_reset(hub, port1, udev, delay); 1464 - if (status) 1463 + if (status && status != -ENOTCONN) 1465 1464 dev_dbg(hub->intfdev, 1466 1465 "port_wait_reset: err = %d\n", 1467 1466 status); ··· 1470 1469 /* return on disconnect or reset */ 1471 1470 switch (status) { 1472 1471 case 0: 1473 - /* TRSTRCY = 10 ms */ 1474 - msleep(10); 1472 + /* TRSTRCY = 10 ms; plus some extra */ 1473 + msleep(10 + 40); 1475 1474 /* FALL THROUGH */ 1476 1475 case -ENOTCONN: 1477 1476 case -ENODEV:
+1
drivers/usb/gadget/inode.c
··· 483 483 data->state = STATE_EP_DISABLED; 484 484 data->desc.bDescriptorType = 0; 485 485 data->hs_desc.bDescriptorType = 0; 486 + usb_ep_disable(data->ep); 486 487 } 487 488 put_ep (data); 488 489 return 0;
+24 -4
drivers/usb/host/ehci-hcd.c
··· 400 400 return -EIO; 401 401 } 402 402 break; 403 + case PCI_VENDOR_ID_NVIDIA: 404 + /* NVidia reports that certain chips don't handle 405 + * QH, ITD, or SITD addresses above 2GB. (But TD, 406 + * data buffer, and periodic schedule are normal.) 407 + */ 408 + switch (pdev->device) { 409 + case 0x003c: /* MCP04 */ 410 + case 0x005b: /* CK804 */ 411 + case 0x00d8: /* CK8 */ 412 + case 0x00e8: /* CK8S */ 413 + if (pci_set_consistent_dma_mask(pdev, 414 + DMA_31BIT_MASK) < 0) 415 + ehci_warn (ehci, "can't enable NVidia " 416 + "workaround for >2GB RAM\n"); 417 + break; 418 + } 419 + break; 403 420 } 404 421 405 422 /* optional debug port, normally in the first BAR */ ··· 776 759 if (time_before (jiffies, ehci->next_statechange)) 777 760 msleep (100); 778 761 779 - /* If any port is suspended, we know we can/must resume the HC. */ 762 + /* If any port is suspended (or owned by the companion), 763 + * we know we can/must resume the HC (and mustn't reset it). 764 + */ 780 765 for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) { 781 766 u32 status; 782 767 port--; 783 768 status = readl (&ehci->regs->port_status [port]); 784 - if (status & PORT_SUSPEND) { 769 + if (!(status & PORT_POWER)) 770 + continue; 771 + if (status & (PORT_SUSPEND | PORT_OWNER)) { 785 772 down (&hcd->self.root_hub->serialize); 786 773 retval = ehci_hub_resume (hcd); 787 774 up (&hcd->self.root_hub->serialize); ··· 1147 1126 case QH_STATE_UNLINK: /* wait for hw to finish? */ 1148 1127 idle_timeout: 1149 1128 spin_unlock_irqrestore (&ehci->lock, flags); 1150 - set_current_state (TASK_UNINTERRUPTIBLE); 1151 - schedule_timeout (1); 1129 + schedule_timeout_uninterruptible(1); 1152 1130 goto rescan; 1153 1131 case QH_STATE_IDLE: /* fully unlinked */ 1154 1132 if (list_empty (&qh->qtd_list)) {
+16 -11
drivers/usb/host/ehci-hub.c
··· 54 54 /* suspend any active/unsuspended ports, maybe allow wakeup */ 55 55 while (port--) { 56 56 u32 __iomem *reg = &ehci->regs->port_status [port]; 57 - u32 t1 = readl (reg); 57 + u32 t1 = readl (reg) & ~PORT_RWC_BITS; 58 58 u32 t2 = t1; 59 59 60 60 if ((t1 & PORT_PE) && !(t1 & PORT_OWNER)) ··· 115 115 i = HCS_N_PORTS (ehci->hcs_params); 116 116 while (i--) { 117 117 temp = readl (&ehci->regs->port_status [i]); 118 - temp &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E); 118 + temp &= ~(PORT_RWC_BITS 119 + | PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E); 119 120 if (temp & PORT_SUSPEND) { 120 121 ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); 121 122 temp |= PORT_RESUME; ··· 129 128 temp = readl (&ehci->regs->port_status [i]); 130 129 if ((temp & PORT_SUSPEND) == 0) 131 130 continue; 132 - temp &= ~PORT_RESUME; 131 + temp &= ~(PORT_RWC_BITS | PORT_RESUME); 133 132 writel (temp, &ehci->regs->port_status [i]); 134 133 ehci_vdbg (ehci, "resumed port %d\n", i + 1); 135 134 } ··· 192 191 193 192 // what happens if HCS_N_CC(params) == 0 ? 194 193 port_status |= PORT_OWNER; 194 + port_status &= ~PORT_RWC_BITS; 195 195 writel (port_status, &ehci->regs->port_status [index]); 196 196 197 197 } else ··· 235 233 if (temp & PORT_OWNER) { 236 234 /* don't report this in GetPortStatus */ 237 235 if (temp & PORT_CSC) { 238 - temp &= ~PORT_CSC; 236 + temp &= ~PORT_RWC_BITS; 237 + temp |= PORT_CSC; 239 238 writel (temp, &ehci->regs->port_status [i]); 240 239 } 241 240 continue; ··· 346 343 &ehci->regs->port_status [wIndex]); 347 344 break; 348 345 case USB_PORT_FEAT_C_ENABLE: 349 - writel (temp | PORT_PEC, 346 + writel((temp & ~PORT_RWC_BITS) | PORT_PEC, 350 347 &ehci->regs->port_status [wIndex]); 351 348 break; 352 349 case USB_PORT_FEAT_SUSPEND: ··· 356 353 if ((temp & PORT_PE) == 0) 357 354 goto error; 358 355 /* resume signaling for 20 msec */ 359 - writel ((temp & ~PORT_WAKE_BITS) | PORT_RESUME, 356 + temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); 357 + writel (temp | PORT_RESUME, 360 358 &ehci->regs->port_status [wIndex]); 361 359 ehci->reset_done [wIndex] = jiffies 362 360 + msecs_to_jiffies (20); ··· 368 364 break; 369 365 case USB_PORT_FEAT_POWER: 370 366 if (HCS_PPC (ehci->hcs_params)) 371 - writel (temp & ~PORT_POWER, 367 + writel (temp & ~(PORT_RWC_BITS | PORT_POWER), 372 368 &ehci->regs->port_status [wIndex]); 373 369 break; 374 370 case USB_PORT_FEAT_C_CONNECTION: 375 - writel (temp | PORT_CSC, 371 + writel((temp & ~PORT_RWC_BITS) | PORT_CSC, 376 372 &ehci->regs->port_status [wIndex]); 377 373 break; 378 374 case USB_PORT_FEAT_C_OVER_CURRENT: 379 - writel (temp | PORT_OCC, 375 + writel((temp & ~PORT_RWC_BITS) | PORT_OCC, 380 376 &ehci->regs->port_status [wIndex]); 381 377 break; 382 378 case USB_PORT_FEAT_C_RESET: ··· 420 416 421 417 /* stop resume signaling */ 422 418 temp = readl (&ehci->regs->port_status [wIndex]); 423 - writel (temp & ~PORT_RESUME, 419 + writel (temp & ~(PORT_RWC_BITS | PORT_RESUME), 424 420 &ehci->regs->port_status [wIndex]); 425 421 retval = handshake ( 426 422 &ehci->regs->port_status [wIndex], ··· 441 437 ehci->reset_done [wIndex] = 0; 442 438 443 439 /* force reset to complete */ 444 - writel (temp & ~PORT_RESET, 440 + writel (temp & ~(PORT_RWC_BITS | PORT_RESET), 445 441 &ehci->regs->port_status [wIndex]); 446 442 /* REVISIT: some hardware needs 550+ usec to clear 447 443 * this bit; seems too long to spin routinely... ··· 504 500 if (temp & PORT_OWNER) 505 501 break; 506 502 503 + temp &= ~PORT_RWC_BITS; 507 504 switch (wValue) { 508 505 case USB_PORT_FEAT_SUSPEND: 509 506 if ((temp & PORT_PE) == 0
+1
drivers/usb/host/ehci.h
··· 263 263 #define PORT_PE (1<<2) /* port enable */ 264 264 #define PORT_CSC (1<<1) /* connect status change */ 265 265 #define PORT_CONNECT (1<<0) /* device connected */ 266 + #define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) 266 267 } __attribute__ ((packed)); 267 268 268 269 /* Appendix C, Debug port ... intended for use with special "debug devices"
+4 -5
drivers/usb/host/ohci-dbg.c
··· 228 228 char **next, 229 229 unsigned *size) 230 230 { 231 - u32 temp, ndp, i; 231 + u32 temp, i; 232 232 233 233 temp = roothub_a (controller); 234 234 if (temp == ~(u32)0) 235 235 return; 236 - ndp = (temp & RH_A_NDP); 237 236 238 237 if (verbose) { 239 238 ohci_dbg_sw (controller, next, size, 240 - "roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d\n", temp, 239 + "roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d(%d)\n", temp, 241 240 ((temp & RH_A_POTPGT) >> 24) & 0xff, 242 241 (temp & RH_A_NOCP) ? " NOCP" : "", 243 242 (temp & RH_A_OCPM) ? " OCPM" : "", 244 243 (temp & RH_A_DT) ? " DT" : "", 245 244 (temp & RH_A_NPS) ? " NPS" : "", 246 245 (temp & RH_A_PSM) ? " PSM" : "", 247 - ndp 246 + (temp & RH_A_NDP), controller->num_ports 248 247 ); 249 248 temp = roothub_b (controller); 250 249 ohci_dbg_sw (controller, next, size, ··· 265 266 ); 266 267 } 267 268 268 - for (i = 0; i < ndp; i++) { 269 + for (i = 0; i < controller->num_ports; i++) { 269 270 temp = roothub_portstatus (controller, i); 270 271 dbg_port_sw (controller, i, temp, next, size); 271 272 }
+8 -6
drivers/usb/host/ohci-hcd.c
··· 382 382 goto sanitize; 383 383 } 384 384 spin_unlock_irqrestore (&ohci->lock, flags); 385 - set_current_state (TASK_UNINTERRUPTIBLE); 386 - schedule_timeout (1); 385 + schedule_timeout_uninterruptible(1); 387 386 goto rescan; 388 387 case ED_IDLE: /* fully unlinked */ 389 388 if (list_empty (&ed->td_list)) { ··· 484 485 // flush the writes 485 486 (void) ohci_readl (ohci, &ohci->regs->control); 486 487 488 + /* Read the number of ports unless overridden */ 489 + if (ohci->num_ports == 0) 490 + ohci->num_ports = roothub_a(ohci) & RH_A_NDP; 491 + 487 492 if (ohci->hcca) 488 493 return 0; 489 494 ··· 564 561 msleep(temp); 565 562 temp = roothub_a (ohci); 566 563 if (!(temp & RH_A_NPS)) { 567 - unsigned ports = temp & RH_A_NDP; 568 - 569 564 /* power down each port */ 570 - for (temp = 0; temp < ports; temp++) 565 + for (temp = 0; temp < ohci->num_ports; temp++) 571 566 ohci_writel (ohci, RH_PS_LSDA, 572 567 &ohci->regs->roothub.portstatus [temp]); 573 568 } ··· 721 720 722 721 if (ints & OHCI_INTR_RD) { 723 722 ohci_vdbg (ohci, "resume detect\n"); 723 + ohci_writel (ohci, OHCI_INTR_RD, &regs->intrstatus); 724 724 if (hcd->state != HC_STATE_QUIESCING) 725 725 schedule_work(&ohci->rh_resume); 726 726 } ··· 863 861 * and that if we try to turn them back on the root hub 864 862 * will respond to CSC processing. 865 863 */ 866 - i = roothub_a (ohci) & RH_A_NDP; 864 + i = ohci->num_ports; 867 865 while (i--) 868 866 ohci_writel (ohci, RH_PS_PSS, 869 867 &ohci->regs->roothub.portstatus [temp]);
+11 -11
drivers/usb/host/ohci-hub.c
··· 184 184 if (status != -EINPROGRESS) 185 185 return status; 186 186 187 - temp = roothub_a (ohci) & RH_A_NDP; 187 + temp = ohci->num_ports; 188 188 enables = 0; 189 189 while (temp--) { 190 190 u32 stat = ohci_readl (ohci, ··· 304 304 ohci_hub_status_data (struct usb_hcd *hcd, char *buf) 305 305 { 306 306 struct ohci_hcd *ohci = hcd_to_ohci (hcd); 307 - int ports, i, changed = 0, length = 1; 307 + int i, changed = 0, length = 1; 308 308 int can_suspend = hcd->can_wakeup; 309 309 unsigned long flags; 310 310 ··· 319 319 goto done; 320 320 } 321 321 322 - ports = roothub_a (ohci) & RH_A_NDP; 323 - if (ports > MAX_ROOT_PORTS) { 324 - ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ports, 322 + /* undocumented erratum seen on at least rev D */ 323 + if ((ohci->flags & OHCI_QUIRK_AMD756) 324 + && (roothub_a (ohci) & RH_A_NDP) > MAX_ROOT_PORTS) { 325 + ohci_warn (ohci, "bogus NDP, rereads as NDP=%d\n", 325 326 ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP); 326 327 /* retry later; "should not happen" */ 327 328 goto done; ··· 333 332 buf [0] = changed = 1; 334 333 else 335 334 buf [0] = 0; 336 - if (ports > 7) { 335 + if (ohci->num_ports > 7) { 337 336 buf [1] = 0; 338 337 length++; 339 338 } 340 339 341 340 /* look at each port */ 342 - for (i = 0; i < ports; i++) { 341 + for (i = 0; i < ohci->num_ports; i++) { 343 342 u32 status = roothub_portstatus (ohci, i); 344 343 345 344 if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC ··· 396 395 struct usb_hub_descriptor *desc 397 396 ) { 398 397 u32 rh = roothub_a (ohci); 399 - int ports = rh & RH_A_NDP; 400 398 u16 temp; 401 399 402 400 desc->bDescriptorType = 0x29; 403 401 desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24; 404 402 desc->bHubContrCurrent = 0; 405 403 406 - desc->bNbrPorts = ports; 407 - temp = 1 + (ports / 8); 404 + desc->bNbrPorts = ohci->num_ports; 405 + temp = 1 + (ohci->num_ports / 8); 408 406 desc->bDescLength = 7 + 2 * temp; 409 407 410 408 temp = 0; ··· 421 421 rh = roothub_b (ohci); 422 422 memset(desc->bitmap, 0xff, sizeof(desc->bitmap)); 423 423 desc->bitmap [0] = rh & RH_B_DR; 424 - if (ports > 7) { 424 + if (ohci->num_ports > 7) { 425 425 desc->bitmap [1] = (rh & RH_B_DR) >> 8; 426 426 desc->bitmap [2] = 0xff; 427 427 } else
+10 -38
drivers/usb/host/ohci-pxa27x.c
··· 75 75 return 0; 76 76 } 77 77 78 - /* 79 - If you select PMM_PERPORT_MODE, you should set the port power 80 - */ 81 - static int pxa27x_ohci_set_port_power( int port ) 82 - { 83 - if ( (pxa27x_ohci_pmm_state==PMM_PERPORT_MODE) 84 - && (port>0) && (port<PXA_UHC_MAX_PORTNUM) ) { 85 - UHCRHPS(port) |= 0x100; 86 - return 0; 87 - } 88 - return -1; 89 - } 90 - 91 - /* 92 - If you select PMM_PERPORT_MODE, you should set the port power 93 - */ 94 - static int pxa27x_ohci_clear_port_power( int port ) 95 - { 96 - if ( (pxa27x_ohci_pmm_state==PMM_PERPORT_MODE) 97 - && (port>0) && (port<PXA_UHC_MAX_PORTNUM) ) { 98 - UHCRHPS(port) |= 0x200; 99 - return 0; 100 - } 101 - 102 - return -1; 103 - } 104 - 105 78 extern int usb_disabled(void); 106 79 107 80 /*-------------------------------------------------------------------------*/ ··· 103 130 Polarity Low to active low. Supply power to USB ports. */ 104 131 UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) & 105 132 ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE); 133 + 134 + pxa27x_ohci_pmm_state = PMM_PERPORT_MODE; 106 135 } 107 136 108 137 UHCHR &= ~UHCHR_SSE; 109 138 110 139 UHCHIE = (UHCHIE_UPRIE | UHCHIE_RWIE); 140 + 141 + /* Clear any OTG Pin Hold */ 142 + if (PSSR & PSSR_OTGPH) 143 + PSSR |= PSSR_OTGPH; 111 144 } 112 145 113 146 static void pxa27x_stop_hc(struct platform_device *dev) ··· 177 198 pxa27x_start_hc(dev); 178 199 179 200 /* Select Power Management Mode */ 180 - pxa27x_ohci_select_pmm( PMM_PERPORT_MODE ); 181 - 182 - /* If choosing PMM_PERPORT_MODE, we should set the port power before we use it. */ 183 - if (pxa27x_ohci_set_port_power(1) < 0) 184 - printk(KERN_ERR "Setting port 1 power failed.\n"); 185 - 186 - if (pxa27x_ohci_clear_port_power(2) < 0) 187 - printk(KERN_ERR "Setting port 2 power failed.\n"); 188 - 189 - if (pxa27x_ohci_clear_port_power(3) < 0) 190 - printk(KERN_ERR "Setting port 3 power failed.\n"); 201 + pxa27x_ohci_select_pmm(pxa27x_ohci_pmm_state); 191 202 192 203 ohci_hcd_init(hcd_to_ohci(hcd)); 193 204 ··· 226 257 int ret; 227 258 228 259 ohci_dbg (ohci, "ohci_pxa27x_start, ohci:%p", ohci); 260 + 261 + /* The value of NDP in roothub_a is incorrect on this hardware */ 262 + ohci->num_ports = 3; 229 263 230 264 if ((ret = ohci_init(ohci)) < 0) 231 265 return ret;
+1
drivers/usb/host/ohci.h
··· 383 383 /* 384 384 * driver state 385 385 */ 386 + int num_ports; 386 387 int load [NUM_INTS]; 387 388 u32 hc_control; /* copy of hc control reg */ 388 389 unsigned long next_statechange; /* suspend/resume */
+22 -40
drivers/usb/host/uhci-hcd.c
··· 97 97 /* to make sure it doesn't hog all of the bandwidth */ 98 98 #define DEPTH_INTERVAL 5 99 99 100 - static inline void restart_timer(struct uhci_hcd *uhci) 101 - { 102 - mod_timer(&uhci->stall_timer, jiffies + msecs_to_jiffies(100)); 103 - } 104 - 105 - #include "uhci-hub.c" 106 100 #include "uhci-debug.c" 107 101 #include "uhci-q.c" 102 + #include "uhci-hub.c" 108 103 109 104 /* 110 105 * Make sure the controller is completely inactive, unable to ··· 155 160 { 156 161 reset_hc(uhci); 157 162 uhci->hc_inaccessible = 1; 158 - del_timer(&uhci->stall_timer); 159 163 } 160 164 161 165 /* ··· 281 287 /* Enable resume-detect interrupts if they work. 282 288 * Then enter Global Suspend mode, still configured. 283 289 */ 284 - int_enable = (resume_detect_interrupts_are_broken(uhci) ? 285 - 0 : USBINTR_RESUME); 290 + uhci->working_RD = 1; 291 + int_enable = USBINTR_RESUME; 292 + if (resume_detect_interrupts_are_broken(uhci)) { 293 + uhci->working_RD = int_enable = 0; 294 + } 286 295 outw(int_enable, uhci->io_addr + USBINTR); 287 296 outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD); 288 297 mb(); ··· 312 315 313 316 uhci->rh_state = new_state; 314 317 uhci->is_stopped = UHCI_IS_STOPPED; 315 - del_timer(&uhci->stall_timer); 316 318 uhci_to_hcd(uhci)->poll_rh = !int_enable; 317 319 318 320 uhci_scan_schedule(uhci, NULL); ··· 331 335 mb(); 332 336 uhci->rh_state = UHCI_RH_RUNNING; 333 337 uhci_to_hcd(uhci)->poll_rh = 1; 334 - restart_timer(uhci); 335 338 } 336 339 337 340 static void wakeup_rh(struct uhci_hcd *uhci) ··· 369 374 mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); 370 375 } 371 376 372 - static void stall_callback(unsigned long _uhci) 373 - { 374 - struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci; 375 - unsigned long flags; 376 - 377 - spin_lock_irqsave(&uhci->lock, flags); 378 - uhci_scan_schedule(uhci, NULL); 379 - check_fsbr(uhci); 380 - 381 - if (!uhci->is_stopped) 382 - restart_timer(uhci); 383 - spin_unlock_irqrestore(&uhci->lock, flags); 384 - } 385 - 386 377 static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) 387 378 { 388 379 struct uhci_hcd *uhci = hcd_to_uhci(hcd); ··· 399 418 "host controller halted, " 400 419 "very bad!\n"); 401 420 hc_died(uhci); 402 - spin_unlock_irqrestore(&uhci->lock, flags); 403 - return IRQ_HANDLED; 421 + 422 + /* Force a callback in case there are 423 + * pending unlinks */ 424 + mod_timer(&hcd->rh_timer, jiffies); 404 425 } 405 426 spin_unlock_irqrestore(&uhci->lock, flags); 406 427 } ··· 410 427 411 428 if (status & USBSTS_RD) 412 429 usb_hcd_poll_rh_status(hcd); 413 - 414 - spin_lock_irqsave(&uhci->lock, flags); 415 - uhci_scan_schedule(uhci, regs); 416 - spin_unlock_irqrestore(&uhci->lock, flags); 430 + else { 431 + spin_lock_irqsave(&uhci->lock, flags); 432 + uhci_scan_schedule(uhci, regs); 433 + spin_unlock_irqrestore(&uhci->lock, flags); 434 + } 417 435 418 436 return IRQ_HANDLED; 419 437 } ··· 579 595 580 596 init_waitqueue_head(&uhci->waitqh); 581 597 582 - init_timer(&uhci->stall_timer); 583 - uhci->stall_timer.function = stall_callback; 584 - uhci->stall_timer.data = (unsigned long) uhci; 585 - 586 598 uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl), 587 599 &dma_handle, 0); 588 600 if (!uhci->fl) { ··· 725 745 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 726 746 727 747 spin_lock_irq(&uhci->lock); 728 - reset_hc(uhci); 748 + if (!uhci->hc_inaccessible) 749 + reset_hc(uhci); 729 750 uhci_scan_schedule(uhci, NULL); 730 751 spin_unlock_irq(&uhci->lock); 731 752 732 - del_timer_sync(&uhci->stall_timer); 733 753 release_uhci(uhci); 734 754 } 735 755 ··· 791 811 */ 792 812 pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); 793 813 uhci->hc_inaccessible = 1; 814 + hcd->poll_rh = 0; 794 815 795 816 /* FIXME: Enable non-PME# remote wakeup? */ 796 817 797 818 done: 798 819 spin_unlock_irq(&uhci->lock); 799 - if (rc == 0) 800 - del_timer_sync(&hcd->rh_timer); 801 820 return rc; 802 821 } 803 822 ··· 829 850 830 851 spin_unlock_irq(&uhci->lock); 831 852 832 - if (hcd->poll_rh) 853 + if (!uhci->working_RD) { 854 + /* Suspended root hub needs to be polled */ 855 + hcd->poll_rh = 1; 833 856 usb_hcd_poll_rh_status(hcd); 857 + } 834 858 return 0; 835 859 } 836 860 #endif
+3 -8
drivers/usb/host/uhci-hcd.h
··· 345 345 346 346 /* 347 347 * This describes the full uhci information. 348 - * 349 - * Note how the "proper" USB information is just 350 - * a subset of what the full implementation needs. 351 348 */ 352 349 struct uhci_hcd { 353 350 ··· 356 359 357 360 struct dma_pool *qh_pool; 358 361 struct dma_pool *td_pool; 359 - 360 - struct usb_bus *bus; 361 362 362 363 struct uhci_td *term_td; /* Terminating TD, see UHCI bug */ 363 364 struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */ ··· 375 380 unsigned int scan_in_progress:1; /* Schedule scan is running */ 376 381 unsigned int need_rescan:1; /* Redo the schedule scan */ 377 382 unsigned int hc_inaccessible:1; /* HC is suspended or dead */ 383 + unsigned int working_RD:1; /* Suspended root hub doesn't 384 + need to be polled */ 378 385 379 386 /* Support for port suspend/resume/reset */ 380 387 unsigned long port_c_suspend; /* Bit-arrays of ports */ ··· 402 405 /* List of URB's awaiting completion callback */ 403 406 struct list_head complete_list; /* P: uhci->lock */ 404 407 405 - int rh_numports; 406 - 407 - struct timer_list stall_timer; 408 + int rh_numports; /* Number of root-hub ports */ 408 409 409 410 wait_queue_head_t waitqh; /* endpoint_disable waiters */ 410 411 };
+6 -5
drivers/usb/host/uhci-hub.c
··· 145 145 { 146 146 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 147 147 unsigned long flags; 148 - int status; 148 + int status = 0; 149 149 150 150 spin_lock_irqsave(&uhci->lock, flags); 151 - if (uhci->hc_inaccessible) { 152 - status = 0; 153 - goto done; 154 - } 155 151 152 + uhci_scan_schedule(uhci, NULL); 153 + if (uhci->hc_inaccessible) 154 + goto done; 155 + check_fsbr(uhci); 156 156 uhci_check_ports(uhci); 157 + 157 158 status = get_hub_status_data(uhci, buf); 158 159 159 160 switch (uhci->rh_state) {
+1 -1
drivers/usb/host/uhci-q.c
··· 33 33 static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci) 34 34 { 35 35 if (uhci->is_stopped) 36 - mod_timer(&uhci->stall_timer, jiffies); 36 + mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); 37 37 uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); 38 38 } 39 39
+20
drivers/usb/input/Kconfig
··· 286 286 287 287 To compile this driver as a module, choose M here: the module will 288 288 be called keyspan_remote. 289 + 290 + config USB_APPLETOUCH 291 + tristate "Apple USB Touchpad support" 292 + depends on USB && INPUT 293 + ---help--- 294 + Say Y here if you want to use an Apple USB Touchpad. 295 + 296 + These are the touchpads that can be found on post-February 2005 297 + Apple Powerbooks (prior models have a Synaptics touchpad connected 298 + to the ADB bus). 299 + 300 + This driver provides a basic mouse driver but can be interfaced 301 + with the synaptics X11 driver to provide acceleration and 302 + scrolling in X11. 303 + 304 + For further information, see 305 + <file:Documentation/input/appletouch.txt>. 306 + 307 + To compile this driver as a module, choose M here: the 308 + module will be called appletouch.
+1
drivers/usb/input/Makefile
··· 41 41 obj-$(CONFIG_USB_ACECAD) += acecad.o 42 42 obj-$(CONFIG_USB_YEALINK) += yealink.o 43 43 obj-$(CONFIG_USB_XPAD) += xpad.o 44 + obj-$(CONFIG_USB_APPLETOUCH) += appletouch.o
+469
drivers/usb/input/appletouch.c
··· 1 + /* 2 + * Apple USB Touchpad (for post-February 2005 PowerBooks) driver 3 + * 4 + * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) 5 + * Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net) 6 + * Copyright (C) 2005 Stelian Pop (stelian@popies.net) 7 + * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de) 8 + * Copyright (C) 2005 Peter Osterlund (petero2@telia.com) 9 + * 10 + * Thanks to Alex Harper <basilisk@foobox.net> for his inputs. 11 + * 12 + * This program is free software; you can redistribute it and/or modify 13 + * it under the terms of the GNU General Public License as published by 14 + * the Free Software Foundation; either version 2 of the License, or 15 + * (at your option) any later version. 16 + * 17 + * This program is distributed in the hope that it will be useful, 18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 + * GNU General Public License for more details. 21 + * 22 + * You should have received a copy of the GNU General Public License 23 + * along with this program; if not, write to the Free Software 24 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25 + * 26 + */ 27 + 28 + #include <linux/config.h> 29 + #include <linux/kernel.h> 30 + #include <linux/errno.h> 31 + #include <linux/init.h> 32 + #include <linux/slab.h> 33 + #include <linux/module.h> 34 + #include <linux/usb.h> 35 + #include <linux/input.h> 36 + #include <linux/usb_input.h> 37 + 38 + /* Apple has powerbooks which have the keyboard with different Product IDs */ 39 + #define APPLE_VENDOR_ID 0x05AC 40 + 41 + #define ATP_DEVICE(prod) \ 42 + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ 43 + USB_DEVICE_ID_MATCH_INT_CLASS | \ 44 + USB_DEVICE_ID_MATCH_INT_PROTOCOL, \ 45 + .idVendor = APPLE_VENDOR_ID, \ 46 + .idProduct = (prod), \ 47 + .bInterfaceClass = 0x03, \ 48 + .bInterfaceProtocol = 0x02 49 + 50 + /* table of devices that work with this driver */ 51 + static struct usb_device_id atp_table [] = { 52 + { ATP_DEVICE(0x020E) }, 53 + { ATP_DEVICE(0x020F) }, 54 + { ATP_DEVICE(0x030A) }, 55 + { ATP_DEVICE(0x030B) }, 56 + { } /* Terminating entry */ 57 + }; 58 + MODULE_DEVICE_TABLE (usb, atp_table); 59 + 60 + /* size of a USB urb transfer */ 61 + #define ATP_DATASIZE 81 62 + 63 + /* 64 + * number of sensors. Note that only 16 instead of 26 X (horizontal) 65 + * sensors exist on 12" and 15" PowerBooks. All models have 16 Y 66 + * (vertical) sensors. 67 + */ 68 + #define ATP_XSENSORS 26 69 + #define ATP_YSENSORS 16 70 + 71 + /* amount of fuzz this touchpad generates */ 72 + #define ATP_FUZZ 16 73 + 74 + /* maximum pressure this driver will report */ 75 + #define ATP_PRESSURE 300 76 + /* 77 + * multiplication factor for the X and Y coordinates. 78 + * We try to keep the touchpad aspect ratio while still doing only simple 79 + * arithmetics. 80 + * The factors below give coordinates like: 81 + * 0 <= x < 960 on 12" and 15" Powerbooks 82 + * 0 <= x < 1600 on 17" Powerbooks 83 + * 0 <= y < 646 84 + */ 85 + #define ATP_XFACT 64 86 + #define ATP_YFACT 43 87 + 88 + /* 89 + * Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is 90 + * ignored. 91 + */ 92 + #define ATP_THRESHOLD 5 93 + 94 + /* Structure to hold all of our device specific stuff */ 95 + struct atp { 96 + struct usb_device * udev; /* usb device */ 97 + struct urb * urb; /* usb request block */ 98 + signed char * data; /* transferred data */ 99 + int open; /* non-zero if opened */ 100 + struct input_dev input; /* input dev */ 101 + int valid; /* are the sensors valid ? */ 102 + int x_old; /* last reported x/y, */ 103 + int y_old; /* used for smoothing */ 104 + /* current value of the sensors */ 105 + signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS]; 106 + /* last value of the sensors */ 107 + signed char xy_old[ATP_XSENSORS + ATP_YSENSORS]; 108 + /* accumulated sensors */ 109 + int xy_acc[ATP_XSENSORS + ATP_YSENSORS]; 110 + }; 111 + 112 + #define dbg_dump(msg, tab) \ 113 + if (debug > 1) { \ 114 + int i; \ 115 + printk("appletouch: %s %lld", msg, (long long)jiffies); \ 116 + for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) \ 117 + printk(" %02x", tab[i]); \ 118 + printk("\n"); \ 119 + } 120 + 121 + #define dprintk(format, a...) \ 122 + do { \ 123 + if (debug) printk(format, ##a); \ 124 + } while (0) 125 + 126 + MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold"); 127 + MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver"); 128 + MODULE_LICENSE("GPL"); 129 + 130 + static int debug = 1; 131 + module_param(debug, int, 0644); 132 + MODULE_PARM_DESC(debug, "Activate debugging output"); 133 + 134 + static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, 135 + int *z, int *fingers) 136 + { 137 + int i; 138 + /* values to calculate mean */ 139 + int pcum = 0, psum = 0; 140 + 141 + *fingers = 0; 142 + 143 + for (i = 0; i < nb_sensors; i++) { 144 + if (xy_sensors[i] < ATP_THRESHOLD) 145 + continue; 146 + if ((i - 1 < 0) || (xy_sensors[i - 1] < ATP_THRESHOLD)) 147 + (*fingers)++; 148 + pcum += xy_sensors[i] * i; 149 + psum += xy_sensors[i]; 150 + } 151 + 152 + if (psum > 0) { 153 + *z = psum; 154 + return pcum * fact / psum; 155 + } 156 + 157 + return 0; 158 + } 159 + 160 + static inline void atp_report_fingers(struct input_dev *input, int fingers) 161 + { 162 + input_report_key(input, BTN_TOOL_FINGER, fingers == 1); 163 + input_report_key(input, BTN_TOOL_DOUBLETAP, fingers == 2); 164 + input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2); 165 + } 166 + 167 + static void atp_complete(struct urb* urb, struct pt_regs* regs) 168 + { 169 + int x, y, x_z, y_z, x_f, y_f; 170 + int retval, i; 171 + struct atp *dev = urb->context; 172 + 173 + switch (urb->status) { 174 + case 0: 175 + /* success */ 176 + break; 177 + case -ECONNRESET: 178 + case -ENOENT: 179 + case -ESHUTDOWN: 180 + /* This urb is terminated, clean up */ 181 + dbg("%s - urb shutting down with status: %d", 182 + __FUNCTION__, urb->status); 183 + return; 184 + default: 185 + dbg("%s - nonzero urb status received: %d", 186 + __FUNCTION__, urb->status); 187 + goto exit; 188 + } 189 + 190 + /* drop incomplete datasets */ 191 + if (dev->urb->actual_length != ATP_DATASIZE) { 192 + dprintk("appletouch: incomplete data package.\n"); 193 + goto exit; 194 + } 195 + 196 + /* reorder the sensors values */ 197 + for (i = 0; i < 8; i++) { 198 + /* X values */ 199 + dev->xy_cur[i ] = dev->data[5 * i + 2]; 200 + dev->xy_cur[i + 8] = dev->data[5 * i + 4]; 201 + dev->xy_cur[i + 16] = dev->data[5 * i + 42]; 202 + if (i < 2) 203 + dev->xy_cur[i + 24] = dev->data[5 * i + 44]; 204 + 205 + /* Y values */ 206 + dev->xy_cur[i + 26] = dev->data[5 * i + 1]; 207 + dev->xy_cur[i + 34] = dev->data[5 * i + 3]; 208 + } 209 + 210 + dbg_dump("sample", dev->xy_cur); 211 + 212 + if (!dev->valid) { 213 + /* first sample */ 214 + dev->valid = 1; 215 + dev->x_old = dev->y_old = -1; 216 + memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); 217 + 218 + /* 17" Powerbooks have 10 extra X sensors */ 219 + for (i = 16; i < ATP_XSENSORS; i++) 220 + if (dev->xy_cur[i]) { 221 + printk("appletouch: 17\" model detected.\n"); 222 + input_set_abs_params(&dev->input, ABS_X, 0, 223 + (ATP_XSENSORS - 1) * 224 + ATP_XFACT - 1, 225 + ATP_FUZZ, 0); 226 + break; 227 + } 228 + 229 + goto exit; 230 + } 231 + 232 + for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { 233 + /* accumulate the change */ 234 + signed char change = dev->xy_old[i] - dev->xy_cur[i]; 235 + dev->xy_acc[i] -= change; 236 + 237 + /* prevent down drifting */ 238 + if (dev->xy_acc[i] < 0) 239 + dev->xy_acc[i] = 0; 240 + } 241 + 242 + memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); 243 + 244 + dbg_dump("accumulator", dev->xy_acc); 245 + 246 + x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS, 247 + ATP_XFACT, &x_z, &x_f); 248 + y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, 249 + ATP_YFACT, &y_z, &y_f); 250 + 251 + if (x && y) { 252 + if (dev->x_old != -1) { 253 + x = (dev->x_old * 3 + x) >> 2; 254 + y = (dev->y_old * 3 + y) >> 2; 255 + dev->x_old = x; 256 + dev->y_old = y; 257 + 258 + if (debug > 1) 259 + printk("appletouch: X: %3d Y: %3d " 260 + "Xz: %3d Yz: %3d\n", 261 + x, y, x_z, y_z); 262 + 263 + input_report_key(&dev->input, BTN_TOUCH, 1); 264 + input_report_abs(&dev->input, ABS_X, x); 265 + input_report_abs(&dev->input, ABS_Y, y); 266 + input_report_abs(&dev->input, ABS_PRESSURE, 267 + min(ATP_PRESSURE, x_z + y_z)); 268 + atp_report_fingers(&dev->input, max(x_f, y_f)); 269 + } 270 + dev->x_old = x; 271 + dev->y_old = y; 272 + } 273 + else if (!x && !y) { 274 + 275 + dev->x_old = dev->y_old = -1; 276 + input_report_key(&dev->input, BTN_TOUCH, 0); 277 + input_report_abs(&dev->input, ABS_PRESSURE, 0); 278 + atp_report_fingers(&dev->input, 0); 279 + 280 + /* reset the accumulator on release */ 281 + memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); 282 + } 283 + 284 + input_report_key(&dev->input, BTN_LEFT, !!dev->data[80]); 285 + 286 + input_sync(&dev->input); 287 + 288 + exit: 289 + retval = usb_submit_urb(dev->urb, GFP_ATOMIC); 290 + if (retval) { 291 + err("%s - usb_submit_urb failed with result %d", 292 + __FUNCTION__, retval); 293 + } 294 + } 295 + 296 + static int atp_open(struct input_dev *input) 297 + { 298 + struct atp *dev = input->private; 299 + 300 + if (usb_submit_urb(dev->urb, GFP_ATOMIC)) 301 + return -EIO; 302 + 303 + dev->open = 1; 304 + return 0; 305 + } 306 + 307 + static void atp_close(struct input_dev *input) 308 + { 309 + struct atp *dev = input->private; 310 + 311 + usb_kill_urb(dev->urb); 312 + dev->open = 0; 313 + } 314 + 315 + static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id) 316 + { 317 + struct atp *dev = NULL; 318 + struct usb_host_interface *iface_desc; 319 + struct usb_endpoint_descriptor *endpoint; 320 + int int_in_endpointAddr = 0; 321 + int i, retval = -ENOMEM; 322 + 323 + /* allocate memory for our device state and initialize it */ 324 + dev = kmalloc(sizeof(struct atp), GFP_KERNEL); 325 + if (dev == NULL) { 326 + err("Out of memory"); 327 + goto err_kmalloc; 328 + } 329 + memset(dev, 0, sizeof(struct atp)); 330 + 331 + dev->udev = interface_to_usbdev(iface); 332 + 333 + /* set up the endpoint information */ 334 + /* use only the first interrupt-in endpoint */ 335 + iface_desc = iface->cur_altsetting; 336 + for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { 337 + endpoint = &iface_desc->endpoint[i].desc; 338 + if (!int_in_endpointAddr && 339 + (endpoint->bEndpointAddress & USB_DIR_IN) && 340 + ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) 341 + == USB_ENDPOINT_XFER_INT)) { 342 + /* we found an interrupt in endpoint */ 343 + int_in_endpointAddr = endpoint->bEndpointAddress; 344 + break; 345 + } 346 + } 347 + if (!int_in_endpointAddr) { 348 + retval = -EIO; 349 + err("Could not find int-in endpoint"); 350 + goto err_endpoint; 351 + } 352 + 353 + /* save our data pointer in this interface device */ 354 + usb_set_intfdata(iface, dev); 355 + 356 + dev->urb = usb_alloc_urb(0, GFP_KERNEL); 357 + if (!dev->urb) { 358 + retval = -ENOMEM; 359 + goto err_usballoc; 360 + } 361 + dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL, 362 + &dev->urb->transfer_dma); 363 + if (!dev->data) { 364 + retval = -ENOMEM; 365 + goto err_usbbufalloc; 366 + } 367 + usb_fill_int_urb(dev->urb, dev->udev, 368 + usb_rcvintpipe(dev->udev, int_in_endpointAddr), 369 + dev->data, ATP_DATASIZE, atp_complete, dev, 1); 370 + 371 + init_input_dev(&dev->input); 372 + dev->input.name = "appletouch"; 373 + dev->input.dev = &iface->dev; 374 + dev->input.private = dev; 375 + dev->input.open = atp_open; 376 + dev->input.close = atp_close; 377 + 378 + usb_to_input_id(dev->udev, &dev->input.id); 379 + 380 + set_bit(EV_ABS, dev->input.evbit); 381 + 382 + /* 383 + * 12" and 15" Powerbooks only have 16 x sensors, 384 + * 17" models are detected later. 385 + */ 386 + input_set_abs_params(&dev->input, ABS_X, 0, 387 + (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0); 388 + input_set_abs_params(&dev->input, ABS_Y, 0, 389 + (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0); 390 + input_set_abs_params(&dev->input, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0); 391 + 392 + set_bit(EV_KEY, dev->input.evbit); 393 + set_bit(BTN_TOUCH, dev->input.keybit); 394 + set_bit(BTN_TOOL_FINGER, dev->input.keybit); 395 + set_bit(BTN_TOOL_DOUBLETAP, dev->input.keybit); 396 + set_bit(BTN_TOOL_TRIPLETAP, dev->input.keybit); 397 + set_bit(BTN_LEFT, dev->input.keybit); 398 + 399 + input_register_device(&dev->input); 400 + 401 + printk(KERN_INFO "input: appletouch connected\n"); 402 + 403 + return 0; 404 + 405 + err_usbbufalloc: 406 + usb_free_urb(dev->urb); 407 + err_usballoc: 408 + usb_set_intfdata(iface, NULL); 409 + err_endpoint: 410 + kfree(dev); 411 + err_kmalloc: 412 + return retval; 413 + } 414 + 415 + static void atp_disconnect(struct usb_interface *iface) 416 + { 417 + struct atp *dev = usb_get_intfdata(iface); 418 + 419 + usb_set_intfdata(iface, NULL); 420 + if (dev) { 421 + usb_kill_urb(dev->urb); 422 + input_unregister_device(&dev->input); 423 + usb_free_urb(dev->urb); 424 + usb_buffer_free(dev->udev, ATP_DATASIZE, 425 + dev->data, dev->urb->transfer_dma); 426 + kfree(dev); 427 + } 428 + printk(KERN_INFO "input: appletouch disconnected\n"); 429 + } 430 + 431 + static int atp_suspend(struct usb_interface *iface, pm_message_t message) 432 + { 433 + struct atp *dev = usb_get_intfdata(iface); 434 + usb_kill_urb(dev->urb); 435 + dev->valid = 0; 436 + return 0; 437 + } 438 + 439 + static int atp_resume(struct usb_interface *iface) 440 + { 441 + struct atp *dev = usb_get_intfdata(iface); 442 + if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC)) 443 + return -EIO; 444 + 445 + return 0; 446 + } 447 + 448 + static struct usb_driver atp_driver = { 449 + .owner = THIS_MODULE, 450 + .name = "appletouch", 451 + .probe = atp_probe, 452 + .disconnect = atp_disconnect, 453 + .suspend = atp_suspend, 454 + .resume = atp_resume, 455 + .id_table = atp_table, 456 + }; 457 + 458 + static int __init atp_init(void) 459 + { 460 + return usb_register(&atp_driver); 461 + } 462 + 463 + static void __exit atp_exit(void) 464 + { 465 + usb_deregister(&atp_driver); 466 + } 467 + 468 + module_init(atp_init); 469 + module_exit(atp_exit);
-2
drivers/usb/input/hid-core.c
··· 1446 1446 1447 1447 #define USB_VENDOR_ID_APPLE 0x05ac 1448 1448 #define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304 1449 - #define USB_DEVICE_ID_APPLE_BLUETOOTH 0x1000 1450 1449 1451 1450 /* 1452 1451 * Alphabetically sorted blacklist by quirk type. ··· 1464 1465 { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE }, 1465 1466 { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE }, 1466 1467 { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE }, 1467 - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_BLUETOOTH, HID_QUIRK_IGNORE }, 1468 1468 { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE }, 1469 1469 { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE }, 1470 1470 { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE },
+37 -5
drivers/usb/misc/sisusbvga/Kconfig
··· 4 4 depends on USB && USB_EHCI_HCD 5 5 ---help--- 6 6 Say Y here if you intend to attach a USB2VGA dongle based on a 7 - Net2280 and a SiS315 chip. 8 - 9 - Note that this device requires a USB 2.0 host controller. It will not 7 + Net2280 and a SiS315 chip. 8 + 9 + Note that this device requires a USB 2.0 host controller. It will not 10 10 work with USB 1.x controllers. 11 11 12 - To compile this driver as a module, choose M here: the module will be 13 - called sisusb. If unsure, say N. 12 + To compile this driver as a module, choose M here; the module will be 13 + called sisusbvga. If unsure, say N. 14 + 15 + config USB_SISUSBVGA_CON 16 + bool "Text console and mode switching support" if USB_SISUSBVGA 17 + depends on VT 18 + select FONT_8x16 19 + ---help--- 20 + Say Y here if you want a VGA text console via the USB dongle or 21 + want to support userland applications that utilize the driver's 22 + display mode switching capabilities. 23 + 24 + Note that this console supports VGA/EGA text mode only. 25 + 26 + By default, the console part of the driver will not kick in when 27 + the driver is initialized. If you want the driver to take over 28 + one or more of the consoles, you need to specify the number of 29 + the first and last consoles (starting at 1) as driver parameters. 30 + 31 + For example, if the driver is compiled as a module: 32 + 33 + modprobe sisusbvga first=1 last=5 34 + 35 + If you use hotplug, add this to your modutils config files with 36 + the "options" keyword, such as eg. 37 + 38 + options sisusbvga first=1 last=5 39 + 40 + If the driver is compiled into the kernel image, the parameters 41 + must be given in the kernel command like, such as 42 + 43 + sisusbvga.first=1 sisusbvga.last=5 44 + 45 + 14 46
+3 -1
drivers/usb/misc/sisusbvga/Makefile
··· 2 2 # Makefile for the sisusb driver (if driver is inside kernel tree). 3 3 # 4 4 5 - obj-$(CONFIG_USB_SISUSBVGA) += sisusb.o 5 + obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga.o 6 + 7 + sisusbvga-objs := sisusb.o sisusb_init.o sisusb_con.o 6 8
+426 -37
drivers/usb/misc/sisusbvga/sisusb.c
··· 1 1 /* 2 2 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles 3 3 * 4 + * Main part 5 + * 4 6 * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria 5 7 * 6 8 * If distributed as part of the Linux kernel, this code is licensed under the ··· 50 48 #include <linux/kref.h> 51 49 #include <linux/usb.h> 52 50 #include <linux/smp_lock.h> 51 + #include <linux/vmalloc.h> 53 52 54 53 #include "sisusb.h" 54 + 55 + #ifdef INCL_SISUSB_CON 56 + #include <linux/font.h> 57 + #endif 55 58 56 59 #define SISUSB_DONTSYNC 57 60 58 61 /* Forward declarations / clean-up routines */ 59 62 63 + #ifdef INCL_SISUSB_CON 64 + int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data); 65 + int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data); 66 + int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data); 67 + int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data); 68 + int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand, u8 myor); 69 + int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor); 70 + int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand); 71 + 72 + int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data); 73 + int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data); 74 + int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data); 75 + int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data); 76 + int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, 77 + u32 dest, int length, size_t *bytes_written); 78 + 79 + int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init); 80 + 81 + extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo); 82 + extern int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo); 83 + 84 + extern void sisusb_init_concode(void); 85 + extern int sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last); 86 + extern void sisusb_console_exit(struct sisusb_usb_data *sisusb); 87 + 88 + extern void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location); 89 + 90 + extern int sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot, 91 + u8 *arg, int cmapsz, int ch512, int dorecalc, 92 + struct vc_data *c, int fh, int uplock); 93 + 94 + static int sisusb_first_vc = 0; 95 + static int sisusb_last_vc = 0; 96 + module_param_named(first, sisusb_first_vc, int, 0); 97 + module_param_named(last, sisusb_last_vc, int, 0); 98 + MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)"); 99 + MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)"); 100 + #endif 101 + 60 102 static struct usb_driver sisusb_driver; 61 103 62 - static DECLARE_MUTEX(disconnect_sem); 104 + DECLARE_MUTEX(disconnect_sem); 63 105 64 106 static void 65 107 sisusb_free_buffers(struct sisusb_usb_data *sisusb) ··· 685 639 686 640 /* The following routines assume being used to transfer byte, word, 687 641 * long etc. 688 - * This means that they assume "data" in machine endianness format. 642 + * This means that 643 + * - the write routines expect "data" in machine endianness format. 644 + * The data will be converted to leXX in sisusb_xxx_packet. 645 + * - the read routines can expect read data in machine-endianess. 689 646 */ 690 647 691 648 static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type, ··· 888 839 if (get_user(swap16, (u16 __user *)userbuffer)) 889 840 return -EFAULT; 890 841 } else 891 - swap16 = (kernbuffer[0] << 8) | kernbuffer[1]; 842 + swap16 = *((u16 *)kernbuffer); 892 843 893 844 ret = sisusb_write_memio_word(sisusb, 894 845 SISUSB_TYPE_MEM, ··· 904 855 if (userbuffer) { 905 856 if (copy_from_user(&buf, userbuffer, 3)) 906 857 return -EFAULT; 907 - 858 + #ifdef __BIG_ENDIAN 908 859 swap32 = (buf[0] << 16) | 909 860 (buf[1] << 8) | 910 861 buf[2]; 862 + #else 863 + swap32 = (buf[2] << 16) | 864 + (buf[1] << 8) | 865 + buf[0]; 866 + #endif 911 867 } else 868 + #ifdef __BIG_ENDIAN 912 869 swap32 = (kernbuffer[0] << 16) | 913 870 (kernbuffer[1] << 8) | 914 871 kernbuffer[2]; 872 + #else 873 + swap32 = (kernbuffer[2] << 16) | 874 + (kernbuffer[1] << 8) | 875 + kernbuffer[0]; 876 + #endif 915 877 916 878 ret = sisusb_write_memio_24bit(sisusb, 917 879 SISUSB_TYPE_MEM, ··· 939 879 if (get_user(swap32, (u32 __user *)userbuffer)) 940 880 return -EFAULT; 941 881 } else 942 - swap32 = (kernbuffer[0] << 24) | 943 - (kernbuffer[1] << 16) | 944 - (kernbuffer[2] << 8) | 945 - kernbuffer[3]; 882 + swap32 = *((u32 *)kernbuffer); 946 883 947 884 ret = sisusb_write_memio_long(sisusb, 948 885 SISUSB_TYPE_MEM, ··· 1061 1004 1062 1005 return ret ? -EIO : 0; 1063 1006 } 1007 + 1008 + /* Remember: Read data in packet is in machine-endianess! So for 1009 + * byte, word, 24bit, long no endian correction is necessary. 1010 + */ 1064 1011 1065 1012 static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type, 1066 1013 u32 addr, u8 *data) ··· 1252 1191 (u16 __user *)userbuffer)) 1253 1192 return -EFAULT; 1254 1193 } else { 1255 - kernbuffer[0] = swap16 >> 8; 1256 - kernbuffer[1] = swap16 & 0xff; 1194 + *((u16 *)kernbuffer) = swap16; 1257 1195 } 1258 1196 } 1259 1197 return ret; ··· 1262 1202 addr, &swap32); 1263 1203 if (!ret) { 1264 1204 (*bytes_read) += 3; 1205 + #ifdef __BIG_ENDIAN 1265 1206 buf[0] = (swap32 >> 16) & 0xff; 1266 1207 buf[1] = (swap32 >> 8) & 0xff; 1267 1208 buf[2] = swap32 & 0xff; 1209 + #else 1210 + buf[2] = (swap32 >> 16) & 0xff; 1211 + buf[1] = (swap32 >> 8) & 0xff; 1212 + buf[0] = swap32 & 0xff; 1213 + #endif 1268 1214 if (userbuffer) { 1269 1215 if (copy_to_user(userbuffer, &buf[0], 3)) 1270 1216 return -EFAULT; ··· 1294 1228 1295 1229 userbuffer += 4; 1296 1230 } else { 1297 - kernbuffer[0] = (swap32 >> 24) & 0xff; 1298 - kernbuffer[1] = (swap32 >> 16) & 0xff; 1299 - kernbuffer[2] = (swap32 >> 8) & 0xff; 1300 - kernbuffer[3] = swap32 & 0xff; 1231 + *((u32 *)kernbuffer) = swap32; 1301 1232 kernbuffer += 4; 1302 1233 } 1303 1234 addr += 4; ··· 1352 1289 1353 1290 /* High level: Gfx (indexed) register access */ 1354 1291 1355 - static int 1292 + #ifdef INCL_SISUSB_CON 1293 + int 1294 + sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data) 1295 + { 1296 + return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data); 1297 + } 1298 + 1299 + int 1300 + sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data) 1301 + { 1302 + return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data); 1303 + } 1304 + #endif 1305 + 1306 + #ifndef INCL_SISUSB_CON 1307 + static 1308 + #endif 1309 + int 1356 1310 sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data) 1357 1311 { 1358 1312 int ret; ··· 1378 1298 return ret; 1379 1299 } 1380 1300 1381 - static int 1301 + #ifndef INCL_SISUSB_CON 1302 + static 1303 + #endif 1304 + int 1382 1305 sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data) 1383 1306 { 1384 1307 int ret; ··· 1390 1307 return ret; 1391 1308 } 1392 1309 1393 - static int 1310 + #ifndef INCL_SISUSB_CON 1311 + static 1312 + #endif 1313 + int 1394 1314 sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, 1395 1315 u8 myand, u8 myor) 1396 1316 { ··· 1422 1336 return ret; 1423 1337 } 1424 1338 1425 - static int 1339 + #ifndef INCL_SISUSB_CON 1340 + static 1341 + #endif 1342 + int 1426 1343 sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor) 1427 1344 { 1428 1345 return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor)); 1429 1346 } 1430 1347 1431 - static int 1348 + #ifndef INCL_SISUSB_CON 1349 + static 1350 + #endif 1351 + int 1432 1352 sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand) 1433 1353 { 1434 1354 return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00)); 1435 1355 } 1356 + 1357 + /* Write/read video ram */ 1358 + 1359 + #ifdef INCL_SISUSB_CON 1360 + int 1361 + sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data) 1362 + { 1363 + return(sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data)); 1364 + } 1365 + 1366 + int 1367 + sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data) 1368 + { 1369 + return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data)); 1370 + } 1371 + 1372 + int 1373 + sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data) 1374 + { 1375 + return(sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data)); 1376 + } 1377 + 1378 + int 1379 + sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data) 1380 + { 1381 + return(sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data)); 1382 + } 1383 + 1384 + int 1385 + sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, 1386 + u32 dest, int length, size_t *bytes_written) 1387 + { 1388 + return(sisusb_write_mem_bulk(sisusb, dest, src, length, NULL, 0, bytes_written)); 1389 + } 1390 + 1391 + #ifdef SISUSBENDIANTEST 1392 + int 1393 + sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest, 1394 + u32 src, int length, size_t *bytes_written) 1395 + { 1396 + return(sisusb_read_mem_bulk(sisusb, src, dest, length, NULL, bytes_written)); 1397 + } 1398 + #endif 1399 + #endif 1400 + 1401 + #ifdef SISUSBENDIANTEST 1402 + static void 1403 + sisusb_testreadwrite(struct sisusb_usb_data *sisusb) 1404 + { 1405 + static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }; 1406 + char destbuffer[10]; 1407 + size_t dummy; 1408 + int i,j; 1409 + 1410 + sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy); 1411 + 1412 + for(i = 1; i <= 7; i++) { 1413 + printk(KERN_DEBUG "sisusb: rwtest %d bytes\n", i); 1414 + sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy); 1415 + for(j = 0; j < i; j++) { 1416 + printk(KERN_DEBUG "sisusb: rwtest read[%d] = %x\n", j, destbuffer[j]); 1417 + } 1418 + } 1419 + } 1420 + #endif 1436 1421 1437 1422 /* access pci config registers (reg numbers 0, 4, 8, etc) */ 1438 1423 ··· 2427 2270 return ret; 2428 2271 } 2429 2272 2273 + 2274 + #ifdef INCL_SISUSB_CON 2275 + 2276 + /* Set up default text mode: 2277 + - Set text mode (0x03) 2278 + - Upload default font 2279 + - Upload user font (if available) 2280 + */ 2281 + 2282 + int 2283 + sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) 2284 + { 2285 + int ret = 0, slot = sisusb->font_slot, i; 2286 + struct font_desc *myfont; 2287 + u8 *tempbuf; 2288 + u16 *tempbufb; 2289 + size_t written; 2290 + static char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer."; 2291 + static char bootlogo[] = "(o_ //\\ V_/_"; 2292 + 2293 + /* sisusb->lock is down */ 2294 + 2295 + if (!sisusb->SiS_Pr) 2296 + return 1; 2297 + 2298 + sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30; 2299 + sisusb->SiS_Pr->sisusb = (void *)sisusb; 2300 + 2301 + /* Set mode 0x03 */ 2302 + SiSUSBSetMode(sisusb->SiS_Pr, 0x03); 2303 + 2304 + if (!(myfont = find_font("VGA8x16"))) 2305 + return 1; 2306 + 2307 + if (!(tempbuf = vmalloc(8192))) 2308 + return 1; 2309 + 2310 + for (i = 0; i < 256; i++) 2311 + memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16); 2312 + 2313 + /* Upload default font */ 2314 + ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, 0, 1, NULL, 16, 0); 2315 + 2316 + vfree(tempbuf); 2317 + 2318 + /* Upload user font (and reset current slot) */ 2319 + if (sisusb->font_backup) { 2320 + ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup, 2321 + 8192, sisusb->font_backup_512, 1, NULL, 2322 + sisusb->font_backup_height, 0); 2323 + if (slot != 2) 2324 + sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1, 2325 + NULL, 16, 0); 2326 + } 2327 + 2328 + if (init && !sisusb->scrbuf) { 2329 + 2330 + if ((tempbuf = vmalloc(8192))) { 2331 + 2332 + i = 4096; 2333 + tempbufb = (u16 *)tempbuf; 2334 + while (i--) 2335 + *(tempbufb++) = 0x0720; 2336 + 2337 + i = 0; 2338 + tempbufb = (u16 *)tempbuf; 2339 + while (bootlogo[i]) { 2340 + *(tempbufb++) = 0x0700 | bootlogo[i++]; 2341 + if (!(i % 4)) 2342 + tempbufb += 76; 2343 + } 2344 + 2345 + i = 0; 2346 + tempbufb = (u16 *)tempbuf + 6; 2347 + while (bootstring[i]) 2348 + *(tempbufb++) = 0x0700 | bootstring[i++]; 2349 + 2350 + ret |= sisusb_copy_memory(sisusb, tempbuf, 2351 + sisusb->vrambase, 8192, &written); 2352 + 2353 + vfree(tempbuf); 2354 + 2355 + } 2356 + 2357 + } else if (sisusb->scrbuf) { 2358 + 2359 + ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf, 2360 + sisusb->vrambase, sisusb->scrbuf_size, &written); 2361 + 2362 + } 2363 + 2364 + if (sisusb->sisusb_cursor_size_from >= 0 && 2365 + sisusb->sisusb_cursor_size_to >= 0) { 2366 + sisusb_setidxreg(sisusb, SISCR, 0x0a, 2367 + sisusb->sisusb_cursor_size_from); 2368 + sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0, 2369 + sisusb->sisusb_cursor_size_to); 2370 + } else { 2371 + sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d); 2372 + sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e); 2373 + sisusb->sisusb_cursor_size_to = -1; 2374 + } 2375 + 2376 + slot = sisusb->sisusb_cursor_loc; 2377 + if(slot < 0) slot = 0; 2378 + 2379 + sisusb->sisusb_cursor_loc = -1; 2380 + sisusb->bad_cursor_pos = 1; 2381 + 2382 + sisusb_set_cursor(sisusb, slot); 2383 + 2384 + sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8)); 2385 + sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff)); 2386 + 2387 + sisusb->textmodedestroyed = 0; 2388 + 2389 + /* sisusb->lock is down */ 2390 + 2391 + return ret; 2392 + } 2393 + 2394 + #endif 2395 + 2430 2396 /* fops */ 2431 2397 2432 2398 static int ··· 2609 2329 } 2610 2330 } 2611 2331 2612 - /* increment usage count for the device */ 2332 + /* Increment usage count for our sisusb */ 2613 2333 kref_get(&sisusb->kref); 2614 2334 2615 2335 sisusb->isopen = 1; ··· 2620 2340 2621 2341 up(&disconnect_sem); 2622 2342 2623 - printk(KERN_DEBUG "sisusbvga[%d]: opened", sisusb->minor); 2624 - 2625 2343 return 0; 2626 2344 } 2627 2345 2628 - static void 2346 + void 2629 2347 sisusb_delete(struct kref *kref) 2630 2348 { 2631 2349 struct sisusb_usb_data *sisusb = to_sisusb_dev(kref); ··· 2637 2359 sisusb->sisusb_dev = NULL; 2638 2360 sisusb_free_buffers(sisusb); 2639 2361 sisusb_free_urbs(sisusb); 2362 + #ifdef INCL_SISUSB_CON 2363 + kfree(sisusb->SiS_Pr); 2364 + #endif 2640 2365 kfree(sisusb); 2641 2366 } 2642 2367 ··· 2675 2394 kref_put(&sisusb->kref, sisusb_delete); 2676 2395 2677 2396 up(&disconnect_sem); 2678 - 2679 - printk(KERN_DEBUG "sisusbvga[%d]: released", myminor); 2680 2397 2681 2398 return 0; 2682 2399 } ··· 3012 2733 int retval, port, length; 3013 2734 u32 address; 3014 2735 2736 + /* All our commands require the device 2737 + * to be initialized. 2738 + */ 2739 + if (!sisusb->devinit) 2740 + return -ENODEV; 2741 + 3015 2742 port = y->data3 - 3016 2743 SISUSB_PCI_PSEUDO_IOPORTBASE + 3017 2744 SISUSB_PCI_IOPORTBASE; ··· 3059 2774 break; 3060 2775 3061 2776 case SUCMD_CLRSCR: 2777 + /* Gfx core must be initialized */ 2778 + if (!sisusb->gfxinit) 2779 + return -ENODEV; 2780 + 3062 2781 length = (y->data0 << 16) | (y->data1 << 8) | y->data2; 3063 2782 address = y->data3 - 3064 2783 SISUSB_PCI_PSEUDO_MEMBASE + ··· 3070 2781 retval = sisusb_clear_vram(sisusb, address, length); 3071 2782 break; 3072 2783 2784 + case SUCMD_HANDLETEXTMODE: 2785 + retval = 0; 2786 + #ifdef INCL_SISUSB_CON 2787 + /* Gfx core must be initialized, SiS_Pr must exist */ 2788 + if (!sisusb->gfxinit || !sisusb->SiS_Pr) 2789 + return -ENODEV; 2790 + 2791 + switch (y->data0) { 2792 + case 0: 2793 + retval = sisusb_reset_text_mode(sisusb, 0); 2794 + break; 2795 + case 1: 2796 + sisusb->textmodedestroyed = 1; 2797 + break; 2798 + } 2799 + #endif 2800 + break; 2801 + 2802 + #ifdef INCL_SISUSB_CON 2803 + case SUCMD_SETMODE: 2804 + /* Gfx core must be initialized, SiS_Pr must exist */ 2805 + if (!sisusb->gfxinit || !sisusb->SiS_Pr) 2806 + return -ENODEV; 2807 + 2808 + retval = 0; 2809 + 2810 + sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30; 2811 + sisusb->SiS_Pr->sisusb = (void *)sisusb; 2812 + 2813 + if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3)) 2814 + retval = -EINVAL; 2815 + 2816 + break; 2817 + 2818 + case SUCMD_SETVESAMODE: 2819 + /* Gfx core must be initialized, SiS_Pr must exist */ 2820 + if (!sisusb->gfxinit || !sisusb->SiS_Pr) 2821 + return -ENODEV; 2822 + 2823 + retval = 0; 2824 + 2825 + sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30; 2826 + sisusb->SiS_Pr->sisusb = (void *)sisusb; 2827 + 2828 + if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3)) 2829 + retval = -EINVAL; 2830 + 2831 + break; 2832 + #endif 2833 + 3073 2834 default: 3074 2835 retval = -EINVAL; 3075 2836 } 3076 2837 3077 - if(retval > 0) 2838 + if (retval > 0) 3078 2839 retval = -EIO; 3079 2840 3080 2841 return retval; ··· 3174 2835 x.sisusb_vramsize = sisusb->vramsize; 3175 2836 x.sisusb_minor = sisusb->minor; 3176 2837 x.sisusb_fbdevactive= 0; 2838 + #ifdef INCL_SISUSB_CON 2839 + x.sisusb_conactive = sisusb->haveconsole ? 1 : 0; 2840 + #else 2841 + x.sisusb_conactive = 0; 2842 + #endif 3177 2843 3178 2844 if (copy_to_user((void __user *)arg, &x, sizeof(x))) 3179 2845 retval = -EFAULT; ··· 3239 2895 }; 3240 2896 3241 2897 static struct usb_class_driver usb_sisusb_class = { 2898 + #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13) 3242 2899 .name = "usb/sisusbvga%d", 3243 - .fops = &usb_sisusb_fops, 3244 2900 .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, 2901 + #else 2902 + .name = "sisusbvga%d", 2903 + #endif 2904 + .fops = &usb_sisusb_fops, 3245 2905 .minor_base = SISUSB_MINOR 3246 2906 }; 3247 2907 ··· 3342 2994 printk(KERN_INFO "sisusbvga[%d]: Allocated %d output buffers\n", 3343 2995 sisusb->minor, sisusb->numobufs); 3344 2996 2997 + #ifdef INCL_SISUSB_CON 2998 + /* Allocate our SiS_Pr */ 2999 + if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) { 3000 + printk(KERN_ERR 3001 + "sisusbvga[%d]: Failed to allocate SiS_Pr\n", 3002 + sisusb->minor); 3003 + } 3004 + #endif 3005 + 3345 3006 /* Do remaining init stuff */ 3346 3007 3347 3008 init_waitqueue_head(&sisusb->wait_q); 3348 3009 3349 3010 usb_set_intfdata(intf, sisusb); 3011 + 3012 + usb_get_dev(sisusb->sisusb_dev); 3013 + 3014 + sisusb->present = 1; 3350 3015 3351 3016 #ifdef SISUSB_OLD_CONFIG_COMPAT 3352 3017 { ··· 3375 3014 sisusb->minor); 3376 3015 else 3377 3016 sisusb->ioctl32registered = 1; 3378 - 3379 3017 } 3380 3018 #endif 3381 3019 3382 - sisusb->present = 1; 3383 - 3384 3020 if (dev->speed == USB_SPEED_HIGH) { 3385 - if (sisusb_init_gfxdevice(sisusb, 1)) 3021 + int initscreen = 1; 3022 + #ifdef INCL_SISUSB_CON 3023 + if (sisusb_first_vc > 0 && 3024 + sisusb_last_vc > 0 && 3025 + sisusb_first_vc <= sisusb_last_vc && 3026 + sisusb_last_vc <= MAX_NR_CONSOLES) 3027 + initscreen = 0; 3028 + #endif 3029 + if (sisusb_init_gfxdevice(sisusb, initscreen)) 3386 3030 printk(KERN_ERR 3387 3031 "sisusbvga[%d]: Failed to early " 3388 3032 "initialize device\n", ··· 3400 3034 sisusb->minor); 3401 3035 3402 3036 sisusb->ready = 1; 3037 + 3038 + #ifdef SISUSBENDIANTEST 3039 + printk(KERN_DEBUG "sisusb: *** RWTEST ***\n"); 3040 + sisusb_testreadwrite(sisusb); 3041 + printk(KERN_DEBUG "sisusb: *** RWTEST END ***\n"); 3042 + #endif 3043 + 3044 + #ifdef INCL_SISUSB_CON 3045 + sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc); 3046 + #endif 3403 3047 3404 3048 return 0; 3405 3049 ··· 3429 3053 struct sisusb_usb_data *sisusb; 3430 3054 int minor; 3431 3055 3432 - down(&disconnect_sem); 3433 - 3434 3056 /* This should *not* happen */ 3435 - if (!(sisusb = usb_get_intfdata(intf))) { 3436 - up(&disconnect_sem); 3057 + if (!(sisusb = usb_get_intfdata(intf))) 3437 3058 return; 3438 - } 3059 + 3060 + #ifdef INCL_SISUSB_CON 3061 + sisusb_console_exit(sisusb); 3062 + #endif 3063 + 3064 + /* The above code doesn't need the disconnect 3065 + * semaphore to be down; its meaning is to 3066 + * protect all other routines from the disconnect 3067 + * case, not the other way round. 3068 + */ 3069 + down(&disconnect_sem); 3439 3070 3440 3071 down(&sisusb->lock); 3441 3072 ··· 3506 3123 { 3507 3124 int retval; 3508 3125 3126 + #ifdef INCL_SISUSB_CON 3127 + sisusb_init_concode(); 3128 + #endif 3129 + 3509 3130 if (!(retval = usb_register(&sisusb_driver))) { 3131 + 3510 3132 printk(KERN_INFO "sisusb: Driver version %d.%d.%d\n", 3511 3133 SISUSB_VERSION, SISUSB_REVISION, SISUSB_PATCHLEVEL); 3512 3134 printk(KERN_INFO 3513 3135 "sisusb: Copyright (C) 2005 Thomas Winischhofer\n"); 3136 + 3514 3137 } 3515 3138 3516 3139 return retval; ··· 3531 3142 module_exit(usb_sisusb_exit); 3532 3143 3533 3144 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>"); 3534 - MODULE_DESCRIPTION("sisusb - Driver for Net2280/SiS315-based USB2VGA dongles"); 3145 + MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles"); 3535 3146 MODULE_LICENSE("GPL"); 3536 3147
+61 -12
drivers/usb/misc/sisusbvga/sisusb.h
··· 46 46 #endif 47 47 #endif 48 48 49 + /* For older kernels, support for text consoles is by default 50 + * off. To ensable text console support, change the following: 51 + */ 52 + #if 0 53 + #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13) 54 + #define CONFIG_USB_SISUSBVGA_CON 55 + #endif 56 + #endif 57 + 49 58 /* Version Information */ 50 59 51 60 #define SISUSB_VERSION 0 52 61 #define SISUSB_REVISION 0 53 - #define SISUSB_PATCHLEVEL 7 62 + #define SISUSB_PATCHLEVEL 8 63 + 64 + /* Include console and mode switching code? */ 65 + 66 + #ifdef CONFIG_USB_SISUSBVGA_CON 67 + #define INCL_SISUSB_CON 1 68 + #endif 69 + 70 + #ifdef INCL_SISUSB_CON 71 + #include <linux/console.h> 72 + #include <linux/vt_kern.h> 73 + #include "sisusb_struct.h" 74 + #endif 54 75 55 76 /* USB related */ 56 77 57 - #define SISUSB_MINOR 133 /* FIXME */ 78 + #define SISUSB_MINOR 133 /* official */ 58 79 59 80 /* Size of the sisusb input/output buffers */ 60 81 #define SISUSB_IBUF_SIZE 0x01000 ··· 152 131 unsigned char gfxinit; /* graphics core initialized? */ 153 132 unsigned short chipid, chipvendor; 154 133 unsigned short chiprevision; 134 + #ifdef INCL_SISUSB_CON 135 + struct SiS_Private *SiS_Pr; 136 + unsigned long scrbuf; 137 + unsigned int scrbuf_size; 138 + int haveconsole, con_first, con_last; 139 + int havethisconsole[MAX_NR_CONSOLES]; 140 + int textmodedestroyed; 141 + unsigned int sisusb_num_columns; /* real number, not vt's idea */ 142 + int cur_start_addr, con_rolled_over; 143 + int sisusb_cursor_loc, bad_cursor_pos; 144 + int sisusb_cursor_size_from; 145 + int sisusb_cursor_size_to; 146 + int current_font_height, current_font_512; 147 + int font_backup_size, font_backup_height, font_backup_512; 148 + char *font_backup; 149 + int font_slot; 150 + struct vc_data *sisusb_display_fg; 151 + int is_gfx; 152 + int con_blanked; 153 + #endif 155 154 }; 156 155 157 156 #define to_sisusb_dev(d) container_of(d, struct sisusb_usb_data, kref) ··· 290 249 291 250 __u32 sisusb_fbdevactive; /* != 0 if framebuffer device active */ 292 251 293 - __u8 sisusb_reserved[32]; /* for future use */ 252 + __u32 sisusb_conactive; /* != 0 if console driver active */ 253 + 254 + __u8 sisusb_reserved[28]; /* for future use */ 294 255 }; 295 256 296 257 struct sisusb_command { ··· 304 261 __u32 data4; /* for future use */ 305 262 }; 306 263 307 - #define SUCMD_GET 0x01 /* for all: data0 = index, data3 = port */ 308 - #define SUCMD_SET 0x02 /* data1 = value */ 309 - #define SUCMD_SETOR 0x03 /* data1 = or */ 310 - #define SUCMD_SETAND 0x04 /* data1 = and */ 311 - #define SUCMD_SETANDOR 0x05 /* data1 = and, data2 = or */ 312 - #define SUCMD_SETMASK 0x06 /* data1 = data, data2 = mask */ 264 + #define SUCMD_GET 0x01 /* for all: data0 = index, data3 = port */ 265 + #define SUCMD_SET 0x02 /* data1 = value */ 266 + #define SUCMD_SETOR 0x03 /* data1 = or */ 267 + #define SUCMD_SETAND 0x04 /* data1 = and */ 268 + #define SUCMD_SETANDOR 0x05 /* data1 = and, data2 = or */ 269 + #define SUCMD_SETMASK 0x06 /* data1 = data, data2 = mask */ 313 270 314 - #define SUCMD_CLRSCR 0x07 /* data0:1:2 = length, data3 = address */ 271 + #define SUCMD_CLRSCR 0x07 /* data0:1:2 = length, data3 = address */ 272 + 273 + #define SUCMD_HANDLETEXTMODE 0x08 /* Reset/destroy text mode */ 274 + 275 + #define SUCMD_SETMODE 0x09 /* Set a display mode (data3 = SiS mode) */ 276 + #define SUCMD_SETVESAMODE 0x0a /* Set a display mode (data3 = VESA mode) */ 315 277 316 278 #define SISUSB_COMMAND _IOWR(0xF3,0x3D,struct sisusb_command) 317 - #define SISUSB_GET_CONFIG_SIZE _IOR(0xF3,0x3E,__u32) 318 - #define SISUSB_GET_CONFIG _IOR(0xF3,0x3F,struct sisusb_info) 279 + #define SISUSB_GET_CONFIG_SIZE _IOR(0xF3,0x3E,__u32) 280 + #define SISUSB_GET_CONFIG _IOR(0xF3,0x3F,struct sisusb_info) 281 + 319 282 320 283 #endif /* SISUSB_H */ 321 284
+1658
drivers/usb/misc/sisusbvga/sisusb_con.c
··· 1 + /* 2 + * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles 3 + * 4 + * VGA text mode console 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 + * Portions based on vgacon.c which are 38 + * Created 28 Sep 1997 by Geert Uytterhoeven 39 + * Rewritten by Martin Mares <mj@ucw.cz>, July 1998 40 + * based on code Copyright (C) 1991, 1992 Linus Torvalds 41 + * 1995 Jay Estabrook 42 + * 43 + * A note on using in_atomic() in here: We can't handle console 44 + * calls from non-schedulable context due to our USB-dependend 45 + * nature. For now, this driver just ignores any calls if it 46 + * detects this state. 47 + * 48 + */ 49 + 50 + #include <linux/config.h> 51 + #include <linux/version.h> 52 + #include <linux/module.h> 53 + #include <linux/kernel.h> 54 + #include <linux/signal.h> 55 + #include <linux/sched.h> 56 + #include <linux/fs.h> 57 + #include <linux/tty.h> 58 + #include <linux/console.h> 59 + #include <linux/string.h> 60 + #include <linux/kd.h> 61 + #include <linux/init.h> 62 + #include <linux/slab.h> 63 + #include <linux/vt_kern.h> 64 + #include <linux/selection.h> 65 + #include <linux/spinlock.h> 66 + #include <linux/kref.h> 67 + #include <linux/smp_lock.h> 68 + #include <linux/ioport.h> 69 + #include <linux/interrupt.h> 70 + #include <linux/vmalloc.h> 71 + 72 + #include "sisusb.h" 73 + 74 + #ifdef INCL_SISUSB_CON 75 + extern int sisusb_setreg(struct sisusb_usb_data *, int, u8); 76 + extern int sisusb_getreg(struct sisusb_usb_data *, int, u8 *); 77 + extern int sisusb_setidxreg(struct sisusb_usb_data *, int, u8, u8); 78 + extern int sisusb_getidxreg(struct sisusb_usb_data *, int, u8, u8 *); 79 + extern int sisusb_setidxregor(struct sisusb_usb_data *, int, u8, u8); 80 + extern int sisusb_setidxregand(struct sisusb_usb_data *, int, u8, u8); 81 + extern int sisusb_setidxregandor(struct sisusb_usb_data *, int, u8, u8, u8); 82 + 83 + extern int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data); 84 + extern int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data); 85 + extern int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data); 86 + extern int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data); 87 + extern int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, 88 + u32 dest, int length, size_t *bytes_written); 89 + 90 + extern void sisusb_delete(struct kref *kref); 91 + extern int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init); 92 + 93 + extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo); 94 + 95 + #define sisusbcon_writew(val, addr) (*(addr) = (val)) 96 + #define sisusbcon_readw(addr) (*(addr)) 97 + #define sisusbcon_memmovew(d, s, c) memmove(d, s, c) 98 + #define sisusbcon_memcpyw(d, s, c) memcpy(d, s, c) 99 + 100 + /* vc_data -> sisusb conversion table */ 101 + static struct sisusb_usb_data *mysisusbs[MAX_NR_CONSOLES]; 102 + 103 + /* Forward declaration */ 104 + static const struct consw sisusb_con; 105 + 106 + extern struct semaphore disconnect_sem; 107 + 108 + static inline void 109 + sisusbcon_memsetw(u16 *s, u16 c, unsigned int count) 110 + { 111 + count /= 2; 112 + while (count--) 113 + sisusbcon_writew(c, s++); 114 + } 115 + 116 + static inline void 117 + sisusb_initialize(struct sisusb_usb_data *sisusb) 118 + { 119 + /* Reset cursor and start address */ 120 + if (sisusb_setidxreg(sisusb, SISCR, 0x0c, 0x00)) 121 + return; 122 + if (sisusb_setidxreg(sisusb, SISCR, 0x0d, 0x00)) 123 + return; 124 + if (sisusb_setidxreg(sisusb, SISCR, 0x0e, 0x00)) 125 + return; 126 + sisusb_setidxreg(sisusb, SISCR, 0x0f, 0x00); 127 + } 128 + 129 + static inline void 130 + sisusbcon_set_start_address(struct sisusb_usb_data *sisusb, struct vc_data *c) 131 + { 132 + sisusb->cur_start_addr = (c->vc_visible_origin - sisusb->scrbuf) / 2; 133 + 134 + sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8)); 135 + sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff)); 136 + } 137 + 138 + void 139 + sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location) 140 + { 141 + if (sisusb->sisusb_cursor_loc == location) 142 + return; 143 + 144 + sisusb->sisusb_cursor_loc = location; 145 + 146 + /* Hardware bug: Text cursor appears twice or not at all 147 + * at some positions. Work around it with the cursor skew 148 + * bits. 149 + */ 150 + 151 + if ((location & 0x0007) == 0x0007) { 152 + sisusb->bad_cursor_pos = 1; 153 + location--; 154 + if (sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0x1f, 0x20)) 155 + return; 156 + } else if (sisusb->bad_cursor_pos) { 157 + if (sisusb_setidxregand(sisusb, SISCR, 0x0b, 0x1f)) 158 + return; 159 + sisusb->bad_cursor_pos = 0; 160 + } 161 + 162 + if (sisusb_setidxreg(sisusb, SISCR, 0x0e, (location >> 8))) 163 + return; 164 + sisusb_setidxreg(sisusb, SISCR, 0x0f, (location & 0xff)); 165 + } 166 + 167 + static inline struct sisusb_usb_data * 168 + sisusb_get_sisusb(unsigned short console) 169 + { 170 + return mysisusbs[console]; 171 + } 172 + 173 + static inline int 174 + sisusb_sisusb_valid(struct sisusb_usb_data *sisusb) 175 + { 176 + if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) 177 + return 0; 178 + 179 + return 1; 180 + } 181 + 182 + static struct sisusb_usb_data * 183 + sisusb_get_sisusb_lock_and_check(unsigned short console) 184 + { 185 + struct sisusb_usb_data *sisusb; 186 + 187 + /* We can't handle console calls in non-schedulable 188 + * context due to our locks and the USB transport. 189 + * So we simply ignore them. This should only affect 190 + * some calls to printk. 191 + */ 192 + if (in_atomic()) 193 + return NULL; 194 + 195 + if (!(sisusb = sisusb_get_sisusb(console))) 196 + return NULL; 197 + 198 + down(&sisusb->lock); 199 + 200 + if (!sisusb_sisusb_valid(sisusb) || 201 + !sisusb->havethisconsole[console]) { 202 + up(&sisusb->lock); 203 + return NULL; 204 + } 205 + 206 + return sisusb; 207 + } 208 + 209 + static int 210 + sisusb_is_inactive(struct vc_data *c, struct sisusb_usb_data *sisusb) 211 + { 212 + if (sisusb->is_gfx || 213 + sisusb->textmodedestroyed || 214 + c->vc_mode != KD_TEXT) 215 + return 1; 216 + 217 + return 0; 218 + } 219 + 220 + /* con_startup console interface routine */ 221 + static const char * 222 + sisusbcon_startup(void) 223 + { 224 + return "SISUSBCON"; 225 + } 226 + 227 + /* con_init console interface routine */ 228 + static void 229 + sisusbcon_init(struct vc_data *c, int init) 230 + { 231 + struct sisusb_usb_data *sisusb; 232 + int cols, rows; 233 + 234 + /* This is called by take_over_console(), 235 + * ie by us/under our control. It is 236 + * only called after text mode and fonts 237 + * are set up/restored. 238 + */ 239 + 240 + down(&disconnect_sem); 241 + 242 + if (!(sisusb = sisusb_get_sisusb(c->vc_num))) { 243 + up(&disconnect_sem); 244 + return; 245 + } 246 + 247 + down(&sisusb->lock); 248 + 249 + if (!sisusb_sisusb_valid(sisusb)) { 250 + up(&sisusb->lock); 251 + up(&disconnect_sem); 252 + return; 253 + } 254 + 255 + c->vc_can_do_color = 1; 256 + 257 + c->vc_complement_mask = 0x7700; 258 + 259 + c->vc_hi_font_mask = sisusb->current_font_512 ? 0x0800 : 0; 260 + 261 + sisusb->haveconsole = 1; 262 + 263 + sisusb->havethisconsole[c->vc_num] = 1; 264 + 265 + /* We only support 640x400 */ 266 + c->vc_scan_lines = 400; 267 + 268 + c->vc_font.height = sisusb->current_font_height; 269 + 270 + /* We only support width = 8 */ 271 + cols = 80; 272 + rows = c->vc_scan_lines / c->vc_font.height; 273 + 274 + /* Increment usage count for our sisusb. 275 + * Doing so saves us from upping/downing 276 + * the disconnect semaphore; we can't 277 + * lose our sisusb until this is undone 278 + * in con_deinit. For all other console 279 + * interface functions, it suffices to 280 + * use sisusb->lock and do a quick check 281 + * of sisusb for device disconnection. 282 + */ 283 + kref_get(&sisusb->kref); 284 + 285 + if (!*c->vc_uni_pagedir_loc) 286 + con_set_default_unimap(c); 287 + 288 + up(&sisusb->lock); 289 + 290 + up(&disconnect_sem); 291 + 292 + if (init) { 293 + c->vc_cols = cols; 294 + c->vc_rows = rows; 295 + } else 296 + vc_resize(c, cols, rows); 297 + } 298 + 299 + /* con_deinit console interface routine */ 300 + static void 301 + sisusbcon_deinit(struct vc_data *c) 302 + { 303 + struct sisusb_usb_data *sisusb; 304 + int i; 305 + 306 + /* This is called by take_over_console() 307 + * and others, ie not under our control. 308 + */ 309 + 310 + down(&disconnect_sem); 311 + 312 + if (!(sisusb = sisusb_get_sisusb(c->vc_num))) { 313 + up(&disconnect_sem); 314 + return; 315 + } 316 + 317 + down(&sisusb->lock); 318 + 319 + /* Clear ourselves in mysisusbs */ 320 + mysisusbs[c->vc_num] = NULL; 321 + 322 + sisusb->havethisconsole[c->vc_num] = 0; 323 + 324 + /* Free our font buffer if all consoles are gone */ 325 + if (sisusb->font_backup) { 326 + for(i = 0; i < MAX_NR_CONSOLES; i++) { 327 + if (sisusb->havethisconsole[c->vc_num]) 328 + break; 329 + } 330 + if (i == MAX_NR_CONSOLES) { 331 + vfree(sisusb->font_backup); 332 + sisusb->font_backup = NULL; 333 + } 334 + } 335 + 336 + up(&sisusb->lock); 337 + 338 + /* decrement the usage count on our sisusb */ 339 + kref_put(&sisusb->kref, sisusb_delete); 340 + 341 + up(&disconnect_sem); 342 + } 343 + 344 + /* interface routine */ 345 + static u8 346 + sisusbcon_build_attr(struct vc_data *c, u8 color, u8 intensity, 347 + u8 blink, u8 underline, u8 reverse) 348 + { 349 + u8 attr = color; 350 + 351 + if (underline) 352 + attr = (attr & 0xf0) | c->vc_ulcolor; 353 + else if (intensity == 0) 354 + attr = (attr & 0xf0) | c->vc_halfcolor; 355 + 356 + if (reverse) 357 + attr = ((attr) & 0x88) | 358 + ((((attr) >> 4) | 359 + ((attr) << 4)) & 0x77); 360 + 361 + if (blink) 362 + attr ^= 0x80; 363 + 364 + if (intensity == 2) 365 + attr ^= 0x08; 366 + 367 + return attr; 368 + } 369 + 370 + /* Interface routine */ 371 + static void 372 + sisusbcon_invert_region(struct vc_data *vc, u16 *p, int count) 373 + { 374 + /* Invert a region. This is called with a pointer 375 + * to the console's internal screen buffer. So we 376 + * simply do the inversion there and rely on 377 + * a call to putc(s) to update the real screen. 378 + */ 379 + 380 + while (count--) { 381 + u16 a = sisusbcon_readw(p); 382 + 383 + a = ((a) & 0x88ff) | 384 + (((a) & 0x7000) >> 4) | 385 + (((a) & 0x0700) << 4); 386 + 387 + sisusbcon_writew(a, p++); 388 + } 389 + } 390 + 391 + #define SISUSB_VADDR(x,y) \ 392 + ((u16 *)c->vc_origin + \ 393 + (y) * sisusb->sisusb_num_columns + \ 394 + (x)) 395 + 396 + #define SISUSB_HADDR(x,y) \ 397 + ((u16 *)(sisusb->vrambase + (c->vc_origin - sisusb->scrbuf)) + \ 398 + (y) * sisusb->sisusb_num_columns + \ 399 + (x)) 400 + 401 + /* Interface routine */ 402 + static void 403 + sisusbcon_putc(struct vc_data *c, int ch, int y, int x) 404 + { 405 + struct sisusb_usb_data *sisusb; 406 + ssize_t written; 407 + 408 + if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num))) 409 + return; 410 + 411 + /* sisusb->lock is down */ 412 + 413 + /* Don't need to put the character into buffer ourselves, 414 + * because the vt does this BEFORE calling us. 415 + */ 416 + #if 0 417 + sisusbcon_writew(ch, SISUSB_VADDR(x, y)); 418 + #endif 419 + 420 + if (sisusb_is_inactive(c, sisusb)) { 421 + up(&sisusb->lock); 422 + return; 423 + } 424 + 425 + 426 + sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y), 427 + (u32)SISUSB_HADDR(x, y), 2, &written); 428 + 429 + up(&sisusb->lock); 430 + } 431 + 432 + /* Interface routine */ 433 + static void 434 + sisusbcon_putcs(struct vc_data *c, const unsigned short *s, 435 + int count, int y, int x) 436 + { 437 + struct sisusb_usb_data *sisusb; 438 + ssize_t written; 439 + u16 *dest; 440 + int i; 441 + 442 + if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num))) 443 + return; 444 + 445 + /* sisusb->lock is down */ 446 + 447 + /* Need to put the characters into the buffer ourselves, 448 + * because the vt does this AFTER calling us. 449 + */ 450 + 451 + dest = SISUSB_VADDR(x, y); 452 + 453 + for (i = count; i > 0; i--) 454 + sisusbcon_writew(sisusbcon_readw(s++), dest++); 455 + 456 + if (sisusb_is_inactive(c, sisusb)) { 457 + up(&sisusb->lock); 458 + return; 459 + } 460 + 461 + sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y), 462 + (u32)SISUSB_HADDR(x, y), count * 2, &written); 463 + 464 + up(&sisusb->lock); 465 + } 466 + 467 + /* Interface routine */ 468 + static void 469 + sisusbcon_clear(struct vc_data *c, int y, int x, int height, int width) 470 + { 471 + struct sisusb_usb_data *sisusb; 472 + u16 eattr = c->vc_video_erase_char; 473 + ssize_t written; 474 + int i, length, cols; 475 + u16 *dest; 476 + 477 + if (width <= 0 || height <= 0) 478 + return; 479 + 480 + if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num))) 481 + return; 482 + 483 + /* sisusb->lock is down */ 484 + 485 + /* Need to clear buffer ourselves, because the vt does 486 + * this AFTER calling us. 487 + */ 488 + 489 + dest = SISUSB_VADDR(x, y); 490 + 491 + cols = sisusb->sisusb_num_columns; 492 + 493 + if (width > cols) 494 + width = cols; 495 + 496 + if (x == 0 && width >= c->vc_cols) { 497 + 498 + sisusbcon_memsetw(dest, eattr, height * cols * 2); 499 + 500 + } else { 501 + 502 + for (i = height; i > 0; i--, dest += cols) 503 + sisusbcon_memsetw(dest, eattr, width * 2); 504 + 505 + } 506 + 507 + if (sisusb_is_inactive(c, sisusb)) { 508 + up(&sisusb->lock); 509 + return; 510 + } 511 + 512 + length = ((height * cols) - x - (cols - width - x)) * 2; 513 + 514 + 515 + sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(x, y), 516 + (u32)SISUSB_HADDR(x, y), length, &written); 517 + 518 + up(&sisusb->lock); 519 + } 520 + 521 + /* Interface routine */ 522 + static void 523 + sisusbcon_bmove(struct vc_data *c, int sy, int sx, 524 + int dy, int dx, int height, int width) 525 + { 526 + struct sisusb_usb_data *sisusb; 527 + ssize_t written; 528 + int cols, length; 529 + #if 0 530 + u16 *src, *dest; 531 + int i; 532 + #endif 533 + 534 + if (width <= 0 || height <= 0) 535 + return; 536 + 537 + if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num))) 538 + return; 539 + 540 + /* sisusb->lock is down */ 541 + 542 + cols = sisusb->sisusb_num_columns; 543 + 544 + /* Don't need to move data outselves, because 545 + * vt does this BEFORE calling us. 546 + * This is only used by vt's insert/deletechar. 547 + */ 548 + #if 0 549 + if (sx == 0 && dx == 0 && width >= c->vc_cols && width <= cols) { 550 + 551 + sisusbcon_memmovew(SISUSB_VADDR(0, dy), SISUSB_VADDR(0, sy), 552 + height * width * 2); 553 + 554 + } else if (dy < sy || (dy == sy && dx < sx)) { 555 + 556 + src = SISUSB_VADDR(sx, sy); 557 + dest = SISUSB_VADDR(dx, dy); 558 + 559 + for (i = height; i > 0; i--) { 560 + sisusbcon_memmovew(dest, src, width * 2); 561 + src += cols; 562 + dest += cols; 563 + } 564 + 565 + } else { 566 + 567 + src = SISUSB_VADDR(sx, sy + height - 1); 568 + dest = SISUSB_VADDR(dx, dy + height - 1); 569 + 570 + for (i = height; i > 0; i--) { 571 + sisusbcon_memmovew(dest, src, width * 2); 572 + src -= cols; 573 + dest -= cols; 574 + } 575 + 576 + } 577 + #endif 578 + 579 + if (sisusb_is_inactive(c, sisusb)) { 580 + up(&sisusb->lock); 581 + return; 582 + } 583 + 584 + length = ((height * cols) - dx - (cols - width - dx)) * 2; 585 + 586 + 587 + sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(dx, dy), 588 + (u32)SISUSB_HADDR(dx, dy), length, &written); 589 + 590 + up(&sisusb->lock); 591 + } 592 + 593 + /* interface routine */ 594 + static int 595 + sisusbcon_switch(struct vc_data *c) 596 + { 597 + struct sisusb_usb_data *sisusb; 598 + ssize_t written; 599 + int length; 600 + 601 + /* Returnvalue 0 means we have fully restored screen, 602 + * and vt doesn't need to call do_update_region(). 603 + * Returnvalue != 0 naturally means the opposite. 604 + */ 605 + 606 + if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num))) 607 + return 0; 608 + 609 + /* sisusb->lock is down */ 610 + 611 + /* Don't write to screen if in gfx mode */ 612 + if (sisusb_is_inactive(c, sisusb)) { 613 + up(&sisusb->lock); 614 + return 0; 615 + } 616 + 617 + /* That really should not happen. It would mean we are 618 + * being called while the vc is using its private buffer 619 + * as origin. 620 + */ 621 + if (c->vc_origin == (unsigned long)c->vc_screenbuf) { 622 + up(&sisusb->lock); 623 + printk(KERN_DEBUG "sisusb: ASSERT ORIGIN != SCREENBUF!\n"); 624 + return 0; 625 + } 626 + 627 + /* Check that we don't copy too much */ 628 + length = min((int)c->vc_screenbuf_size, 629 + (int)(sisusb->scrbuf + sisusb->scrbuf_size - c->vc_origin)); 630 + 631 + /* Restore the screen contents */ 632 + sisusbcon_memcpyw((u16 *)c->vc_origin, (u16 *)c->vc_screenbuf, 633 + length); 634 + 635 + sisusb_copy_memory(sisusb, (unsigned char *)c->vc_origin, 636 + (u32)SISUSB_HADDR(0, 0), 637 + length, &written); 638 + 639 + up(&sisusb->lock); 640 + 641 + return 0; 642 + } 643 + 644 + /* interface routine */ 645 + static void 646 + sisusbcon_save_screen(struct vc_data *c) 647 + { 648 + struct sisusb_usb_data *sisusb; 649 + int length; 650 + 651 + /* Save the current screen contents to vc's private 652 + * buffer. 653 + */ 654 + 655 + if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num))) 656 + return; 657 + 658 + /* sisusb->lock is down */ 659 + 660 + if (sisusb_is_inactive(c, sisusb)) { 661 + up(&sisusb->lock); 662 + return; 663 + } 664 + 665 + /* Check that we don't copy too much */ 666 + length = min((int)c->vc_screenbuf_size, 667 + (int)(sisusb->scrbuf + sisusb->scrbuf_size - c->vc_origin)); 668 + 669 + /* Save the screen contents to vc's private buffer */ 670 + sisusbcon_memcpyw((u16 *)c->vc_screenbuf, (u16 *)c->vc_origin, 671 + length); 672 + 673 + up(&sisusb->lock); 674 + } 675 + 676 + /* interface routine */ 677 + static int 678 + sisusbcon_set_palette(struct vc_data *c, unsigned char *table) 679 + { 680 + struct sisusb_usb_data *sisusb; 681 + int i, j; 682 + 683 + /* Return value not used by vt */ 684 + 685 + if (!CON_IS_VISIBLE(c)) 686 + return -EINVAL; 687 + 688 + if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num))) 689 + return -EINVAL; 690 + 691 + /* sisusb->lock is down */ 692 + 693 + if (sisusb_is_inactive(c, sisusb)) { 694 + up(&sisusb->lock); 695 + return -EINVAL; 696 + } 697 + 698 + for (i = j = 0; i < 16; i++) { 699 + if (sisusb_setreg(sisusb, SISCOLIDX, table[i])) 700 + break; 701 + if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2)) 702 + break; 703 + if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2)) 704 + break; 705 + if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2)) 706 + break; 707 + } 708 + 709 + up(&sisusb->lock); 710 + 711 + return 0; 712 + } 713 + 714 + /* interface routine */ 715 + static int 716 + sisusbcon_blank(struct vc_data *c, int blank, int mode_switch) 717 + { 718 + struct sisusb_usb_data *sisusb; 719 + u8 sr1, cr17, pmreg, cr63; 720 + ssize_t written; 721 + int ret = 0; 722 + 723 + if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num))) 724 + return 0; 725 + 726 + /* sisusb->lock is down */ 727 + 728 + if (mode_switch) 729 + sisusb->is_gfx = blank ? 1 : 0; 730 + 731 + if (sisusb_is_inactive(c, sisusb)) { 732 + up(&sisusb->lock); 733 + return 0; 734 + } 735 + 736 + switch (blank) { 737 + 738 + case 1: /* Normal blanking: Clear screen */ 739 + case -1: 740 + sisusbcon_memsetw((u16 *)c->vc_origin, 741 + c->vc_video_erase_char, 742 + c->vc_screenbuf_size); 743 + sisusb_copy_memory(sisusb, 744 + (unsigned char *)c->vc_origin, 745 + (u32)(sisusb->vrambase + 746 + (c->vc_origin - sisusb->scrbuf)), 747 + c->vc_screenbuf_size, &written); 748 + sisusb->con_blanked = 1; 749 + ret = 1; 750 + break; 751 + 752 + default: /* VESA blanking */ 753 + switch (blank) { 754 + case 0: /* Unblank */ 755 + sr1 = 0x00; 756 + cr17 = 0x80; 757 + pmreg = 0x00; 758 + cr63 = 0x00; 759 + ret = 1; 760 + sisusb->con_blanked = 0; 761 + break; 762 + case VESA_VSYNC_SUSPEND + 1: 763 + sr1 = 0x20; 764 + cr17 = 0x80; 765 + pmreg = 0x80; 766 + cr63 = 0x40; 767 + break; 768 + case VESA_HSYNC_SUSPEND + 1: 769 + sr1 = 0x20; 770 + cr17 = 0x80; 771 + pmreg = 0x40; 772 + cr63 = 0x40; 773 + break; 774 + case VESA_POWERDOWN + 1: 775 + sr1 = 0x20; 776 + cr17 = 0x00; 777 + pmreg = 0xc0; 778 + cr63 = 0x40; 779 + break; 780 + default: 781 + up(&sisusb->lock); 782 + return -EINVAL; 783 + } 784 + 785 + sisusb_setidxregandor(sisusb, SISSR, 0x01, ~0x20, sr1); 786 + sisusb_setidxregandor(sisusb, SISCR, 0x17, 0x7f, cr17); 787 + sisusb_setidxregandor(sisusb, SISSR, 0x1f, 0x3f, pmreg); 788 + sisusb_setidxregandor(sisusb, SISCR, 0x63, 0xbf, cr63); 789 + 790 + } 791 + 792 + up(&sisusb->lock); 793 + 794 + return ret; 795 + } 796 + 797 + /* interface routine */ 798 + static int 799 + sisusbcon_scrolldelta(struct vc_data *c, int lines) 800 + { 801 + struct sisusb_usb_data *sisusb; 802 + int margin = c->vc_size_row * 4; 803 + int ul, we, p, st; 804 + 805 + /* The return value does not seem to be used */ 806 + 807 + if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num))) 808 + return 0; 809 + 810 + /* sisusb->lock is down */ 811 + 812 + if (sisusb_is_inactive(c, sisusb)) { 813 + up(&sisusb->lock); 814 + return 0; 815 + } 816 + 817 + if (!lines) /* Turn scrollback off */ 818 + c->vc_visible_origin = c->vc_origin; 819 + else { 820 + 821 + if (sisusb->con_rolled_over > 822 + (c->vc_scr_end - sisusb->scrbuf) + margin) { 823 + 824 + ul = c->vc_scr_end - sisusb->scrbuf; 825 + we = sisusb->con_rolled_over + c->vc_size_row; 826 + 827 + } else { 828 + 829 + ul = 0; 830 + we = sisusb->scrbuf_size; 831 + 832 + } 833 + 834 + p = (c->vc_visible_origin - sisusb->scrbuf - ul + we) % we + 835 + lines * c->vc_size_row; 836 + 837 + st = (c->vc_origin - sisusb->scrbuf - ul + we) % we; 838 + 839 + if (st < 2 * margin) 840 + margin = 0; 841 + 842 + if (p < margin) 843 + p = 0; 844 + 845 + if (p > st - margin) 846 + p = st; 847 + 848 + c->vc_visible_origin = sisusb->scrbuf + (p + ul) % we; 849 + } 850 + 851 + sisusbcon_set_start_address(sisusb, c); 852 + 853 + up(&sisusb->lock); 854 + 855 + return 1; 856 + } 857 + 858 + /* Interface routine */ 859 + static void 860 + sisusbcon_cursor(struct vc_data *c, int mode) 861 + { 862 + struct sisusb_usb_data *sisusb; 863 + int from, to, baseline; 864 + 865 + if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num))) 866 + return; 867 + 868 + /* sisusb->lock is down */ 869 + 870 + if (sisusb_is_inactive(c, sisusb)) { 871 + up(&sisusb->lock); 872 + return; 873 + } 874 + 875 + if (c->vc_origin != c->vc_visible_origin) { 876 + c->vc_visible_origin = c->vc_origin; 877 + sisusbcon_set_start_address(sisusb, c); 878 + } 879 + 880 + if (mode == CM_ERASE) { 881 + sisusb_setidxregor(sisusb, SISCR, 0x0a, 0x20); 882 + sisusb->sisusb_cursor_size_to = -1; 883 + up(&sisusb->lock); 884 + return; 885 + } 886 + 887 + sisusb_set_cursor(sisusb, (c->vc_pos - sisusb->scrbuf) / 2); 888 + 889 + baseline = c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2); 890 + 891 + switch (c->vc_cursor_type & 0x0f) { 892 + case CUR_BLOCK: from = 1; 893 + to = c->vc_font.height; 894 + break; 895 + case CUR_TWO_THIRDS: from = c->vc_font.height / 3; 896 + to = baseline; 897 + break; 898 + case CUR_LOWER_HALF: from = c->vc_font.height / 2; 899 + to = baseline; 900 + break; 901 + case CUR_LOWER_THIRD: from = (c->vc_font.height * 2) / 3; 902 + to = baseline; 903 + break; 904 + case CUR_NONE: from = 31; 905 + to = 30; 906 + break; 907 + default: 908 + case CUR_UNDERLINE: from = baseline - 1; 909 + to = baseline; 910 + break; 911 + } 912 + 913 + if (sisusb->sisusb_cursor_size_from != from || 914 + sisusb->sisusb_cursor_size_to != to) { 915 + 916 + sisusb_setidxreg(sisusb, SISCR, 0x0a, from); 917 + sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0, to); 918 + 919 + sisusb->sisusb_cursor_size_from = from; 920 + sisusb->sisusb_cursor_size_to = to; 921 + } 922 + 923 + up(&sisusb->lock); 924 + } 925 + 926 + static int 927 + sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb, 928 + int t, int b, int dir, int lines) 929 + { 930 + int cols = sisusb->sisusb_num_columns; 931 + int length = ((b - t) * cols) * 2; 932 + u16 eattr = c->vc_video_erase_char; 933 + ssize_t written; 934 + 935 + /* sisusb->lock is down */ 936 + 937 + /* Scroll an area which does not match the 938 + * visible screen's dimensions. This needs 939 + * to be done separately, as it does not 940 + * use hardware panning. 941 + */ 942 + 943 + switch (dir) { 944 + 945 + case SM_UP: 946 + sisusbcon_memmovew(SISUSB_VADDR(0, t), 947 + SISUSB_VADDR(0, t + lines), 948 + (b - t - lines) * cols * 2); 949 + sisusbcon_memsetw(SISUSB_VADDR(0, b - lines), eattr, 950 + lines * cols * 2); 951 + break; 952 + 953 + case SM_DOWN: 954 + sisusbcon_memmovew(SISUSB_VADDR(0, t + lines), 955 + SISUSB_VADDR(0, t), 956 + (b - t - lines) * cols * 2); 957 + sisusbcon_memsetw(SISUSB_VADDR(0, t), eattr, 958 + lines * cols * 2); 959 + break; 960 + } 961 + 962 + sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(0, t), 963 + (u32)SISUSB_HADDR(0, t), length, &written); 964 + 965 + up(&sisusb->lock); 966 + 967 + return 1; 968 + } 969 + 970 + /* Interface routine */ 971 + static int 972 + sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines) 973 + { 974 + struct sisusb_usb_data *sisusb; 975 + u16 eattr = c->vc_video_erase_char; 976 + ssize_t written; 977 + int copyall = 0; 978 + unsigned long oldorigin; 979 + unsigned int delta = lines * c->vc_size_row; 980 + u32 originoffset; 981 + 982 + /* Returning != 0 means we have done the scrolling successfully. 983 + * Returning 0 makes vt do the scrolling on its own. 984 + * Note that con_scroll is only called if the console is 985 + * visible. In that case, the origin should be our buffer, 986 + * not the vt's private one. 987 + */ 988 + 989 + if (!lines) 990 + return 1; 991 + 992 + if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num))) 993 + return 0; 994 + 995 + /* sisusb->lock is down */ 996 + 997 + if (sisusb_is_inactive(c, sisusb)) { 998 + up(&sisusb->lock); 999 + return 0; 1000 + } 1001 + 1002 + /* Special case */ 1003 + if (t || b != c->vc_rows) 1004 + return sisusbcon_scroll_area(c, sisusb, t, b, dir, lines); 1005 + 1006 + if (c->vc_origin != c->vc_visible_origin) { 1007 + c->vc_visible_origin = c->vc_origin; 1008 + sisusbcon_set_start_address(sisusb, c); 1009 + } 1010 + 1011 + /* limit amount to maximum realistic size */ 1012 + if (lines > c->vc_rows) 1013 + lines = c->vc_rows; 1014 + 1015 + oldorigin = c->vc_origin; 1016 + 1017 + switch (dir) { 1018 + 1019 + case SM_UP: 1020 + 1021 + if (c->vc_scr_end + delta >= 1022 + sisusb->scrbuf + sisusb->scrbuf_size) { 1023 + sisusbcon_memcpyw((u16 *)sisusb->scrbuf, 1024 + (u16 *)(oldorigin + delta), 1025 + c->vc_screenbuf_size - delta); 1026 + c->vc_origin = sisusb->scrbuf; 1027 + sisusb->con_rolled_over = oldorigin - sisusb->scrbuf; 1028 + copyall = 1; 1029 + } else 1030 + c->vc_origin += delta; 1031 + 1032 + sisusbcon_memsetw( 1033 + (u16 *)(c->vc_origin + c->vc_screenbuf_size - delta), 1034 + eattr, delta); 1035 + 1036 + break; 1037 + 1038 + case SM_DOWN: 1039 + 1040 + if (oldorigin - delta < sisusb->scrbuf) { 1041 + sisusbcon_memmovew((u16 *)(sisusb->scrbuf + 1042 + sisusb->scrbuf_size - 1043 + c->vc_screenbuf_size + 1044 + delta), 1045 + (u16 *)oldorigin, 1046 + c->vc_screenbuf_size - delta); 1047 + c->vc_origin = sisusb->scrbuf + 1048 + sisusb->scrbuf_size - 1049 + c->vc_screenbuf_size; 1050 + sisusb->con_rolled_over = 0; 1051 + copyall = 1; 1052 + } else 1053 + c->vc_origin -= delta; 1054 + 1055 + c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size; 1056 + 1057 + scr_memsetw((u16 *)(c->vc_origin), eattr, delta); 1058 + 1059 + break; 1060 + } 1061 + 1062 + originoffset = (u32)(c->vc_origin - sisusb->scrbuf); 1063 + 1064 + if (copyall) 1065 + sisusb_copy_memory(sisusb, 1066 + (char *)c->vc_origin, 1067 + (u32)(sisusb->vrambase + originoffset), 1068 + c->vc_screenbuf_size, &written); 1069 + else if (dir == SM_UP) 1070 + sisusb_copy_memory(sisusb, 1071 + (char *)c->vc_origin + c->vc_screenbuf_size - delta, 1072 + (u32)sisusb->vrambase + originoffset + 1073 + c->vc_screenbuf_size - delta, 1074 + delta, &written); 1075 + else 1076 + sisusb_copy_memory(sisusb, 1077 + (char *)c->vc_origin, 1078 + (u32)(sisusb->vrambase + originoffset), 1079 + delta, &written); 1080 + 1081 + c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size; 1082 + c->vc_visible_origin = c->vc_origin; 1083 + 1084 + sisusbcon_set_start_address(sisusb, c); 1085 + 1086 + c->vc_pos = c->vc_pos - oldorigin + c->vc_origin; 1087 + 1088 + up(&sisusb->lock); 1089 + 1090 + return 1; 1091 + } 1092 + 1093 + /* Interface routine */ 1094 + static int 1095 + sisusbcon_set_origin(struct vc_data *c) 1096 + { 1097 + struct sisusb_usb_data *sisusb; 1098 + 1099 + /* Returning != 0 means we were successful. 1100 + * Returning 0 will vt make to use its own 1101 + * screenbuffer as the origin. 1102 + */ 1103 + 1104 + if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num))) 1105 + return 0; 1106 + 1107 + /* sisusb->lock is down */ 1108 + 1109 + if (sisusb_is_inactive(c, sisusb) || sisusb->con_blanked) { 1110 + up(&sisusb->lock); 1111 + return 0; 1112 + } 1113 + 1114 + c->vc_origin = c->vc_visible_origin = sisusb->scrbuf; 1115 + 1116 + sisusbcon_set_start_address(sisusb, c); 1117 + 1118 + sisusb->con_rolled_over = 0; 1119 + 1120 + up(&sisusb->lock); 1121 + 1122 + return 1; 1123 + } 1124 + 1125 + /* Interface routine */ 1126 + static int 1127 + sisusbcon_resize(struct vc_data *c, unsigned int newcols, unsigned int newrows) 1128 + { 1129 + struct sisusb_usb_data *sisusb; 1130 + int fh; 1131 + 1132 + if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num))) 1133 + return -ENODEV; 1134 + 1135 + fh = sisusb->current_font_height; 1136 + 1137 + up(&sisusb->lock); 1138 + 1139 + /* We are quite unflexible as regards resizing. The vt code 1140 + * handles sizes where the line length isn't equal the pitch 1141 + * quite badly. As regards the rows, our panning tricks only 1142 + * work well if the number of rows equals the visible number 1143 + * of rows. 1144 + */ 1145 + 1146 + if (newcols != 80 || c->vc_scan_lines / fh != newrows) 1147 + return -EINVAL; 1148 + 1149 + return 0; 1150 + } 1151 + 1152 + int 1153 + sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot, 1154 + u8 *arg, int cmapsz, int ch512, int dorecalc, 1155 + struct vc_data *c, int fh, int uplock) 1156 + { 1157 + int font_select = 0x00, i, err = 0; 1158 + u32 offset = 0; 1159 + u8 dummy; 1160 + 1161 + /* sisusb->lock is down */ 1162 + 1163 + /* 1164 + * The default font is kept in slot 0. 1165 + * A user font is loaded in slot 2 (256 ch) 1166 + * or 2+3 (512 ch). 1167 + */ 1168 + 1169 + if ((slot != 0 && slot != 2) || !fh) { 1170 + if (uplock) 1171 + up(&sisusb->lock); 1172 + return -EINVAL; 1173 + } 1174 + 1175 + if (set) 1176 + sisusb->font_slot = slot; 1177 + 1178 + /* Default font is always 256 */ 1179 + if (slot == 0) 1180 + ch512 = 0; 1181 + else 1182 + offset = 4 * cmapsz; 1183 + 1184 + font_select = (slot == 0) ? 0x00 : (ch512 ? 0x0e : 0x0a); 1185 + 1186 + err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x01); /* Reset */ 1187 + err |= sisusb_setidxreg(sisusb, SISSR, 0x02, 0x04); /* Write to plane 2 */ 1188 + err |= sisusb_setidxreg(sisusb, SISSR, 0x04, 0x07); /* Memory mode a0-bf */ 1189 + err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x03); /* Reset */ 1190 + 1191 + if (err) 1192 + goto font_op_error; 1193 + 1194 + err |= sisusb_setidxreg(sisusb, SISGR, 0x04, 0x03); /* Select plane read 2 */ 1195 + err |= sisusb_setidxreg(sisusb, SISGR, 0x05, 0x00); /* Disable odd/even */ 1196 + err |= sisusb_setidxreg(sisusb, SISGR, 0x06, 0x00); /* Address range a0-bf */ 1197 + 1198 + if (err) 1199 + goto font_op_error; 1200 + 1201 + if (arg) { 1202 + if (set) 1203 + for (i = 0; i < cmapsz; i++) { 1204 + err |= sisusb_writeb(sisusb, 1205 + sisusb->vrambase + offset + i, 1206 + arg[i]); 1207 + if (err) 1208 + break; 1209 + } 1210 + else 1211 + for (i = 0; i < cmapsz; i++) { 1212 + err |= sisusb_readb(sisusb, 1213 + sisusb->vrambase + offset + i, 1214 + &arg[i]); 1215 + if (err) 1216 + break; 1217 + } 1218 + 1219 + /* 1220 + * In 512-character mode, the character map is not contiguous if 1221 + * we want to remain EGA compatible -- which we do 1222 + */ 1223 + 1224 + if (ch512) { 1225 + if (set) 1226 + for (i = 0; i < cmapsz; i++) { 1227 + err |= sisusb_writeb(sisusb, 1228 + sisusb->vrambase + offset + 1229 + (2 * cmapsz) + i, 1230 + arg[cmapsz + i]); 1231 + if (err) 1232 + break; 1233 + } 1234 + else 1235 + for (i = 0; i < cmapsz; i++) { 1236 + err |= sisusb_readb(sisusb, 1237 + sisusb->vrambase + offset + 1238 + (2 * cmapsz) + i, 1239 + &arg[cmapsz + i]); 1240 + if (err) 1241 + break; 1242 + } 1243 + } 1244 + } 1245 + 1246 + if (err) 1247 + goto font_op_error; 1248 + 1249 + err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x01); /* Reset */ 1250 + err |= sisusb_setidxreg(sisusb, SISSR, 0x02, 0x03); /* Write to planes 0+1 */ 1251 + err |= sisusb_setidxreg(sisusb, SISSR, 0x04, 0x03); /* Memory mode a0-bf */ 1252 + if (set) 1253 + sisusb_setidxreg(sisusb, SISSR, 0x03, font_select); 1254 + err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x03); /* Reset end */ 1255 + 1256 + if (err) 1257 + goto font_op_error; 1258 + 1259 + err |= sisusb_setidxreg(sisusb, SISGR, 0x04, 0x00); /* Select plane read 0 */ 1260 + err |= sisusb_setidxreg(sisusb, SISGR, 0x05, 0x10); /* Enable odd/even */ 1261 + err |= sisusb_setidxreg(sisusb, SISGR, 0x06, 0x06); /* Address range b8-bf */ 1262 + 1263 + if (err) 1264 + goto font_op_error; 1265 + 1266 + if ((set) && (ch512 != sisusb->current_font_512)) { 1267 + 1268 + /* Font is shared among all our consoles. 1269 + * And so is the hi_font_mask. 1270 + */ 1271 + for (i = 0; i < MAX_NR_CONSOLES; i++) { 1272 + struct vc_data *c = vc_cons[i].d; 1273 + if (c && c->vc_sw == &sisusb_con) 1274 + c->vc_hi_font_mask = ch512 ? 0x0800 : 0; 1275 + } 1276 + 1277 + sisusb->current_font_512 = ch512; 1278 + 1279 + /* color plane enable register: 1280 + 256-char: enable intensity bit 1281 + 512-char: disable intensity bit */ 1282 + sisusb_getreg(sisusb, SISINPSTAT, &dummy); 1283 + sisusb_setreg(sisusb, SISAR, 0x12); 1284 + sisusb_setreg(sisusb, SISAR, ch512 ? 0x07 : 0x0f); 1285 + 1286 + sisusb_getreg(sisusb, SISINPSTAT, &dummy); 1287 + sisusb_setreg(sisusb, SISAR, 0x20); 1288 + sisusb_getreg(sisusb, SISINPSTAT, &dummy); 1289 + } 1290 + 1291 + if (dorecalc) { 1292 + 1293 + /* 1294 + * Adjust the screen to fit a font of a certain height 1295 + */ 1296 + 1297 + unsigned char ovr, vde, fsr; 1298 + int rows = 0, maxscan = 0; 1299 + 1300 + if (c) { 1301 + 1302 + /* Number of video rows */ 1303 + rows = c->vc_scan_lines / fh; 1304 + /* Scan lines to actually display-1 */ 1305 + maxscan = rows * fh - 1; 1306 + 1307 + /*printk(KERN_DEBUG "sisusb recalc rows %d maxscan %d fh %d sl %d\n", 1308 + rows, maxscan, fh, c->vc_scan_lines);*/ 1309 + 1310 + sisusb_getidxreg(sisusb, SISCR, 0x07, &ovr); 1311 + vde = maxscan & 0xff; 1312 + ovr = (ovr & 0xbd) | 1313 + ((maxscan & 0x100) >> 7) | 1314 + ((maxscan & 0x200) >> 3); 1315 + sisusb_setidxreg(sisusb, SISCR, 0x07, ovr); 1316 + sisusb_setidxreg(sisusb, SISCR, 0x12, vde); 1317 + 1318 + } 1319 + 1320 + sisusb_getidxreg(sisusb, SISCR, 0x09, &fsr); 1321 + fsr = (fsr & 0xe0) | (fh - 1); 1322 + sisusb_setidxreg(sisusb, SISCR, 0x09, fsr); 1323 + sisusb->current_font_height = fh; 1324 + 1325 + sisusb->sisusb_cursor_size_from = -1; 1326 + sisusb->sisusb_cursor_size_to = -1; 1327 + 1328 + } 1329 + 1330 + if (uplock) 1331 + up(&sisusb->lock); 1332 + 1333 + if (dorecalc && c) { 1334 + int i, rows = c->vc_scan_lines / fh; 1335 + 1336 + /* Now adjust our consoles' size */ 1337 + 1338 + for (i = 0; i < MAX_NR_CONSOLES; i++) { 1339 + struct vc_data *vc = vc_cons[i].d; 1340 + 1341 + if (vc && vc->vc_sw == &sisusb_con) { 1342 + if (CON_IS_VISIBLE(vc)) { 1343 + vc->vc_sw->con_cursor(vc, CM_DRAW); 1344 + } 1345 + vc->vc_font.height = fh; 1346 + vc_resize(vc, 0, rows); 1347 + } 1348 + } 1349 + } 1350 + 1351 + return 0; 1352 + 1353 + font_op_error: 1354 + if (uplock) 1355 + up(&sisusb->lock); 1356 + 1357 + return -EIO; 1358 + } 1359 + 1360 + /* Interface routine */ 1361 + static int 1362 + sisusbcon_font_set(struct vc_data *c, struct console_font *font, 1363 + unsigned flags) 1364 + { 1365 + struct sisusb_usb_data *sisusb; 1366 + unsigned charcount = font->charcount; 1367 + 1368 + if (font->width != 8 || (charcount != 256 && charcount != 512)) 1369 + return -EINVAL; 1370 + 1371 + if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num))) 1372 + return -ENODEV; 1373 + 1374 + /* sisusb->lock is down */ 1375 + 1376 + /* Save the user-provided font into a buffer. This 1377 + * is used for restoring text mode after quitting 1378 + * from X and for the con_getfont routine. 1379 + */ 1380 + if (sisusb->font_backup) { 1381 + if (sisusb->font_backup_size < charcount) { 1382 + vfree(sisusb->font_backup); 1383 + sisusb->font_backup = NULL; 1384 + } 1385 + } 1386 + 1387 + if (!sisusb->font_backup) 1388 + sisusb->font_backup = vmalloc(charcount * 32); 1389 + 1390 + if (sisusb->font_backup) { 1391 + memcpy(sisusb->font_backup, font->data, charcount * 32); 1392 + sisusb->font_backup_size = charcount; 1393 + sisusb->font_backup_height = font->height; 1394 + sisusb->font_backup_512 = (charcount == 512) ? 1 : 0; 1395 + } 1396 + 1397 + /* do_font_op ups sisusb->lock */ 1398 + 1399 + return sisusbcon_do_font_op(sisusb, 1, 2, font->data, 1400 + 8192, (charcount == 512), 1401 + (!(flags & KD_FONT_FLAG_DONT_RECALC)) ? 1 : 0, 1402 + c, font->height, 1); 1403 + } 1404 + 1405 + /* Interface routine */ 1406 + static int 1407 + sisusbcon_font_get(struct vc_data *c, struct console_font *font) 1408 + { 1409 + struct sisusb_usb_data *sisusb; 1410 + 1411 + if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num))) 1412 + return -ENODEV; 1413 + 1414 + /* sisusb->lock is down */ 1415 + 1416 + font->width = 8; 1417 + font->height = c->vc_font.height; 1418 + font->charcount = 256; 1419 + 1420 + if (!font->data) { 1421 + up(&sisusb->lock); 1422 + return 0; 1423 + } 1424 + 1425 + if (!sisusb->font_backup) { 1426 + up(&sisusb->lock); 1427 + return -ENODEV; 1428 + } 1429 + 1430 + /* Copy 256 chars only, like vgacon */ 1431 + memcpy(font->data, sisusb->font_backup, 256 * 32); 1432 + 1433 + up(&sisusb->lock); 1434 + 1435 + return 0; 1436 + } 1437 + 1438 + /* 1439 + * The console `switch' structure for the sisusb console 1440 + */ 1441 + 1442 + static const struct consw sisusb_con = { 1443 + .owner = THIS_MODULE, 1444 + .con_startup = sisusbcon_startup, 1445 + .con_init = sisusbcon_init, 1446 + .con_deinit = sisusbcon_deinit, 1447 + .con_clear = sisusbcon_clear, 1448 + .con_putc = sisusbcon_putc, 1449 + .con_putcs = sisusbcon_putcs, 1450 + .con_cursor = sisusbcon_cursor, 1451 + .con_scroll = sisusbcon_scroll, 1452 + .con_bmove = sisusbcon_bmove, 1453 + .con_switch = sisusbcon_switch, 1454 + .con_blank = sisusbcon_blank, 1455 + .con_font_set = sisusbcon_font_set, 1456 + .con_font_get = sisusbcon_font_get, 1457 + .con_set_palette = sisusbcon_set_palette, 1458 + .con_scrolldelta = sisusbcon_scrolldelta, 1459 + .con_build_attr = sisusbcon_build_attr, 1460 + .con_invert_region = sisusbcon_invert_region, 1461 + .con_set_origin = sisusbcon_set_origin, 1462 + .con_save_screen = sisusbcon_save_screen, 1463 + .con_resize = sisusbcon_resize, 1464 + }; 1465 + 1466 + /* Our very own dummy console driver */ 1467 + 1468 + static const char *sisusbdummycon_startup(void) 1469 + { 1470 + return "SISUSBVGADUMMY"; 1471 + } 1472 + 1473 + static void sisusbdummycon_init(struct vc_data *vc, int init) 1474 + { 1475 + vc->vc_can_do_color = 1; 1476 + if (init) { 1477 + vc->vc_cols = 80; 1478 + vc->vc_rows = 25; 1479 + } else 1480 + vc_resize(vc, 80, 25); 1481 + } 1482 + 1483 + static int sisusbdummycon_dummy(void) 1484 + { 1485 + return 0; 1486 + } 1487 + 1488 + #define SISUSBCONDUMMY (void *)sisusbdummycon_dummy 1489 + 1490 + const struct consw sisusb_dummy_con = { 1491 + .owner = THIS_MODULE, 1492 + .con_startup = sisusbdummycon_startup, 1493 + .con_init = sisusbdummycon_init, 1494 + .con_deinit = SISUSBCONDUMMY, 1495 + .con_clear = SISUSBCONDUMMY, 1496 + .con_putc = SISUSBCONDUMMY, 1497 + .con_putcs = SISUSBCONDUMMY, 1498 + .con_cursor = SISUSBCONDUMMY, 1499 + .con_scroll = SISUSBCONDUMMY, 1500 + .con_bmove = SISUSBCONDUMMY, 1501 + .con_switch = SISUSBCONDUMMY, 1502 + .con_blank = SISUSBCONDUMMY, 1503 + .con_font_set = SISUSBCONDUMMY, 1504 + .con_font_get = SISUSBCONDUMMY, 1505 + .con_font_default = SISUSBCONDUMMY, 1506 + .con_font_copy = SISUSBCONDUMMY, 1507 + .con_set_palette = SISUSBCONDUMMY, 1508 + .con_scrolldelta = SISUSBCONDUMMY, 1509 + }; 1510 + 1511 + int 1512 + sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) 1513 + { 1514 + int i, ret, minor = sisusb->minor; 1515 + 1516 + down(&disconnect_sem); 1517 + 1518 + down(&sisusb->lock); 1519 + 1520 + /* Erm.. that should not happen */ 1521 + if (sisusb->haveconsole || !sisusb->SiS_Pr) { 1522 + up(&sisusb->lock); 1523 + up(&disconnect_sem); 1524 + return 1; 1525 + } 1526 + 1527 + sisusb->con_first = first; 1528 + sisusb->con_last = last; 1529 + 1530 + if (first > last || 1531 + first > MAX_NR_CONSOLES || 1532 + last > MAX_NR_CONSOLES) { 1533 + up(&sisusb->lock); 1534 + up(&disconnect_sem); 1535 + return 1; 1536 + } 1537 + 1538 + /* If gfxcore not initialized or no consoles given, quit graciously */ 1539 + if (!sisusb->gfxinit || first < 1 || last < 1) { 1540 + up(&sisusb->lock); 1541 + up(&disconnect_sem); 1542 + return 0; 1543 + } 1544 + 1545 + sisusb->sisusb_cursor_loc = -1; 1546 + sisusb->sisusb_cursor_size_from = -1; 1547 + sisusb->sisusb_cursor_size_to = -1; 1548 + 1549 + /* Set up text mode (and upload default font) */ 1550 + if (sisusb_reset_text_mode(sisusb, 1)) { 1551 + up(&sisusb->lock); 1552 + up(&disconnect_sem); 1553 + printk(KERN_ERR 1554 + "sisusbvga[%d]: Failed to set up text mode\n", 1555 + minor); 1556 + return 1; 1557 + } 1558 + 1559 + /* Initialize some gfx registers */ 1560 + sisusb_initialize(sisusb); 1561 + 1562 + for (i = first - 1; i <= last - 1; i++) { 1563 + /* Save sisusb for our interface routines */ 1564 + mysisusbs[i] = sisusb; 1565 + } 1566 + 1567 + /* Initial console setup */ 1568 + sisusb->sisusb_num_columns = 80; 1569 + 1570 + /* Use a 32K buffer (matches b8000-bffff area) */ 1571 + sisusb->scrbuf_size = 32 * 1024; 1572 + 1573 + /* Allocate screen buffer */ 1574 + if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) { 1575 + up(&sisusb->lock); 1576 + up(&disconnect_sem); 1577 + printk(KERN_ERR 1578 + "sisusbvga[%d]: Failed to allocate screen buffer\n", 1579 + minor); 1580 + return 1; 1581 + } 1582 + 1583 + up(&sisusb->lock); 1584 + up(&disconnect_sem); 1585 + 1586 + /* Now grab the desired console(s) */ 1587 + ret = take_over_console(&sisusb_con, first - 1, last - 1, 0); 1588 + 1589 + if (!ret) 1590 + sisusb->haveconsole = 1; 1591 + else { 1592 + for (i = first - 1; i <= last - 1; i++) 1593 + mysisusbs[i] = NULL; 1594 + } 1595 + 1596 + return ret; 1597 + } 1598 + 1599 + void 1600 + sisusb_console_exit(struct sisusb_usb_data *sisusb) 1601 + { 1602 + int i; 1603 + 1604 + /* This is called if the device is disconnected 1605 + * and while disconnect and lock semaphores 1606 + * are up. This should be save because we 1607 + * can't lose our sisusb any other way but by 1608 + * disconnection (and hence, the disconnect 1609 + * sema is for protecting all other access 1610 + * functions from disconnection, not the 1611 + * other way round). 1612 + */ 1613 + 1614 + /* Now what do we do in case of disconnection: 1615 + * One alternative would be to simply call 1616 + * give_up_console(). Nah, not a good idea. 1617 + * give_up_console() is obviously buggy as it 1618 + * only discards the consw pointer from the 1619 + * driver_map, but doesn't adapt vc->vc_sw 1620 + * of the affected consoles. Hence, the next 1621 + * call to any of the console functions will 1622 + * eventually take a trip to oops county. 1623 + * Also, give_up_console for some reason 1624 + * doesn't decrement our module refcount. 1625 + * Instead, we switch our consoles to a private 1626 + * dummy console. This, of course, keeps our 1627 + * refcount up as well, but it works perfectly. 1628 + */ 1629 + 1630 + if (sisusb->haveconsole) { 1631 + for (i = 0; i < MAX_NR_CONSOLES; i++) 1632 + if (sisusb->havethisconsole[i]) 1633 + take_over_console(&sisusb_dummy_con, i, i, 0); 1634 + /* At this point, con_deinit for all our 1635 + * consoles is executed by take_over_console(). 1636 + */ 1637 + sisusb->haveconsole = 0; 1638 + } 1639 + 1640 + vfree((void *)sisusb->scrbuf); 1641 + sisusb->scrbuf = 0; 1642 + 1643 + vfree(sisusb->font_backup); 1644 + sisusb->font_backup = NULL; 1645 + } 1646 + 1647 + void __init sisusb_init_concode(void) 1648 + { 1649 + int i; 1650 + 1651 + for (i = 0; i < MAX_NR_CONSOLES; i++) 1652 + mysisusbs[i] = NULL; 1653 + } 1654 + 1655 + #endif /* INCL_CON */ 1656 + 1657 + 1658 +
+1047
drivers/usb/misc/sisusbvga/sisusb_init.c
··· 1 + /* 2 + * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles 3 + * 4 + * Display mode initializing code 5 + * 6 + * Copyright (C) 2001-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 prior written permission. 23 + * * 24 + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 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/config.h> 40 + #include <linux/version.h> 41 + #include <linux/module.h> 42 + #include <linux/kernel.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 + 50 + #include "sisusb.h" 51 + 52 + #ifdef INCL_SISUSB_CON 53 + 54 + #include "sisusb_init.h" 55 + 56 + /*********************************************/ 57 + /* POINTER INITIALIZATION */ 58 + /*********************************************/ 59 + 60 + static void 61 + SiSUSB_InitPtr(struct SiS_Private *SiS_Pr) 62 + { 63 + SiS_Pr->SiS_ModeResInfo = SiSUSB_ModeResInfo; 64 + SiS_Pr->SiS_StandTable = SiSUSB_StandTable; 65 + 66 + SiS_Pr->SiS_SModeIDTable = SiSUSB_SModeIDTable; 67 + SiS_Pr->SiS_EModeIDTable = SiSUSB_EModeIDTable; 68 + SiS_Pr->SiS_RefIndex = SiSUSB_RefIndex; 69 + SiS_Pr->SiS_CRT1Table = SiSUSB_CRT1Table; 70 + 71 + SiS_Pr->SiS_VCLKData = SiSUSB_VCLKData; 72 + } 73 + 74 + /*********************************************/ 75 + /* HELPER: Get ModeID */ 76 + /*********************************************/ 77 + 78 + unsigned short 79 + SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth) 80 + { 81 + unsigned short ModeIndex = 0; 82 + 83 + switch (HDisplay) 84 + { 85 + case 320: 86 + if (VDisplay == 200) 87 + ModeIndex = ModeIndex_320x200[Depth]; 88 + else if (VDisplay == 240) 89 + ModeIndex = ModeIndex_320x240[Depth]; 90 + break; 91 + case 400: 92 + if (VDisplay == 300) 93 + ModeIndex = ModeIndex_400x300[Depth]; 94 + break; 95 + case 512: 96 + if (VDisplay == 384) 97 + ModeIndex = ModeIndex_512x384[Depth]; 98 + break; 99 + case 640: 100 + if (VDisplay == 480) 101 + ModeIndex = ModeIndex_640x480[Depth]; 102 + else if (VDisplay == 400) 103 + ModeIndex = ModeIndex_640x400[Depth]; 104 + break; 105 + case 720: 106 + if (VDisplay == 480) 107 + ModeIndex = ModeIndex_720x480[Depth]; 108 + else if (VDisplay == 576) 109 + ModeIndex = ModeIndex_720x576[Depth]; 110 + break; 111 + case 768: 112 + if (VDisplay == 576) 113 + ModeIndex = ModeIndex_768x576[Depth]; 114 + break; 115 + case 800: 116 + if (VDisplay == 600) 117 + ModeIndex = ModeIndex_800x600[Depth]; 118 + else if (VDisplay == 480) 119 + ModeIndex = ModeIndex_800x480[Depth]; 120 + break; 121 + case 848: 122 + if (VDisplay == 480) 123 + ModeIndex = ModeIndex_848x480[Depth]; 124 + break; 125 + case 856: 126 + if (VDisplay == 480) 127 + ModeIndex = ModeIndex_856x480[Depth]; 128 + break; 129 + case 960: 130 + if (VDisplay == 540) 131 + ModeIndex = ModeIndex_960x540[Depth]; 132 + else if (VDisplay == 600) 133 + ModeIndex = ModeIndex_960x600[Depth]; 134 + break; 135 + case 1024: 136 + if (VDisplay == 576) 137 + ModeIndex = ModeIndex_1024x576[Depth]; 138 + else if (VDisplay == 768) 139 + ModeIndex = ModeIndex_1024x768[Depth]; 140 + break; 141 + case 1152: 142 + if (VDisplay == 864) 143 + ModeIndex = ModeIndex_1152x864[Depth]; 144 + break; 145 + case 1280: 146 + switch (VDisplay) { 147 + case 720: 148 + ModeIndex = ModeIndex_1280x720[Depth]; 149 + break; 150 + case 768: 151 + ModeIndex = ModeIndex_1280x768[Depth]; 152 + break; 153 + case 1024: 154 + ModeIndex = ModeIndex_1280x1024[Depth]; 155 + break; 156 + } 157 + } 158 + 159 + return ModeIndex; 160 + } 161 + 162 + /*********************************************/ 163 + /* HELPER: SetReg, GetReg */ 164 + /*********************************************/ 165 + 166 + static void 167 + SiS_SetReg(struct SiS_Private *SiS_Pr, unsigned long port, 168 + unsigned short index, unsigned short data) 169 + { 170 + sisusb_setidxreg(SiS_Pr->sisusb, port, index, data); 171 + } 172 + 173 + static void 174 + SiS_SetRegByte(struct SiS_Private *SiS_Pr, unsigned long port, 175 + unsigned short data) 176 + { 177 + sisusb_setreg(SiS_Pr->sisusb, port, data); 178 + } 179 + 180 + static unsigned char 181 + SiS_GetReg(struct SiS_Private *SiS_Pr, unsigned long port, 182 + unsigned short index) 183 + { 184 + u8 data; 185 + 186 + sisusb_getidxreg(SiS_Pr->sisusb, port, index, &data); 187 + 188 + return data; 189 + } 190 + 191 + static unsigned char 192 + SiS_GetRegByte(struct SiS_Private *SiS_Pr, unsigned long port) 193 + { 194 + u8 data; 195 + 196 + sisusb_getreg(SiS_Pr->sisusb, port, &data); 197 + 198 + return data; 199 + } 200 + 201 + static void 202 + SiS_SetRegANDOR(struct SiS_Private *SiS_Pr, unsigned long port, 203 + unsigned short index, unsigned short DataAND, 204 + unsigned short DataOR) 205 + { 206 + sisusb_setidxregandor(SiS_Pr->sisusb, port, index, DataAND, DataOR); 207 + } 208 + 209 + static void 210 + SiS_SetRegAND(struct SiS_Private *SiS_Pr, unsigned long port, 211 + unsigned short index, unsigned short DataAND) 212 + { 213 + sisusb_setidxregand(SiS_Pr->sisusb, port, index, DataAND); 214 + } 215 + 216 + static void 217 + SiS_SetRegOR(struct SiS_Private *SiS_Pr,unsigned long port, 218 + unsigned short index, unsigned short DataOR) 219 + { 220 + sisusb_setidxregor(SiS_Pr->sisusb, port, index, DataOR); 221 + } 222 + 223 + /*********************************************/ 224 + /* HELPER: DisplayOn, DisplayOff */ 225 + /*********************************************/ 226 + 227 + static void 228 + SiS_DisplayOn(struct SiS_Private *SiS_Pr) 229 + { 230 + SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0xDF); 231 + } 232 + 233 + /*********************************************/ 234 + /* HELPER: Init Port Addresses */ 235 + /*********************************************/ 236 + 237 + void 238 + SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr) 239 + { 240 + SiS_Pr->SiS_P3c4 = BaseAddr + 0x14; 241 + SiS_Pr->SiS_P3d4 = BaseAddr + 0x24; 242 + SiS_Pr->SiS_P3c0 = BaseAddr + 0x10; 243 + SiS_Pr->SiS_P3ce = BaseAddr + 0x1e; 244 + SiS_Pr->SiS_P3c2 = BaseAddr + 0x12; 245 + SiS_Pr->SiS_P3ca = BaseAddr + 0x1a; 246 + SiS_Pr->SiS_P3c6 = BaseAddr + 0x16; 247 + SiS_Pr->SiS_P3c7 = BaseAddr + 0x17; 248 + SiS_Pr->SiS_P3c8 = BaseAddr + 0x18; 249 + SiS_Pr->SiS_P3c9 = BaseAddr + 0x19; 250 + SiS_Pr->SiS_P3cb = BaseAddr + 0x1b; 251 + SiS_Pr->SiS_P3cc = BaseAddr + 0x1c; 252 + SiS_Pr->SiS_P3cd = BaseAddr + 0x1d; 253 + SiS_Pr->SiS_P3da = BaseAddr + 0x2a; 254 + SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04; 255 + } 256 + 257 + /*********************************************/ 258 + /* HELPER: GetSysFlags */ 259 + /*********************************************/ 260 + 261 + static void 262 + SiS_GetSysFlags(struct SiS_Private *SiS_Pr) 263 + { 264 + SiS_Pr->SiS_MyCR63 = 0x63; 265 + } 266 + 267 + /*********************************************/ 268 + /* HELPER: Init PCI & Engines */ 269 + /*********************************************/ 270 + 271 + static void 272 + SiSInitPCIetc(struct SiS_Private *SiS_Pr) 273 + { 274 + SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x20, 0xa1); 275 + /* - Enable 2D (0x40) 276 + * - Enable 3D (0x02) 277 + * - Enable 3D vertex command fetch (0x10) 278 + * - Enable 3D command parser (0x08) 279 + * - Enable 3D G/L transformation engine (0x80) 280 + */ 281 + SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1E, 0xDA); 282 + } 283 + 284 + /*********************************************/ 285 + /* HELPER: SET SEGMENT REGISTERS */ 286 + /*********************************************/ 287 + 288 + static void 289 + SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value) 290 + { 291 + unsigned short temp; 292 + 293 + value &= 0x00ff; 294 + temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0xf0; 295 + temp |= (value >> 4); 296 + SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp); 297 + temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0xf0; 298 + temp |= (value & 0x0f); 299 + SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp); 300 + } 301 + 302 + static void 303 + SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value) 304 + { 305 + unsigned short temp; 306 + 307 + value &= 0x00ff; 308 + temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0x0f; 309 + temp |= (value & 0xf0); 310 + SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp); 311 + temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0x0f; 312 + temp |= (value << 4); 313 + SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp); 314 + } 315 + 316 + static void 317 + SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value) 318 + { 319 + SiS_SetSegRegLower(SiS_Pr, value); 320 + SiS_SetSegRegUpper(SiS_Pr, value); 321 + } 322 + 323 + static void 324 + SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr) 325 + { 326 + SiS_SetSegmentReg(SiS_Pr, 0); 327 + } 328 + 329 + static void 330 + SiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value) 331 + { 332 + unsigned short temp = value >> 8; 333 + 334 + temp &= 0x07; 335 + temp |= (temp << 4); 336 + SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1d, temp); 337 + SiS_SetSegmentReg(SiS_Pr, value); 338 + } 339 + 340 + static void 341 + SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr) 342 + { 343 + SiS_SetSegmentRegOver(SiS_Pr, 0); 344 + } 345 + 346 + static void 347 + SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr) 348 + { 349 + SiS_ResetSegmentReg(SiS_Pr); 350 + SiS_ResetSegmentRegOver(SiS_Pr); 351 + } 352 + 353 + /*********************************************/ 354 + /* HELPER: SearchModeID */ 355 + /*********************************************/ 356 + 357 + static int 358 + SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo, 359 + unsigned short *ModeIdIndex) 360 + { 361 + if ((*ModeNo) <= 0x13) { 362 + 363 + if ((*ModeNo) != 0x03) 364 + return 0; 365 + 366 + (*ModeIdIndex) = 0; 367 + 368 + } else { 369 + 370 + for(*ModeIdIndex = 0; ;(*ModeIdIndex)++) { 371 + 372 + if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == (*ModeNo)) 373 + break; 374 + 375 + if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF) 376 + return 0; 377 + } 378 + 379 + } 380 + 381 + return 1; 382 + } 383 + 384 + /*********************************************/ 385 + /* HELPER: ENABLE CRT1 */ 386 + /*********************************************/ 387 + 388 + static void 389 + SiS_HandleCRT1(struct SiS_Private *SiS_Pr) 390 + { 391 + /* Enable CRT1 gating */ 392 + SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, SiS_Pr->SiS_MyCR63, 0xbf); 393 + } 394 + 395 + /*********************************************/ 396 + /* HELPER: GetColorDepth */ 397 + /*********************************************/ 398 + 399 + static unsigned short 400 + SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 401 + unsigned short ModeIdIndex) 402 + { 403 + static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8}; 404 + unsigned short modeflag; 405 + short index; 406 + 407 + if (ModeNo <= 0x13) { 408 + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; 409 + } else { 410 + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; 411 + } 412 + 413 + index = (modeflag & ModeTypeMask) - ModeEGA; 414 + if (index < 0) index = 0; 415 + return ColorDepth[index]; 416 + } 417 + 418 + /*********************************************/ 419 + /* HELPER: GetOffset */ 420 + /*********************************************/ 421 + 422 + static unsigned short 423 + SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 424 + unsigned short ModeIdIndex, unsigned short rrti) 425 + { 426 + unsigned short xres, temp, colordepth, infoflag; 427 + 428 + infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag; 429 + xres = SiS_Pr->SiS_RefIndex[rrti].XRes; 430 + 431 + colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex); 432 + 433 + temp = xres / 16; 434 + 435 + if (infoflag & InterlaceMode) 436 + temp <<= 1; 437 + 438 + temp *= colordepth; 439 + 440 + if (xres % 16) 441 + temp += (colordepth >> 1); 442 + 443 + return temp; 444 + } 445 + 446 + /*********************************************/ 447 + /* SEQ */ 448 + /*********************************************/ 449 + 450 + static void 451 + SiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex) 452 + { 453 + unsigned char SRdata; 454 + int i; 455 + 456 + SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x00, 0x03); 457 + 458 + SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20; 459 + SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, SRdata); 460 + 461 + for(i = 2; i <= 4; i++) { 462 + SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i-1]; 463 + SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, SRdata); 464 + } 465 + } 466 + 467 + /*********************************************/ 468 + /* MISC */ 469 + /*********************************************/ 470 + 471 + static void 472 + SiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex) 473 + { 474 + unsigned char Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC; 475 + 476 + SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, Miscdata); 477 + } 478 + 479 + /*********************************************/ 480 + /* CRTC */ 481 + /*********************************************/ 482 + 483 + static void 484 + SiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex) 485 + { 486 + unsigned char CRTCdata; 487 + unsigned short i; 488 + 489 + SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, 0x11, 0x7f); 490 + 491 + for(i = 0; i <= 0x18; i++) { 492 + CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i]; 493 + SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, i, CRTCdata); 494 + } 495 + } 496 + 497 + /*********************************************/ 498 + /* ATT */ 499 + /*********************************************/ 500 + 501 + static void 502 + SiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex) 503 + { 504 + unsigned char ARdata; 505 + unsigned short i; 506 + 507 + for(i = 0; i <= 0x13; i++) { 508 + ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i]; 509 + SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da); 510 + SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, i); 511 + SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, ARdata); 512 + } 513 + SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da); 514 + SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x14); 515 + SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x00); 516 + 517 + SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da); 518 + SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x20); 519 + SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da); 520 + } 521 + 522 + /*********************************************/ 523 + /* GRC */ 524 + /*********************************************/ 525 + 526 + static void 527 + SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex) 528 + { 529 + unsigned char GRdata; 530 + unsigned short i; 531 + 532 + for(i = 0; i <= 0x08; i++) { 533 + GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i]; 534 + SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3ce, i, GRdata); 535 + } 536 + 537 + if (SiS_Pr->SiS_ModeType > ModeVGA) { 538 + /* 256 color disable */ 539 + SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3ce, 0x05, 0xBF); 540 + } 541 + } 542 + 543 + /*********************************************/ 544 + /* CLEAR EXTENDED REGISTERS */ 545 + /*********************************************/ 546 + 547 + static void 548 + SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo) 549 + { 550 + int i; 551 + 552 + for(i = 0x0A; i <= 0x0E; i++) { 553 + SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, 0x00); 554 + } 555 + 556 + SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x37, 0xFE); 557 + } 558 + 559 + /*********************************************/ 560 + /* Get rate index */ 561 + /*********************************************/ 562 + 563 + static unsigned short 564 + SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 565 + unsigned short ModeIdIndex) 566 + { 567 + unsigned short rrti, i, index, temp; 568 + 569 + if (ModeNo <= 0x13) 570 + return 0xFFFF; 571 + 572 + index = SiS_GetReg(SiS_Pr,SiS_Pr->SiS_P3d4, 0x33) & 0x0F; 573 + if (index > 0) index--; 574 + 575 + rrti = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex; 576 + ModeNo = SiS_Pr->SiS_RefIndex[rrti].ModeID; 577 + 578 + i = 0; 579 + do { 580 + if (SiS_Pr->SiS_RefIndex[rrti + i].ModeID != ModeNo) 581 + break; 582 + 583 + temp = SiS_Pr->SiS_RefIndex[rrti + i].Ext_InfoFlag & ModeTypeMask; 584 + if (temp < SiS_Pr->SiS_ModeType) 585 + break; 586 + 587 + i++; 588 + index--; 589 + } while(index != 0xFFFF); 590 + 591 + i--; 592 + 593 + return (rrti + i); 594 + } 595 + 596 + /*********************************************/ 597 + /* SYNC */ 598 + /*********************************************/ 599 + 600 + static void 601 + SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short rrti) 602 + { 603 + unsigned short sync = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag >> 8; 604 + sync &= 0xC0; 605 + sync |= 0x2f; 606 + SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, sync); 607 + } 608 + 609 + /*********************************************/ 610 + /* CRTC/2 */ 611 + /*********************************************/ 612 + 613 + static void 614 + SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 615 + unsigned short ModeIdIndex, unsigned short rrti) 616 + { 617 + unsigned char index; 618 + unsigned short temp, i, j, modeflag; 619 + 620 + SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4,0x11,0x7f); 621 + 622 + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; 623 + 624 + index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRT1CRTC; 625 + 626 + for(i = 0,j = 0; i <= 7; i++, j++) { 627 + SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j, 628 + SiS_Pr->SiS_CRT1Table[index].CR[i]); 629 + } 630 + for(j = 0x10; i <= 10; i++, j++) { 631 + SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j, 632 + SiS_Pr->SiS_CRT1Table[index].CR[i]); 633 + } 634 + for(j = 0x15; i <= 12; i++, j++) { 635 + SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j, 636 + SiS_Pr->SiS_CRT1Table[index].CR[i]); 637 + } 638 + for(j = 0x0A; i <= 15; i++, j++) { 639 + SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, j, 640 + SiS_Pr->SiS_CRT1Table[index].CR[i]); 641 + } 642 + 643 + temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0; 644 + SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4, 0x0E, temp); 645 + 646 + temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5; 647 + if (modeflag & DoubleScanMode) temp |= 0x80; 648 + SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x09, 0x5F, temp); 649 + 650 + if (SiS_Pr->SiS_ModeType > ModeVGA) 651 + SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x14, 0x4F); 652 + } 653 + 654 + /*********************************************/ 655 + /* OFFSET & PITCH */ 656 + /*********************************************/ 657 + /* (partly overruled by SetPitch() in XF86) */ 658 + /*********************************************/ 659 + 660 + static void 661 + SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 662 + unsigned short ModeIdIndex, unsigned short rrti) 663 + { 664 + unsigned short du = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, rrti); 665 + unsigned short infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag; 666 + unsigned short temp; 667 + 668 + temp = (du >> 8) & 0x0f; 669 + SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0E, 0xF0, temp); 670 + 671 + SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x13, (du & 0xFF)); 672 + 673 + if (infoflag & InterlaceMode) du >>= 1; 674 + 675 + du <<= 5; 676 + temp = (du >> 8) & 0xff; 677 + if (du & 0xff) temp++; 678 + temp++; 679 + SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x10, temp); 680 + } 681 + 682 + /*********************************************/ 683 + /* VCLK */ 684 + /*********************************************/ 685 + 686 + static void 687 + SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 688 + unsigned short rrti) 689 + { 690 + unsigned short index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK; 691 + unsigned short clka = SiS_Pr->SiS_VCLKData[index].SR2B; 692 + unsigned short clkb = SiS_Pr->SiS_VCLKData[index].SR2C; 693 + 694 + SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4,0x31,0xCF); 695 + 696 + SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2B,clka); 697 + SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2C,clkb); 698 + SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2D,0x01); 699 + } 700 + 701 + /*********************************************/ 702 + /* FIFO */ 703 + /*********************************************/ 704 + 705 + static void 706 + SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 707 + unsigned short mi) 708 + { 709 + unsigned short modeflag = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag; 710 + 711 + /* disable auto-threshold */ 712 + SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x3D, 0xFE); 713 + 714 + SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x08, 0xAE); 715 + SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x09, 0xF0); 716 + 717 + if (ModeNo <= 0x13) 718 + return; 719 + 720 + if ((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) { 721 + SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x08, 0x34); 722 + SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x3D, 0x01); 723 + } 724 + } 725 + 726 + /*********************************************/ 727 + /* MODE REGISTERS */ 728 + /*********************************************/ 729 + 730 + static void 731 + SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 732 + unsigned short rrti) 733 + { 734 + unsigned short data = 0, VCLK = 0, index = 0; 735 + 736 + if (ModeNo > 0x13) { 737 + index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK; 738 + VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; 739 + } 740 + 741 + if (VCLK >= 166) data |= 0x0c; 742 + SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x32, 0xf3, data); 743 + 744 + if (VCLK >= 166) 745 + SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1f, 0xe7); 746 + 747 + /* DAC speed */ 748 + data = 0x03; 749 + if (VCLK >= 260) 750 + data = 0x00; 751 + else if (VCLK >= 160) 752 + data = 0x01; 753 + else if (VCLK >= 135) 754 + data = 0x02; 755 + 756 + SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x07, 0xF8, data); 757 + } 758 + 759 + static void 760 + SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 761 + unsigned short ModeIdIndex, unsigned short rrti) 762 + { 763 + unsigned short data, infoflag = 0, modeflag; 764 + 765 + if (ModeNo <= 0x13) 766 + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; 767 + else { 768 + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; 769 + infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag; 770 + } 771 + 772 + /* Disable DPMS */ 773 + SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1F, 0x3F); 774 + 775 + data = 0; 776 + if (ModeNo > 0x13) { 777 + if (SiS_Pr->SiS_ModeType > ModeEGA) { 778 + data |= 0x02; 779 + data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2); 780 + } 781 + if (infoflag & InterlaceMode) data |= 0x20; 782 + } 783 + SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x06, 0xC0, data); 784 + 785 + data = 0; 786 + if (infoflag & InterlaceMode) { 787 + /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */ 788 + unsigned short hrs = (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x04) | 789 + ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0xc0) << 2)) - 3; 790 + unsigned short hto = (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x00) | 791 + ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0x03) << 8)) + 5; 792 + data = hrs - (hto >> 1) + 3; 793 + } 794 + SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x19, (data & 0xFF)); 795 + SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x1a, 0xFC, (data >> 8)); 796 + 797 + if (modeflag & HalfDCLK) 798 + SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0x08); 799 + 800 + data = 0; 801 + if (modeflag & LineCompareOff) 802 + data = 0x08; 803 + SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0F, 0xB7, data); 804 + 805 + if ((SiS_Pr->SiS_ModeType == ModeEGA) && (ModeNo > 0x13)) 806 + SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0F, 0x40); 807 + 808 + SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x31, 0xfb); 809 + 810 + data = 0x60; 811 + if (SiS_Pr->SiS_ModeType != ModeText) { 812 + data ^= 0x60; 813 + if (SiS_Pr->SiS_ModeType != ModeEGA) 814 + data ^= 0xA0; 815 + } 816 + SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x21, 0x1F, data); 817 + 818 + SiS_SetVCLKState(SiS_Pr, ModeNo, rrti); 819 + 820 + if (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x31) & 0x40) 821 + SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x52, 0x2c); 822 + else 823 + SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x52, 0x6c); 824 + } 825 + 826 + /*********************************************/ 827 + /* LOAD DAC */ 828 + /*********************************************/ 829 + 830 + static void 831 + SiS_WriteDAC(struct SiS_Private *SiS_Pr, unsigned long DACData, 832 + unsigned short shiftflag, unsigned short dl, unsigned short ah, 833 + unsigned short al, unsigned short dh) 834 + { 835 + unsigned short d1, d2, d3; 836 + 837 + switch (dl) { 838 + case 0: 839 + d1 = dh; d2 = ah; d3 = al; 840 + break; 841 + case 1: 842 + d1 = ah; d2 = al; d3 = dh; 843 + break; 844 + default: 845 + d1 = al; d2 = dh; d3 = ah; 846 + } 847 + SiS_SetRegByte(SiS_Pr, DACData, (d1 << shiftflag)); 848 + SiS_SetRegByte(SiS_Pr, DACData, (d2 << shiftflag)); 849 + SiS_SetRegByte(SiS_Pr, DACData, (d3 << shiftflag)); 850 + } 851 + 852 + static void 853 + SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short mi) 854 + { 855 + unsigned short data, data2, time, i, j, k, m, n, o; 856 + unsigned short si, di, bx, sf; 857 + unsigned long DACAddr, DACData; 858 + const unsigned char *table = NULL; 859 + 860 + if (ModeNo < 0x13) 861 + data = SiS_Pr->SiS_SModeIDTable[mi].St_ModeFlag; 862 + else 863 + data = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag; 864 + 865 + data &= DACInfoFlag; 866 + 867 + j = time = 64; 868 + if (data == 0x00) 869 + table = SiS_MDA_DAC; 870 + else if (data == 0x08) 871 + table = SiS_CGA_DAC; 872 + else if (data == 0x10) 873 + table = SiS_EGA_DAC; 874 + else { 875 + j = 16; 876 + time = 256; 877 + table = SiS_VGA_DAC; 878 + } 879 + 880 + DACAddr = SiS_Pr->SiS_P3c8; 881 + DACData = SiS_Pr->SiS_P3c9; 882 + sf = 0; 883 + SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c6, 0xFF); 884 + 885 + SiS_SetRegByte(SiS_Pr, DACAddr, 0x00); 886 + 887 + for(i = 0; i < j; i++) { 888 + data = table[i]; 889 + for(k = 0; k < 3; k++) { 890 + data2 = 0; 891 + if (data & 0x01) data2 += 0x2A; 892 + if (data & 0x02) data2 += 0x15; 893 + SiS_SetRegByte(SiS_Pr, DACData, (data2 << sf)); 894 + data >>= 2; 895 + } 896 + } 897 + 898 + if (time == 256) { 899 + for(i = 16; i < 32; i++) { 900 + data = table[i] << sf; 901 + for(k = 0; k < 3; k++) 902 + SiS_SetRegByte(SiS_Pr, DACData, data); 903 + } 904 + si = 32; 905 + for(m = 0; m < 9; m++) { 906 + di = si; 907 + bx = si + 4; 908 + for(n = 0; n < 3; n++) { 909 + for(o = 0; o < 5; o++) { 910 + SiS_WriteDAC(SiS_Pr, DACData, sf, n, 911 + table[di], table[bx], table[si]); 912 + si++; 913 + } 914 + si -= 2; 915 + for(o = 0; o < 3; o++) { 916 + SiS_WriteDAC(SiS_Pr, DACData, sf, n, 917 + table[di], table[si], table[bx]); 918 + si--; 919 + } 920 + } 921 + si += 5; 922 + } 923 + } 924 + } 925 + 926 + /*********************************************/ 927 + /* SET CRT1 REGISTER GROUP */ 928 + /*********************************************/ 929 + 930 + static void 931 + SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 932 + unsigned short ModeIdIndex) 933 + { 934 + unsigned short StandTableIndex, rrti; 935 + 936 + SiS_Pr->SiS_CRT1Mode = ModeNo; 937 + 938 + if (ModeNo <= 0x13) 939 + StandTableIndex = 0; 940 + else 941 + StandTableIndex = 1; 942 + 943 + SiS_ResetSegmentRegisters(SiS_Pr); 944 + SiS_SetSeqRegs(SiS_Pr, StandTableIndex); 945 + SiS_SetMiscRegs(SiS_Pr, StandTableIndex); 946 + SiS_SetCRTCRegs(SiS_Pr, StandTableIndex); 947 + SiS_SetATTRegs(SiS_Pr, StandTableIndex); 948 + SiS_SetGRCRegs(SiS_Pr, StandTableIndex); 949 + SiS_ClearExt1Regs(SiS_Pr, ModeNo); 950 + 951 + rrti = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex); 952 + 953 + if (rrti != 0xFFFF) { 954 + SiS_SetCRT1Sync(SiS_Pr, rrti); 955 + SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, rrti); 956 + SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, rrti); 957 + SiS_SetCRT1VCLK(SiS_Pr, ModeNo, rrti); 958 + } 959 + 960 + SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex); 961 + 962 + SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, rrti); 963 + 964 + SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex); 965 + 966 + SiS_DisplayOn(SiS_Pr); 967 + } 968 + 969 + /*********************************************/ 970 + /* SiSSetMode() */ 971 + /*********************************************/ 972 + 973 + int 974 + SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo) 975 + { 976 + unsigned short ModeIdIndex; 977 + unsigned long BaseAddr = SiS_Pr->IOAddress; 978 + 979 + SiSUSB_InitPtr(SiS_Pr); 980 + SiSUSBRegInit(SiS_Pr, BaseAddr); 981 + SiS_GetSysFlags(SiS_Pr); 982 + 983 + if (!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) 984 + return 0; 985 + 986 + SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x05, 0x86); 987 + 988 + SiSInitPCIetc(SiS_Pr); 989 + 990 + ModeNo &= 0x7f; 991 + 992 + SiS_Pr->SiS_ModeType = 993 + SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag & ModeTypeMask; 994 + 995 + SiS_Pr->SiS_SetFlag = LowModeTests; 996 + 997 + /* Set mode on CRT1 */ 998 + SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex); 999 + 1000 + SiS_HandleCRT1(SiS_Pr); 1001 + 1002 + SiS_DisplayOn(SiS_Pr); 1003 + SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c6, 0xFF); 1004 + 1005 + /* Store mode number */ 1006 + SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x34, ModeNo); 1007 + 1008 + return 1; 1009 + } 1010 + 1011 + int 1012 + SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo) 1013 + { 1014 + unsigned short ModeNo = 0; 1015 + int i; 1016 + 1017 + SiSUSB_InitPtr(SiS_Pr); 1018 + 1019 + if (VModeNo == 0x03) { 1020 + 1021 + ModeNo = 0x03; 1022 + 1023 + } else { 1024 + 1025 + i = 0; 1026 + do { 1027 + 1028 + if (SiS_Pr->SiS_EModeIDTable[i].Ext_VESAID == VModeNo) { 1029 + ModeNo = SiS_Pr->SiS_EModeIDTable[i].Ext_ModeID; 1030 + break; 1031 + } 1032 + 1033 + } while (SiS_Pr->SiS_EModeIDTable[i++].Ext_ModeID != 0xff); 1034 + 1035 + } 1036 + 1037 + if (!ModeNo) 1038 + return 0; 1039 + 1040 + return SiSUSBSetMode(SiS_Pr, ModeNo); 1041 + } 1042 + 1043 + #endif /* INCL_SISUSB_CON */ 1044 + 1045 + 1046 + 1047 +
+830
drivers/usb/misc/sisusbvga/sisusb_init.h
··· 1 + /* $XFree86$ */ 2 + /* $XdotOrg$ */ 3 + /* 4 + * Data and prototypes for init.c 5 + * 6 + * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria 7 + * 8 + * If distributed as part of the Linux kernel, the following license terms 9 + * apply: 10 + * 11 + * * This program is free software; you can redistribute it and/or modify 12 + * * it under the terms of the GNU General Public License as published by 13 + * * the Free Software Foundation; either version 2 of the named License, 14 + * * or any later version. 15 + * * 16 + * * This program is distributed in the hope that it will be useful, 17 + * * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 + * * GNU General Public License for more details. 20 + * * 21 + * * You should have received a copy of the GNU General Public License 22 + * * along with this program; if not, write to the Free Software 23 + * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA 24 + * 25 + * Otherwise, the following license terms apply: 26 + * 27 + * * Redistribution and use in source and binary forms, with or without 28 + * * modification, are permitted provided that the following conditions 29 + * * are met: 30 + * * 1) Redistributions of source code must retain the above copyright 31 + * * notice, this list of conditions and the following disclaimer. 32 + * * 2) Redistributions in binary form must reproduce the above copyright 33 + * * notice, this list of conditions and the following disclaimer in the 34 + * * documentation and/or other materials provided with the distribution. 35 + * * 3) The name of the author may not be used to endorse or promote products 36 + * * derived from this software without specific prior written permission. 37 + * * 38 + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 39 + * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 40 + * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 41 + * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 42 + * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 43 + * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 44 + * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 45 + * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 46 + * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 47 + * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 48 + * 49 + * Author: Thomas Winischhofer <thomas@winischhofer.net> 50 + * 51 + */ 52 + 53 + #ifndef _SISUSB_INIT_H_ 54 + #define _SISUSB_INIT_H_ 55 + 56 + /* SiS_ModeType */ 57 + #define ModeText 0x00 58 + #define ModeCGA 0x01 59 + #define ModeEGA 0x02 60 + #define ModeVGA 0x03 61 + #define Mode15Bpp 0x04 62 + #define Mode16Bpp 0x05 63 + #define Mode24Bpp 0x06 64 + #define Mode32Bpp 0x07 65 + 66 + #define ModeTypeMask 0x07 67 + #define IsTextMode 0x07 68 + 69 + #define DACInfoFlag 0x0018 70 + #define MemoryInfoFlag 0x01E0 71 + #define MemorySizeShift 5 72 + 73 + /* modeflag */ 74 + #define Charx8Dot 0x0200 75 + #define LineCompareOff 0x0400 76 + #define CRT2Mode 0x0800 77 + #define HalfDCLK 0x1000 78 + #define NoSupportSimuTV 0x2000 79 + #define NoSupportLCDScale 0x4000 /* SiS bridge: No scaling possible (no matter what panel) */ 80 + #define DoubleScanMode 0x8000 81 + 82 + /* Infoflag */ 83 + #define SupportTV 0x0008 84 + #define SupportTV1024 0x0800 85 + #define SupportCHTV 0x0800 86 + #define Support64048060Hz 0x0800 /* Special for 640x480 LCD */ 87 + #define SupportHiVision 0x0010 88 + #define SupportYPbPr750p 0x1000 89 + #define SupportLCD 0x0020 90 + #define SupportRAMDAC2 0x0040 /* All (<= 100Mhz) */ 91 + #define SupportRAMDAC2_135 0x0100 /* All except DH (<= 135Mhz) */ 92 + #define SupportRAMDAC2_162 0x0200 /* B, C (<= 162Mhz) */ 93 + #define SupportRAMDAC2_202 0x0400 /* C (<= 202Mhz) */ 94 + #define InterlaceMode 0x0080 95 + #define SyncPP 0x0000 96 + #define SyncPN 0x4000 97 + #define SyncNP 0x8000 98 + #define SyncNN 0xc000 99 + 100 + /* SetFlag */ 101 + #define ProgrammingCRT2 0x0001 102 + #define LowModeTests 0x0002 103 + #define LCDVESATiming 0x0008 104 + #define EnableLVDSDDA 0x0010 105 + #define SetDispDevSwitchFlag 0x0020 106 + #define CheckWinDos 0x0040 107 + #define SetDOSMode 0x0080 108 + 109 + /* Index in ModeResInfo table */ 110 + #define SIS_RI_320x200 0 111 + #define SIS_RI_320x240 1 112 + #define SIS_RI_320x400 2 113 + #define SIS_RI_400x300 3 114 + #define SIS_RI_512x384 4 115 + #define SIS_RI_640x400 5 116 + #define SIS_RI_640x480 6 117 + #define SIS_RI_800x600 7 118 + #define SIS_RI_1024x768 8 119 + #define SIS_RI_1280x1024 9 120 + #define SIS_RI_1600x1200 10 121 + #define SIS_RI_1920x1440 11 122 + #define SIS_RI_2048x1536 12 123 + #define SIS_RI_720x480 13 124 + #define SIS_RI_720x576 14 125 + #define SIS_RI_1280x960 15 126 + #define SIS_RI_800x480 16 127 + #define SIS_RI_1024x576 17 128 + #define SIS_RI_1280x720 18 129 + #define SIS_RI_856x480 19 130 + #define SIS_RI_1280x768 20 131 + #define SIS_RI_1400x1050 21 132 + #define SIS_RI_1152x864 22 /* Up to here SiS conforming */ 133 + #define SIS_RI_848x480 23 134 + #define SIS_RI_1360x768 24 135 + #define SIS_RI_1024x600 25 136 + #define SIS_RI_1152x768 26 137 + #define SIS_RI_768x576 27 138 + #define SIS_RI_1360x1024 28 139 + #define SIS_RI_1680x1050 29 140 + #define SIS_RI_1280x800 30 141 + #define SIS_RI_1920x1080 31 142 + #define SIS_RI_960x540 32 143 + #define SIS_RI_960x600 33 144 + 145 + #define SIS_VIDEO_CAPTURE 0x00 - 0x30 146 + #define SIS_VIDEO_PLAYBACK 0x02 - 0x30 147 + #define SIS_CRT2_PORT_04 0x04 - 0x30 148 + 149 + /* Mode numbers */ 150 + static const unsigned short ModeIndex_320x200[] = {0x59, 0x41, 0x00, 0x4f}; 151 + static const unsigned short ModeIndex_320x240[] = {0x50, 0x56, 0x00, 0x53}; 152 + static const unsigned short ModeIndex_400x300[] = {0x51, 0x57, 0x00, 0x54}; 153 + static const unsigned short ModeIndex_512x384[] = {0x52, 0x58, 0x00, 0x5c}; 154 + static const unsigned short ModeIndex_640x400[] = {0x2f, 0x5d, 0x00, 0x5e}; 155 + static const unsigned short ModeIndex_640x480[] = {0x2e, 0x44, 0x00, 0x62}; 156 + static const unsigned short ModeIndex_720x480[] = {0x31, 0x33, 0x00, 0x35}; 157 + static const unsigned short ModeIndex_720x576[] = {0x32, 0x34, 0x00, 0x36}; 158 + static const unsigned short ModeIndex_768x576[] = {0x5f, 0x60, 0x00, 0x61}; 159 + static const unsigned short ModeIndex_800x480[] = {0x70, 0x7a, 0x00, 0x76}; 160 + static const unsigned short ModeIndex_800x600[] = {0x30, 0x47, 0x00, 0x63}; 161 + static const unsigned short ModeIndex_848x480[] = {0x39, 0x3b, 0x00, 0x3e}; 162 + static const unsigned short ModeIndex_856x480[] = {0x3f, 0x42, 0x00, 0x45}; 163 + static const unsigned short ModeIndex_960x540[] = {0x1d, 0x1e, 0x00, 0x1f}; 164 + static const unsigned short ModeIndex_960x600[] = {0x20, 0x21, 0x00, 0x22}; 165 + static const unsigned short ModeIndex_1024x768[] = {0x38, 0x4a, 0x00, 0x64}; 166 + static const unsigned short ModeIndex_1024x576[] = {0x71, 0x74, 0x00, 0x77}; 167 + static const unsigned short ModeIndex_1152x864[] = {0x29, 0x2a, 0x00, 0x2b}; 168 + static const unsigned short ModeIndex_1280x720[] = {0x79, 0x75, 0x00, 0x78}; 169 + static const unsigned short ModeIndex_1280x768[] = {0x23, 0x24, 0x00, 0x25}; 170 + static const unsigned short ModeIndex_1280x1024[] = {0x3a, 0x4d, 0x00, 0x65}; 171 + 172 + static const unsigned char SiS_MDA_DAC[] = 173 + { 174 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 175 + 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, 176 + 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, 177 + 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, 178 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 179 + 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, 180 + 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, 181 + 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F 182 + }; 183 + 184 + static const unsigned char SiS_CGA_DAC[] = 185 + { 186 + 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15, 187 + 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15, 188 + 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F, 189 + 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F, 190 + 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15, 191 + 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15, 192 + 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F, 193 + 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F 194 + }; 195 + 196 + static const unsigned char SiS_EGA_DAC[] = 197 + { 198 + 0x00,0x10,0x04,0x14,0x01,0x11,0x05,0x15, 199 + 0x20,0x30,0x24,0x34,0x21,0x31,0x25,0x35, 200 + 0x08,0x18,0x0C,0x1C,0x09,0x19,0x0D,0x1D, 201 + 0x28,0x38,0x2C,0x3C,0x29,0x39,0x2D,0x3D, 202 + 0x02,0x12,0x06,0x16,0x03,0x13,0x07,0x17, 203 + 0x22,0x32,0x26,0x36,0x23,0x33,0x27,0x37, 204 + 0x0A,0x1A,0x0E,0x1E,0x0B,0x1B,0x0F,0x1F, 205 + 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F 206 + }; 207 + 208 + static const unsigned char SiS_VGA_DAC[] = 209 + { 210 + 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15, 211 + 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F, 212 + 0x00,0x05,0x08,0x0B,0x0E,0x11,0x14,0x18, 213 + 0x1C,0x20,0x24,0x28,0x2D,0x32,0x38,0x3F, 214 + 0x00,0x10,0x1F,0x2F,0x3F,0x1F,0x27,0x2F, 215 + 0x37,0x3F,0x2D,0x31,0x36,0x3A,0x3F,0x00, 216 + 0x07,0x0E,0x15,0x1C,0x0E,0x11,0x15,0x18, 217 + 0x1C,0x14,0x16,0x18,0x1A,0x1C,0x00,0x04, 218 + 0x08,0x0C,0x10,0x08,0x0A,0x0C,0x0E,0x10, 219 + 0x0B,0x0C,0x0D,0x0F,0x10 220 + }; 221 + 222 + static const struct SiS_St SiSUSB_SModeIDTable[] = 223 + { 224 + {0x03,0x0010,0x18,0x02,0x02,0x00,0x01,0x03,0x40}, 225 + {0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00} 226 + }; 227 + 228 + static const struct SiS_StResInfo_S SiSUSB_StResInfo[] = 229 + { 230 + { 640,400}, 231 + { 640,350}, 232 + { 720,400}, 233 + { 720,350}, 234 + { 640,480} 235 + }; 236 + 237 + static const struct SiS_ModeResInfo SiSUSB_ModeResInfo[] = 238 + { 239 + { 320, 200, 8, 8}, /* 0x00 */ 240 + { 320, 240, 8, 8}, /* 0x01 */ 241 + { 320, 400, 8, 8}, /* 0x02 */ 242 + { 400, 300, 8, 8}, /* 0x03 */ 243 + { 512, 384, 8, 8}, /* 0x04 */ 244 + { 640, 400, 8,16}, /* 0x05 */ 245 + { 640, 480, 8,16}, /* 0x06 */ 246 + { 800, 600, 8,16}, /* 0x07 */ 247 + { 1024, 768, 8,16}, /* 0x08 */ 248 + { 1280,1024, 8,16}, /* 0x09 */ 249 + { 1600,1200, 8,16}, /* 0x0a */ 250 + { 1920,1440, 8,16}, /* 0x0b */ 251 + { 2048,1536, 8,16}, /* 0x0c */ 252 + { 720, 480, 8,16}, /* 0x0d */ 253 + { 720, 576, 8,16}, /* 0x0e */ 254 + { 1280, 960, 8,16}, /* 0x0f */ 255 + { 800, 480, 8,16}, /* 0x10 */ 256 + { 1024, 576, 8,16}, /* 0x11 */ 257 + { 1280, 720, 8,16}, /* 0x12 */ 258 + { 856, 480, 8,16}, /* 0x13 */ 259 + { 1280, 768, 8,16}, /* 0x14 */ 260 + { 1400,1050, 8,16}, /* 0x15 */ 261 + { 1152, 864, 8,16}, /* 0x16 */ 262 + { 848, 480, 8,16}, /* 0x17 */ 263 + { 1360, 768, 8,16}, /* 0x18 */ 264 + { 1024, 600, 8,16}, /* 0x19 */ 265 + { 1152, 768, 8,16}, /* 0x1a */ 266 + { 768, 576, 8,16}, /* 0x1b */ 267 + { 1360,1024, 8,16}, /* 0x1c */ 268 + { 1680,1050, 8,16}, /* 0x1d */ 269 + { 1280, 800, 8,16}, /* 0x1e */ 270 + { 1920,1080, 8,16}, /* 0x1f */ 271 + { 960, 540, 8,16}, /* 0x20 */ 272 + { 960, 600, 8,16} /* 0x21 */ 273 + }; 274 + 275 + static const struct SiS_StandTable SiSUSB_StandTable[] = 276 + { 277 + /* MD_3_400 - mode 0x03 - 400 */ 278 + { 279 + 0x50,0x18,0x10,0x1000, 280 + { 0x00,0x03,0x00,0x02 }, 281 + 0x67, 282 + { 0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, 283 + 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00, 284 + 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3, 285 + 0xff }, 286 + { 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, 287 + 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, 288 + 0x0c,0x00,0x0f,0x08 }, 289 + { 0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, 0xff } 290 + }, 291 + /* Generic for VGA and higher */ 292 + { 293 + 0x00,0x00,0x00,0x0000, 294 + { 0x01,0x0f,0x00,0x0e }, 295 + 0x23, 296 + { 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e, 297 + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, 298 + 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3, 299 + 0xff }, 300 + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 301 + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, 302 + 0x01,0x00,0x00,0x00 }, 303 + { 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f, 0xff } 304 + } 305 + }; 306 + 307 + static const struct SiS_Ext SiSUSB_EModeIDTable[] = 308 + { 309 + {0x2e,0x0a1b,0x0101,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x8 */ 310 + {0x2f,0x0a1b,0x0100,SIS_RI_640x400, 0x00,0x00,0x05,0x05,0x10, 0}, /* 640x400x8 */ 311 + {0x30,0x2a1b,0x0103,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x8 */ 312 + {0x31,0x4a1b,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x8 */ 313 + {0x32,0x4a1b,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x8 */ 314 + {0x33,0x4a1d,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x16 */ 315 + {0x34,0x6a1d,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x16 */ 316 + {0x35,0x4a1f,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x32 */ 317 + {0x36,0x6a1f,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x32 */ 318 + {0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x8 */ 319 + {0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x8 */ 320 + {0x41,0x9a1d,0x010e,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x16 */ 321 + {0x44,0x0a1d,0x0111,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x16 */ 322 + {0x47,0x2a1d,0x0114,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x16 */ 323 + {0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x16 */ 324 + {0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x16 */ 325 + {0x50,0x9a1b,0x0132,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x8 */ 326 + {0x51,0xba1b,0x0133,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x8 */ 327 + {0x52,0xba1b,0x0134,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x8 */ 328 + {0x56,0x9a1d,0x0135,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x16 */ 329 + {0x57,0xba1d,0x0136,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x16 */ 330 + {0x58,0xba1d,0x0137,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x16 */ 331 + {0x59,0x9a1b,0x0138,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x8 */ 332 + {0x5c,0xba1f,0x0000,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x32 */ 333 + {0x5d,0x0a1d,0x0139,SIS_RI_640x400, 0x00,0x00,0x05,0x07,0x10, 0}, /* 640x400x16 */ 334 + {0x5e,0x0a1f,0x0000,SIS_RI_640x400, 0x00,0x00,0x05,0x07,0x10, 0}, /* 640x400x32 */ 335 + {0x62,0x0a3f,0x013a,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x32 */ 336 + {0x63,0x2a3f,0x013b,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x32 */ 337 + {0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x32 */ 338 + {0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x32 */ 339 + {0x70,0x6a1b,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x8 */ 340 + {0x71,0x4a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x8 */ 341 + {0x74,0x4a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x16 */ 342 + {0x75,0x0a3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x16 */ 343 + {0x76,0x6a1f,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x32 */ 344 + {0x77,0x4a1f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x32 */ 345 + {0x78,0x0a3f,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x32 */ 346 + {0x79,0x0a3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x8 */ 347 + {0x7a,0x6a1d,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x16 */ 348 + {0x23,0x0e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x8 */ 349 + {0x24,0x0e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x16 */ 350 + {0x25,0x0eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x32 */ 351 + {0x39,0x6a1b,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x28,-1}, /* 848x480 */ 352 + {0x3b,0x6a3d,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x28,-1}, 353 + {0x3e,0x6a7f,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x28,-1}, 354 + {0x3f,0x6a1b,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x2a,-1}, /* 856x480 */ 355 + {0x42,0x6a3d,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x2a,-1}, 356 + {0x45,0x6a7f,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x2a,-1}, 357 + {0x4f,0x9a1f,0x0000,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x32 */ 358 + {0x53,0x9a1f,0x0000,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x32 */ 359 + {0x54,0xba1f,0x0000,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x32 */ 360 + {0x5f,0x6a1b,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x2c,-1}, /* 768x576 */ 361 + {0x60,0x6a1d,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x2c,-1}, 362 + {0x61,0x6a3f,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x2c,-1}, 363 + {0x1d,0x6a1b,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x2d,-1}, /* 960x540 */ 364 + {0x1e,0x6a3d,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x2d,-1}, 365 + {0x1f,0x6a7f,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x2d,-1}, 366 + {0x20,0x6a1b,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x2e,-1}, /* 960x600 */ 367 + {0x21,0x6a3d,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x2e,-1}, 368 + {0x22,0x6a7f,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x2e,-1}, 369 + {0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1}, /* 1152x864 */ 370 + {0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1}, 371 + {0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1}, 372 + {0xff,0x0000,0x0000,0, 0x00,0x00,0x00,0x00,0x00,-1} 373 + }; 374 + 375 + static const struct SiS_Ext2 SiSUSB_RefIndex[] = 376 + { 377 + {0x085f,0x0d,0x03,0x05,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x0 */ 378 + {0x0067,0x0e,0x04,0x05,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x1 */ 379 + {0x0067,0x0f,0x08,0x48,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x2 */ 380 + {0x0067,0x10,0x07,0x8b,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x3 */ 381 + {0x0047,0x11,0x0a,0x00,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x4 */ 382 + {0x0047,0x12,0x0d,0x00,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x5 */ 383 + {0x0047,0x13,0x13,0x00,0x05,0x30, 800, 600, 0x20, 0x00, 0x00}, /* 0x6 */ 384 + {0x0107,0x14,0x1c,0x00,0x05,0x30, 800, 600, 0x20, 0x00, 0x00}, /* 0x7 */ 385 + {0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0x8 */ 386 + {0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0x9 */ 387 + {0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xa */ 388 + {0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xb */ 389 + {0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xc */ 390 + {0xc047,0x0a,0x09,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xd */ 391 + {0xc047,0x0b,0x0e,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xe */ 392 + {0xc047,0x0c,0x15,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xf */ 393 + {0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0x30, 0x55, 0x6e}, /* 0x10 */ 394 + {0xc06f,0x3c,0x01,0x06,0x13,0x31, 720, 480, 0x30, 0x00, 0x00}, /* 0x11 */ 395 + {0x006f,0x3d,0x6f,0x06,0x14,0x32, 720, 576, 0x30, 0x00, 0x00}, /* 0x12 (6f was 03) */ 396 + {0x0087,0x15,0x06,0x00,0x06,0x38,1024, 768, 0x30, 0x00, 0x00}, /* 0x13 */ 397 + {0xc877,0x16,0x0b,0x06,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x14 */ 398 + {0xc067,0x17,0x0f,0x49,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x15 */ 399 + {0x0067,0x18,0x11,0x00,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x16 */ 400 + {0x0047,0x19,0x16,0x8c,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x17 */ 401 + {0x0107,0x1a,0x1b,0x00,0x06,0x38,1024, 768, 0x10, 0x00, 0x00}, /* 0x18 */ 402 + {0x0107,0x1b,0x1f,0x00,0x06,0x38,1024, 768, 0x10, 0x00, 0x00}, /* 0x19 */ 403 + {0x407f,0x00,0x00,0x00,0x00,0x41, 320, 200, 0x30, 0x56, 0x4e}, /* 0x1a */ 404 + {0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0x30, 0x00, 0x00}, /* 0x1b */ 405 + {0x007f,0x02,0x04,0x05,0x05,0x51, 400, 300, 0x30, 0x00, 0x00}, /* 0x1c */ 406 + {0xc077,0x03,0x0b,0x06,0x06,0x52, 512, 384, 0x30, 0x00, 0x00}, /* 0x1d */ 407 + {0x0077,0x32,0x40,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x1e */ 408 + {0x0047,0x33,0x07,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x1f */ 409 + {0x0047,0x34,0x0a,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x20 */ 410 + {0x0077,0x35,0x0b,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x21 */ 411 + {0x0047,0x36,0x11,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x22 */ 412 + {0x0047,0x37,0x16,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x23 */ 413 + {0x1137,0x38,0x19,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x24 */ 414 + {0x1107,0x39,0x1e,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x25 */ 415 + {0x1307,0x3a,0x20,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x26 */ 416 + {0x0077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00}, /* 0x27 */ 417 + {0x0087,0x45,0x57,0x00,0x16,0x39, 848, 480, 0x30, 0x00, 0x00}, /* 0x28 38Hzi */ 418 + {0xc067,0x46,0x55,0x0b,0x16,0x39, 848, 480, 0x30, 0x00, 0x00}, /* 0x29 848x480-60Hz */ 419 + {0x0087,0x47,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00}, /* 0x2a 856x480-38Hzi */ 420 + {0xc067,0x48,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00}, /* 0x2b 856x480-60Hz */ 421 + {0x006f,0x4d,0x71,0x06,0x15,0x5f, 768, 576, 0x30, 0x00, 0x00}, /* 0x2c 768x576-56Hz */ 422 + {0x0067,0x52,0x6a,0x00,0x1c,0x1d, 960, 540, 0x30, 0x00, 0x00}, /* 0x2d 960x540 60Hz */ 423 + {0x0077,0x53,0x6b,0x0b,0x1d,0x20, 960, 600, 0x30, 0x00, 0x00}, /* 0x2e 960x600 60Hz */ 424 + {0x0087,0x1c,0x11,0x00,0x07,0x3a,1280,1024, 0x30, 0x00, 0x00}, /* 0x2f */ 425 + {0x0137,0x1d,0x19,0x07,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x30 */ 426 + {0x0107,0x1e,0x1e,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x31 */ 427 + {0x0207,0x1f,0x20,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x32 */ 428 + {0x0127,0x54,0x6d,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x33 1152x864-60Hz */ 429 + {0x0127,0x44,0x19,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x34 1152x864-75Hz */ 430 + {0x0127,0x4a,0x1e,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x35 1152x864-85Hz */ 431 + {0xffff,0x00,0x00,0x00,0x00,0x00, 0, 0, 0, 0x00, 0x00} 432 + }; 433 + 434 + static const struct SiS_CRT1Table SiSUSB_CRT1Table[] = 435 + { 436 + {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, 437 + 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00, 438 + 0x00}}, /* 0x0 */ 439 + {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e, 440 + 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00, 441 + 0x00}}, /* 0x1 */ 442 + {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0, 443 + 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05, 444 + 0x01}}, /* 0x2 */ 445 + {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5, 446 + 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01, 447 + 0x01}}, /* 0x3 */ 448 + {{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, 449 + 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05, 450 + 0x00}}, /* 0x4 */ 451 + {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e, 452 + 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05, 453 + 0x00}}, /* 0x5 */ 454 + {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e, 455 + 0xe8,0x8a,0xdf,0xe7,0x07,0x00,0x00,0x01, 456 + 0x00}}, /* 0x6 */ 457 + {{0x64,0x4f,0x4f,0x88,0x55,0x9d,0xf2,0x1f, 458 + 0xe0,0x83,0xdf,0xdf,0xf3,0x10,0x00,0x01, 459 + 0x00}}, /* 0x7 */ 460 + {{0x63,0x4f,0x4f,0x87,0x5a,0x81,0xfb,0x1f, 461 + 0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05, 462 + 0x00}}, /* 0x8 */ 463 + {{0x65,0x4f,0x4f,0x89,0x58,0x80,0xfb,0x1f, 464 + 0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05, 465 + 0x61}}, /* 0x9 */ 466 + {{0x65,0x4f,0x4f,0x89,0x58,0x80,0x01,0x3e, 467 + 0xe0,0x83,0xdf,0xdf,0x02,0x00,0x00,0x05, 468 + 0x61}}, /* 0xa */ 469 + {{0x67,0x4f,0x4f,0x8b,0x58,0x81,0x0d,0x3e, 470 + 0xe0,0x83,0xdf,0xdf,0x0e,0x00,0x00,0x05, 471 + 0x61}}, /* 0xb */ 472 + {{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f, 473 + 0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01, 474 + 0x00}}, /* 0xc */ 475 + {{0x7b,0x63,0x63,0x9f,0x6a,0x93,0x6f,0xf0, 476 + 0x58,0x8a,0x57,0x57,0x70,0x20,0x00,0x05, 477 + 0x01}}, /* 0xd */ 478 + {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xf0, 479 + 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x06, 480 + 0x01}}, /* 0xe */ 481 + {{0x7d,0x63,0x63,0x81,0x6e,0x1d,0x98,0xf0, 482 + 0x7c,0x82,0x57,0x57,0x99,0x00,0x00,0x06, 483 + 0x01}}, /* 0xf */ 484 + {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xf0, 485 + 0x58,0x8b,0x57,0x57,0x70,0x20,0x00,0x06, 486 + 0x01}}, /* 0x10 */ 487 + {{0x7e,0x63,0x63,0x82,0x6b,0x13,0x75,0xf0, 488 + 0x58,0x8b,0x57,0x57,0x76,0x20,0x00,0x06, 489 + 0x01}}, /* 0x11 */ 490 + {{0x81,0x63,0x63,0x85,0x6d,0x18,0x7a,0xf0, 491 + 0x58,0x8b,0x57,0x57,0x7b,0x20,0x00,0x06, 492 + 0x61}}, /* 0x12 */ 493 + {{0x83,0x63,0x63,0x87,0x6e,0x19,0x81,0xf0, 494 + 0x58,0x8b,0x57,0x57,0x82,0x20,0x00,0x06, 495 + 0x61}}, /* 0x13 */ 496 + {{0x85,0x63,0x63,0x89,0x6f,0x1a,0x91,0xf0, 497 + 0x58,0x8b,0x57,0x57,0x92,0x20,0x00,0x06, 498 + 0x61}}, /* 0x14 */ 499 + {{0x99,0x7f,0x7f,0x9d,0x84,0x1a,0x96,0x1f, 500 + 0x7f,0x83,0x7f,0x7f,0x97,0x10,0x00,0x02, 501 + 0x00}}, /* 0x15 */ 502 + {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5, 503 + 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02, 504 + 0x01}}, /* 0x16 */ 505 + {{0xa1,0x7f,0x7f,0x85,0x86,0x97,0x24,0xf5, 506 + 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02, 507 + 0x01}}, /* 0x17 */ 508 + {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf5, 509 + 0x00,0x83,0xff,0xff,0x1f,0x10,0x00,0x02, 510 + 0x01}}, /* 0x18 */ 511 + {{0xa7,0x7f,0x7f,0x8b,0x89,0x95,0x26,0xf5, 512 + 0x00,0x83,0xff,0xff,0x27,0x10,0x00,0x02, 513 + 0x01}}, /* 0x19 */ 514 + {{0xa9,0x7f,0x7f,0x8d,0x8c,0x9a,0x2c,0xf5, 515 + 0x00,0x83,0xff,0xff,0x2d,0x14,0x00,0x02, 516 + 0x62}}, /* 0x1a */ 517 + {{0xab,0x7f,0x7f,0x8f,0x8d,0x9b,0x35,0xf5, 518 + 0x00,0x83,0xff,0xff,0x36,0x14,0x00,0x02, 519 + 0x62}}, /* 0x1b */ 520 + {{0xcf,0x9f,0x9f,0x93,0xb2,0x01,0x14,0xba, 521 + 0x00,0x83,0xff,0xff,0x15,0x00,0x00,0x03, 522 + 0x00}}, /* 0x1c */ 523 + {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0x5a, 524 + 0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07, 525 + 0x01}}, /* 0x1d */ 526 + {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0x5a, 527 + 0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07, 528 + 0x01}}, /* 0x1e */ 529 + {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0x5a, 530 + 0x00,0x83,0xff,0xff,0x2f,0x09,0x00,0x07, 531 + 0x01}}, /* 0x1f */ 532 + {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, 533 + 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, 534 + 0x00}}, /* 0x20 */ 535 + {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, 536 + 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, 537 + 0x00}}, /* 0x21 */ 538 + {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, 539 + 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, 540 + 0x00}}, /* 0x22 */ 541 + {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, 542 + 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, 543 + 0x00}}, /* 0x23 */ 544 + {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, 545 + 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, 546 + 0x00}}, /* 0x24 */ 547 + {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, 548 + 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, 549 + 0x00}}, /* 0x25 */ 550 + {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, 551 + 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, 552 + 0x00}}, /* 0x26 */ 553 + {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f, 554 + 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01, 555 + 0x00}}, /* 0x27 */ 556 + {{0x43,0xef,0xef,0x87,0x06,0x00,0xd4,0x1f, 557 + 0xa0,0x83,0x9f,0x9f,0xd5,0x1f,0x41,0x05, 558 + 0x63}}, /* 0x28 */ 559 + {{0x45,0xef,0xef,0x89,0x07,0x01,0xd9,0x1f, 560 + 0xa0,0x83,0x9f,0x9f,0xda,0x1f,0x41,0x05, 561 + 0x63}}, /* 0x29 */ 562 + {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f, 563 + 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01, 564 + 0x00}}, /* 0x2a */ 565 + {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f, 566 + 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01, 567 + 0x00}}, /* 0x2b */ 568 + {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f, 569 + 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01, 570 + 0x00}}, /* 0x2c */ 571 + {{0x59,0xff,0xff,0x9d,0x17,0x13,0x33,0xba, 572 + 0x00,0x83,0xff,0xff,0x34,0x0f,0x41,0x05, 573 + 0x44}}, /* 0x2d */ 574 + {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x38,0xba, 575 + 0x00,0x83,0xff,0xff,0x39,0x0f,0x41,0x05, 576 + 0x44}}, /* 0x2e */ 577 + {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x3d,0xba, 578 + 0x00,0x83,0xff,0xff,0x3e,0x0f,0x41,0x05, 579 + 0x44}}, /* 0x2f */ 580 + {{0x5d,0xff,0xff,0x81,0x19,0x95,0x41,0xba, 581 + 0x00,0x84,0xff,0xff,0x42,0x0f,0x41,0x05, 582 + 0x44}}, /* 0x30 */ 583 + {{0x55,0xff,0xff,0x99,0x0d,0x0c,0x3e,0xba, 584 + 0x00,0x84,0xff,0xff,0x3f,0x0f,0x41,0x05, 585 + 0x00}}, /* 0x31 */ 586 + {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba, 587 + 0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06, 588 + 0x01}}, /* 0x32 */ 589 + {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xba, 590 + 0x26,0x89,0xdf,0xdf,0x6f,0x00,0x00,0x06, 591 + 0x01}}, /* 0x33 */ 592 + {{0x7f,0x63,0x63,0x82,0x6b,0x13,0x75,0xba, 593 + 0x29,0x8c,0xdf,0xdf,0x75,0x00,0x00,0x06, 594 + 0x01}}, /* 0x34 */ 595 + {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf1, 596 + 0xaf,0x85,0x3f,0x3f,0x25,0x30,0x00,0x02, 597 + 0x01}}, /* 0x35 */ 598 + {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1, 599 + 0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02, 600 + 0x01}}, /* 0x36 */ 601 + {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1, 602 + 0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02, 603 + 0x01}}, /* 0x37 */ 604 + {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4, 605 + 0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07, 606 + 0x01}}, /* 0x38 */ 607 + {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xd4, 608 + 0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07, 609 + 0x01}}, /* 0x39 */ 610 + {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4, 611 + 0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07, 612 + 0x01}}, /* 0x3a */ 613 + {{0xdc,0x9f,0x9f,0x80,0xaf,0x9d,0xe6,0xff, 614 + 0xc0,0x83,0xbf,0xbf,0xe7,0x10,0x00,0x07, 615 + 0x01}}, /* 0x3b */ 616 + {{0x6b,0x59,0x59,0x8f,0x5e,0x8c,0x0b,0x3e, 617 + 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05, 618 + 0x00}}, /* 0x3c */ 619 + {{0x6d,0x59,0x59,0x91,0x60,0x89,0x53,0xf0, 620 + 0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05, 621 + 0x41}}, /* 0x3d */ 622 + {{0x86,0x6a,0x6a,0x8a,0x74,0x06,0x8c,0x15, 623 + 0x4f,0x83,0xef,0xef,0x8d,0x30,0x00,0x02, 624 + 0x00}}, /* 0x3e */ 625 + {{0x81,0x6a,0x6a,0x85,0x70,0x00,0x0f,0x3e, 626 + 0xeb,0x8e,0xdf,0xdf,0x10,0x00,0x00,0x02, 627 + 0x00}}, /* 0x3f */ 628 + {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1, 629 + 0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02, 630 + 0x01}}, /* 0x40 */ 631 + {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5, 632 + 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02, 633 + 0x01}}, /* 0x41 */ 634 + {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x20,0xf5, 635 + 0x03,0x88,0xff,0xff,0x21,0x10,0x00,0x07, 636 + 0x01}}, /* 0x42 */ 637 + {{0xe6,0xae,0xae,0x8a,0xbd,0x90,0x3d,0x10, 638 + 0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x00,0x03, 639 + 0x00}}, /* 0x43 */ 640 + {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef, 641 + 0x60,0x83,0x5f,0x5f,0x83,0x10,0x00,0x07, 642 + 0x01}}, /* 0x44 */ 643 + {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15, 644 + 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02, 645 + 0x00}}, /* 0x45 */ 646 + {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E, 647 + 0xE5,0x8d,0xDF,0xe4,0x04,0x00,0x00,0x06, 648 + 0x00}}, /* 0x46 */ 649 + {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15, 650 + 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02, 651 + 0x00}}, /* 0x47 */ 652 + {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E, 653 + 0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02, 654 + 0x00}}, /* 0x48 */ 655 + {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd, 656 + 0x01,0x8d,0xff,0x00,0x27,0x10,0x00,0x03, 657 + 0x01}}, /* 0x49 */ 658 + {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff, 659 + 0x60,0x8b,0x5f,0x5f,0x8b,0x10,0x00,0x03, 660 + 0x01}}, /* 0x4a */ 661 + {{0xea,0xae,0xae,0x8e,0xba,0x82,0x40,0x10, 662 + 0x1b,0x87,0x19,0x1a,0x41,0x0f,0x00,0x03, 663 + 0x00}}, /* 0x4b */ 664 + {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff, 665 + 0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07, 666 + 0x01}}, /* 0x4c */ 667 + {{0x75,0x5f,0x5f,0x99,0x66,0x90,0x53,0xf0, 668 + 0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05, 669 + 0x41}}, 670 + {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e, 671 + 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00, 672 + 0x00}}, /* 0x4e */ 673 + {{0xcd,0x9f,0x9f,0x91,0xab,0x1c,0x3a,0xff, 674 + 0x20,0x83,0x1f,0x1f,0x3b,0x10,0x00,0x07, 675 + 0x21}}, /* 0x4f */ 676 + {{0x15,0xd1,0xd1,0x99,0xe2,0x19,0x3d,0x10, 677 + 0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x01,0x0c, 678 + 0x20}}, /* 0x50 */ 679 + {{0x0e,0xef,0xef,0x92,0xfe,0x03,0x30,0xf0, 680 + 0x1e,0x83,0x1b,0x1c,0x31,0x00,0x01,0x00, 681 + 0x61}}, /* 0x51 */ 682 + {{0x85,0x77,0x77,0x89,0x7d,0x01,0x31,0xf0, 683 + 0x1e,0x84,0x1b,0x1c,0x32,0x00,0x00,0x02, 684 + 0x41}}, /* 0x52 */ 685 + {{0x87,0x77,0x77,0x8b,0x81,0x0b,0x68,0xf0, 686 + 0x5a,0x80,0x57,0x57,0x69,0x00,0x00,0x02, 687 + 0x01}}, /* 0x53 */ 688 + {{0xcd,0x8f,0x8f,0x91,0x9b,0x1b,0x7a,0xff, 689 + 0x64,0x8c,0x5f,0x62,0x7b,0x10,0x00,0x07, 690 + 0x41}} /* 0x54 */ 691 + }; 692 + 693 + static struct SiS_VCLKData SiSUSB_VCLKData[] = 694 + { 695 + { 0x1b,0xe1, 25}, /* 0x00 */ 696 + { 0x4e,0xe4, 28}, /* 0x01 */ 697 + { 0x57,0xe4, 31}, /* 0x02 */ 698 + { 0xc3,0xc8, 36}, /* 0x03 */ 699 + { 0x42,0xe2, 40}, /* 0x04 */ 700 + { 0xfe,0xcd, 43}, /* 0x05 */ 701 + { 0x5d,0xc4, 44}, /* 0x06 */ 702 + { 0x52,0xe2, 49}, /* 0x07 */ 703 + { 0x53,0xe2, 50}, /* 0x08 */ 704 + { 0x74,0x67, 52}, /* 0x09 */ 705 + { 0x6d,0x66, 56}, /* 0x0a */ 706 + { 0x5a,0x64, 65}, /* 0x0b */ 707 + { 0x46,0x44, 67}, /* 0x0c */ 708 + { 0xb1,0x46, 68}, /* 0x0d */ 709 + { 0xd3,0x4a, 72}, /* 0x0e */ 710 + { 0x29,0x61, 75}, /* 0x0f */ 711 + { 0x6e,0x46, 76}, /* 0x10 */ 712 + { 0x2b,0x61, 78}, /* 0x11 */ 713 + { 0x31,0x42, 79}, /* 0x12 */ 714 + { 0xab,0x44, 83}, /* 0x13 */ 715 + { 0x46,0x25, 84}, /* 0x14 */ 716 + { 0x78,0x29, 86}, /* 0x15 */ 717 + { 0x62,0x44, 94}, /* 0x16 */ 718 + { 0x2b,0x41,104}, /* 0x17 */ 719 + { 0x3a,0x23,105}, /* 0x18 */ 720 + { 0x70,0x44,108}, /* 0x19 */ 721 + { 0x3c,0x23,109}, /* 0x1a */ 722 + { 0x5e,0x43,113}, /* 0x1b */ 723 + { 0xbc,0x44,116}, /* 0x1c */ 724 + { 0xe0,0x46,132}, /* 0x1d */ 725 + { 0x54,0x42,135}, /* 0x1e */ 726 + { 0xea,0x2a,139}, /* 0x1f */ 727 + { 0x41,0x22,157}, /* 0x20 */ 728 + { 0x70,0x24,162}, /* 0x21 */ 729 + { 0x30,0x21,175}, /* 0x22 */ 730 + { 0x4e,0x22,189}, /* 0x23 */ 731 + { 0xde,0x26,194}, /* 0x24 */ 732 + { 0x62,0x06,202}, /* 0x25 */ 733 + { 0x3f,0x03,229}, /* 0x26 */ 734 + { 0xb8,0x06,234}, /* 0x27 */ 735 + { 0x34,0x02,253}, /* 0x28 */ 736 + { 0x58,0x04,255}, /* 0x29 */ 737 + { 0x24,0x01,265}, /* 0x2a */ 738 + { 0x9b,0x02,267}, /* 0x2b */ 739 + { 0x70,0x05,270}, /* 0x2c */ 740 + { 0x25,0x01,272}, /* 0x2d */ 741 + { 0x9c,0x02,277}, /* 0x2e */ 742 + { 0x27,0x01,286}, /* 0x2f */ 743 + { 0x3c,0x02,291}, /* 0x30 */ 744 + { 0xef,0x0a,292}, /* 0x31 */ 745 + { 0xf6,0x0a,310}, /* 0x32 */ 746 + { 0x95,0x01,315}, /* 0x33 */ 747 + { 0xf0,0x09,324}, /* 0x34 */ 748 + { 0xfe,0x0a,331}, /* 0x35 */ 749 + { 0xf3,0x09,332}, /* 0x36 */ 750 + { 0xea,0x08,340}, /* 0x37 */ 751 + { 0xe8,0x07,376}, /* 0x38 */ 752 + { 0xde,0x06,389}, /* 0x39 */ 753 + { 0x52,0x2a, 54}, /* 0x3a 301 TV */ 754 + { 0x52,0x6a, 27}, /* 0x3b 301 TV */ 755 + { 0x62,0x24, 70}, /* 0x3c 301 TV */ 756 + { 0x62,0x64, 70}, /* 0x3d 301 TV */ 757 + { 0xa8,0x4c, 30}, /* 0x3e 301 TV */ 758 + { 0x20,0x26, 33}, /* 0x3f 301 TV */ 759 + { 0x31,0xc2, 39}, /* 0x40 */ 760 + { 0x60,0x36, 30}, /* 0x41 Chrontel */ 761 + { 0x40,0x4a, 28}, /* 0x42 Chrontel */ 762 + { 0x9f,0x46, 44}, /* 0x43 Chrontel */ 763 + { 0x97,0x2c, 26}, /* 0x44 */ 764 + { 0x44,0xe4, 25}, /* 0x45 Chrontel */ 765 + { 0x7e,0x32, 47}, /* 0x46 Chrontel */ 766 + { 0x8a,0x24, 31}, /* 0x47 Chrontel */ 767 + { 0x97,0x2c, 26}, /* 0x48 Chrontel */ 768 + { 0xce,0x3c, 39}, /* 0x49 */ 769 + { 0x52,0x4a, 36}, /* 0x4a Chrontel */ 770 + { 0x34,0x61, 95}, /* 0x4b */ 771 + { 0x78,0x27,108}, /* 0x4c - was 102 */ 772 + { 0x66,0x43,123}, /* 0x4d Modes 0x26-0x28 (1400x1050) */ 773 + { 0x41,0x4e, 21}, /* 0x4e */ 774 + { 0xa1,0x4a, 29}, /* 0x4f Chrontel */ 775 + { 0x19,0x42, 42}, /* 0x50 */ 776 + { 0x54,0x46, 58}, /* 0x51 Chrontel */ 777 + { 0x25,0x42, 61}, /* 0x52 */ 778 + { 0x44,0x44, 66}, /* 0x53 Chrontel */ 779 + { 0x3a,0x62, 70}, /* 0x54 Chrontel */ 780 + { 0x62,0xc6, 34}, /* 0x55 848x480-60 */ 781 + { 0x6a,0xc6, 37}, /* 0x56 848x480-75 - TEMP */ 782 + { 0xbf,0xc8, 35}, /* 0x57 856x480-38i,60 */ 783 + { 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) */ 784 + { 0x52,0x07,149}, /* 0x59 1280x960-85 */ 785 + { 0x56,0x07,156}, /* 0x5a 1400x1050-75 */ 786 + { 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */ 787 + { 0x45,0x25, 83}, /* 0x5c 1280x800 */ 788 + { 0x70,0x0a,147}, /* 0x5d 1680x1050 */ 789 + { 0x70,0x24,162}, /* 0x5e 1600x1200 */ 790 + { 0x5a,0x64, 65}, /* 0x5f 1280x720 - temp */ 791 + { 0x63,0x46, 68}, /* 0x60 1280x768_2 */ 792 + { 0x31,0x42, 79}, /* 0x61 1280x768_3 - temp */ 793 + { 0, 0, 0}, /* 0x62 - custom (will be filled out at run-time) */ 794 + { 0x5a,0x64, 65}, /* 0x63 1280x720 (LCD LVDS) */ 795 + { 0x70,0x28, 90}, /* 0x64 1152x864@60 */ 796 + { 0x41,0xc4, 32}, /* 0x65 848x480@60 */ 797 + { 0x5c,0xc6, 32}, /* 0x66 856x480@60 */ 798 + { 0x76,0xe7, 27}, /* 0x67 720x480@60 */ 799 + { 0x5f,0xc6, 33}, /* 0x68 720/768x576@60 */ 800 + { 0x52,0x27, 75}, /* 0x69 1920x1080i 60Hz interlaced */ 801 + { 0x7c,0x6b, 38}, /* 0x6a 960x540@60 */ 802 + { 0xe3,0x56, 41}, /* 0x6b 960x600@60 */ 803 + { 0x45,0x25, 83}, /* 0x6c 1280x800 */ 804 + { 0x70,0x28, 90}, /* 0x6d 1152x864@60 */ 805 + { 0x15,0xe1, 20}, /* 0x6e 640x400@60 (fake, not actually used) */ 806 + { 0x5f,0xc6, 33}, /* 0x6f 720x576@60 */ 807 + { 0x37,0x5a, 10}, /* 0x70 320x200@60 (fake, not actually used) */ 808 + { 0x2b,0xc2, 35} /* 0x71 768@576@60 */ 809 + }; 810 + 811 + void SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr); 812 + unsigned short SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth); 813 + int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo); 814 + int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo); 815 + 816 + extern int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data); 817 + extern int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data); 818 + extern int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, 819 + u8 index, u8 data); 820 + extern int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, 821 + u8 index, u8 *data); 822 + extern int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, 823 + u8 idx, u8 myand, u8 myor); 824 + extern int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, 825 + u8 index, u8 myor); 826 + extern int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, 827 + u8 idx, u8 myand); 828 + 829 + #endif 830 +
+169
drivers/usb/misc/sisusbvga/sisusb_struct.h
··· 1 + /* 2 + * General structure definitions for universal mode switching modules 3 + * 4 + * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria 5 + * 6 + * If distributed as part of the Linux kernel, the following license terms 7 + * apply: 8 + * 9 + * * This program is free software; you can redistribute it and/or modify 10 + * * it under the terms of the GNU General Public License as published by 11 + * * the Free Software Foundation; either version 2 of the named License, 12 + * * or any later version. 13 + * * 14 + * * This program is distributed in the hope that it will be useful, 15 + * * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 + * * GNU General Public License for more details. 18 + * * 19 + * * You should have received a copy of the GNU General Public License 20 + * * along with this program; if not, write to the Free Software 21 + * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA 22 + * 23 + * Otherwise, the following license terms apply: 24 + * 25 + * * Redistribution and use in source and binary forms, with or without 26 + * * modification, are permitted provided that the following conditions 27 + * * are met: 28 + * * 1) Redistributions of source code must retain the above copyright 29 + * * notice, this list of conditions and the following disclaimer. 30 + * * 2) Redistributions in binary form must reproduce the above copyright 31 + * * notice, this list of conditions and the following disclaimer in the 32 + * * documentation and/or other materials provided with the distribution. 33 + * * 3) The name of the author may not be used to endorse or promote products 34 + * * derived from this software without specific prior written permission. 35 + * * 36 + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 37 + * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 38 + * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 39 + * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 40 + * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 41 + * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 42 + * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 43 + * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 44 + * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 45 + * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 46 + * 47 + * Author: Thomas Winischhofer <thomas@winischhofer.net> 48 + * 49 + */ 50 + 51 + #ifndef _SISUSB_STRUCT_H_ 52 + #define _SISUSB_STRUCT_H_ 53 + 54 + struct SiS_St { 55 + unsigned char St_ModeID; 56 + unsigned short St_ModeFlag; 57 + unsigned char St_StTableIndex; 58 + unsigned char St_CRT2CRTC; 59 + unsigned char St_ResInfo; 60 + unsigned char VB_StTVFlickerIndex; 61 + unsigned char VB_StTVEdgeIndex; 62 + unsigned char VB_StTVYFilterIndex; 63 + unsigned char St_PDC; 64 + }; 65 + 66 + struct SiS_StandTable 67 + { 68 + unsigned char CRT_COLS; 69 + unsigned char ROWS; 70 + unsigned char CHAR_HEIGHT; 71 + unsigned short CRT_LEN; 72 + unsigned char SR[4]; 73 + unsigned char MISC; 74 + unsigned char CRTC[0x19]; 75 + unsigned char ATTR[0x14]; 76 + unsigned char GRC[9]; 77 + }; 78 + 79 + struct SiS_StResInfo_S { 80 + unsigned short HTotal; 81 + unsigned short VTotal; 82 + }; 83 + 84 + struct SiS_Ext 85 + { 86 + unsigned char Ext_ModeID; 87 + unsigned short Ext_ModeFlag; 88 + unsigned short Ext_VESAID; 89 + unsigned char Ext_RESINFO; 90 + unsigned char VB_ExtTVFlickerIndex; 91 + unsigned char VB_ExtTVEdgeIndex; 92 + unsigned char VB_ExtTVYFilterIndex; 93 + unsigned char VB_ExtTVYFilterIndexROM661; 94 + unsigned char REFindex; 95 + char ROMMODEIDX661; 96 + }; 97 + 98 + struct SiS_Ext2 99 + { 100 + unsigned short Ext_InfoFlag; 101 + unsigned char Ext_CRT1CRTC; 102 + unsigned char Ext_CRTVCLK; 103 + unsigned char Ext_CRT2CRTC; 104 + unsigned char Ext_CRT2CRTC_NS; 105 + unsigned char ModeID; 106 + unsigned short XRes; 107 + unsigned short YRes; 108 + unsigned char Ext_PDC; 109 + unsigned char Ext_FakeCRT2CRTC; 110 + unsigned char Ext_FakeCRT2Clk; 111 + }; 112 + 113 + struct SiS_CRT1Table 114 + { 115 + unsigned char CR[17]; 116 + }; 117 + 118 + struct SiS_VCLKData 119 + { 120 + unsigned char SR2B,SR2C; 121 + unsigned short CLOCK; 122 + }; 123 + 124 + struct SiS_ModeResInfo 125 + { 126 + unsigned short HTotal; 127 + unsigned short VTotal; 128 + unsigned char XChar; 129 + unsigned char YChar; 130 + }; 131 + 132 + struct SiS_Private 133 + { 134 + void *sisusb; 135 + 136 + unsigned long IOAddress; 137 + 138 + unsigned long SiS_P3c4; 139 + unsigned long SiS_P3d4; 140 + unsigned long SiS_P3c0; 141 + unsigned long SiS_P3ce; 142 + unsigned long SiS_P3c2; 143 + unsigned long SiS_P3ca; 144 + unsigned long SiS_P3c6; 145 + unsigned long SiS_P3c7; 146 + unsigned long SiS_P3c8; 147 + unsigned long SiS_P3c9; 148 + unsigned long SiS_P3cb; 149 + unsigned long SiS_P3cc; 150 + unsigned long SiS_P3cd; 151 + unsigned long SiS_P3da; 152 + unsigned long SiS_Part1Port; 153 + 154 + unsigned char SiS_MyCR63; 155 + unsigned short SiS_CRT1Mode; 156 + unsigned short SiS_ModeType; 157 + unsigned short SiS_SetFlag; 158 + 159 + const struct SiS_StandTable *SiS_StandTable; 160 + const struct SiS_St *SiS_SModeIDTable; 161 + const struct SiS_Ext *SiS_EModeIDTable; 162 + const struct SiS_Ext2 *SiS_RefIndex; 163 + const struct SiS_CRT1Table *SiS_CRT1Table; 164 + struct SiS_VCLKData *SiS_VCLKData; 165 + const struct SiS_ModeResInfo *SiS_ModeResInfo; 166 + }; 167 + 168 + #endif 169 +
+272 -125
drivers/usb/misc/uss720.c
··· 3 3 /* 4 4 * uss720.c -- USS720 USB Parport Cable. 5 5 * 6 - * Copyright (C) 1999 7 - * Thomas Sailer (sailer@ife.ee.ethz.ch) 6 + * Copyright (C) 1999, 2005 7 + * Thomas Sailer (t.sailer@alumni.ethz.ch) 8 8 * 9 9 * This program is free software; you can redistribute it and/or modify 10 10 * it under the terms of the GNU General Public License as published by ··· 23 23 * Based on parport_pc.c 24 24 * 25 25 * History: 26 - * 0.1 04.08.99 Created 27 - * 0.2 07.08.99 Some fixes mainly suggested by Tim Waugh 28 - * Interrupt handling currently disabled because 29 - * usb_request_irq crashes somewhere within ohci.c 30 - * for no apparent reason (that is for me, anyway) 31 - * ECP currently untested 32 - * 0.3 10.08.99 fixing merge errors 33 - * 0.4 13.08.99 Added Vendor/Product ID of Brad Hard's cable 34 - * 0.5 20.09.99 usb_control_msg wrapper used 35 - * Nov01.00 usb_device_table support by Adam J. Richter 36 - * 08.04.01 Identify version on module load. gb 26 + * 0.1 04.08.1999 Created 27 + * 0.2 07.08.1999 Some fixes mainly suggested by Tim Waugh 28 + * Interrupt handling currently disabled because 29 + * usb_request_irq crashes somewhere within ohci.c 30 + * for no apparent reason (that is for me, anyway) 31 + * ECP currently untested 32 + * 0.3 10.08.1999 fixing merge errors 33 + * 0.4 13.08.1999 Added Vendor/Product ID of Brad Hard's cable 34 + * 0.5 20.09.1999 usb_control_msg wrapper used 35 + * Nov01.2000 usb_device_table support by Adam J. Richter 36 + * 08.04.2001 Identify version on module load. gb 37 + * 0.6 02.09.2005 Fix "scheduling in interrupt" problem by making save/restore 38 + * context asynchronous 37 39 * 38 40 */ 39 41 40 42 /*****************************************************************************/ 43 + 44 + #define DEBUG 41 45 42 46 #include <linux/module.h> 43 47 #include <linux/socket.h> ··· 49 45 #include <linux/init.h> 50 46 #include <linux/usb.h> 51 47 #include <linux/delay.h> 48 + #include <linux/completion.h> 49 + #include <linux/kref.h> 52 50 53 51 /* 54 52 * Version Information 55 53 */ 56 - #define DRIVER_VERSION "v0.5" 57 - #define DRIVER_AUTHOR "Thomas M. Sailer, sailer@ife.ee.ethz.ch" 54 + #define DRIVER_VERSION "v0.6" 55 + #define DRIVER_AUTHOR "Thomas M. Sailer, t.sailer@alumni.ethz.ch" 58 56 #define DRIVER_DESC "USB Parport Cable driver for Cables using the Lucent Technologies USS720 Chip" 59 57 60 58 /* --------------------------------------------------------------------- */ 61 59 62 60 struct parport_uss720_private { 63 61 struct usb_device *usbdev; 64 - void *irqhandle; 65 - unsigned int irqpipe; 66 - unsigned char reg[7]; /* USB registers */ 62 + struct parport *pp; 63 + struct kref ref_count; 64 + __u8 reg[7]; /* USB registers */ 65 + struct list_head asynclist; 66 + spinlock_t asynclock; 67 + }; 68 + 69 + struct uss720_async_request { 70 + struct parport_uss720_private *priv; 71 + struct kref ref_count; 72 + struct list_head asynclist; 73 + struct completion compl; 74 + struct urb *urb; 75 + struct usb_ctrlrequest dr; 76 + __u8 reg[7]; 67 77 }; 68 78 69 79 /* --------------------------------------------------------------------- */ 70 80 71 - static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val) 81 + static void destroy_priv(struct kref *kref) 72 82 { 73 - struct parport_uss720_private *priv = pp->private_data; 74 - struct usb_device *usbdev = priv->usbdev; 83 + struct parport_uss720_private *priv = container_of(kref, struct parport_uss720_private, ref_count); 84 + 85 + usb_put_dev(priv->usbdev); 86 + kfree(priv); 87 + dbg("destroying priv datastructure"); 88 + } 89 + 90 + static void destroy_async(struct kref *kref) 91 + { 92 + struct uss720_async_request *rq = container_of(kref, struct uss720_async_request, ref_count); 93 + struct parport_uss720_private *priv = rq->priv; 94 + unsigned long flags; 95 + 96 + if (likely(rq->urb)) 97 + usb_free_urb(rq->urb); 98 + spin_lock_irqsave(&priv->asynclock, flags); 99 + list_del_init(&rq->asynclist); 100 + spin_unlock_irqrestore(&priv->asynclock, flags); 101 + kfree(rq); 102 + kref_put(&priv->ref_count, destroy_priv); 103 + } 104 + 105 + /* --------------------------------------------------------------------- */ 106 + 107 + static void async_complete(struct urb *urb, struct pt_regs *ptregs) 108 + { 109 + struct uss720_async_request *rq; 110 + struct parport *pp; 111 + struct parport_uss720_private *priv; 112 + 113 + rq = urb->context; 114 + priv = rq->priv; 115 + pp = priv->pp; 116 + if (urb->status) { 117 + err("async_complete: urb error %d", urb->status); 118 + } else if (rq->dr.bRequest == 3) { 119 + memcpy(priv->reg, rq->reg, sizeof(priv->reg)); 120 + #if 0 121 + dbg("async_complete regs %02x %02x %02x %02x %02x %02x %02x", 122 + (unsigned int)priv->reg[0], (unsigned int)priv->reg[1], (unsigned int)priv->reg[2], 123 + (unsigned int)priv->reg[3], (unsigned int)priv->reg[4], (unsigned int)priv->reg[5], 124 + (unsigned int)priv->reg[6]); 125 + #endif 126 + /* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */ 127 + if (rq->reg[2] & rq->reg[1] & 0x10 && pp) 128 + parport_generic_irq(0, pp, NULL); 129 + } 130 + complete(&rq->compl); 131 + kref_put(&rq->ref_count, destroy_async); 132 + } 133 + 134 + static struct uss720_async_request *submit_async_request(struct parport_uss720_private *priv, 135 + __u8 request, __u8 requesttype, __u16 value, __u16 index, 136 + unsigned int mem_flags) 137 + { 138 + struct usb_device *usbdev; 139 + struct uss720_async_request *rq; 140 + unsigned long flags; 141 + int ret; 142 + 143 + if (!priv) 144 + return NULL; 145 + usbdev = priv->usbdev; 146 + if (!usbdev) 147 + return NULL; 148 + rq = kmalloc(sizeof(struct uss720_async_request), mem_flags); 149 + if (!rq) { 150 + err("submit_async_request out of memory"); 151 + return NULL; 152 + } 153 + kref_init(&rq->ref_count); 154 + INIT_LIST_HEAD(&rq->asynclist); 155 + init_completion(&rq->compl); 156 + kref_get(&priv->ref_count); 157 + rq->priv = priv; 158 + rq->urb = usb_alloc_urb(0, mem_flags); 159 + if (!rq->urb) { 160 + kref_put(&rq->ref_count, destroy_async); 161 + err("submit_async_request out of memory"); 162 + return NULL; 163 + } 164 + rq->dr.bRequestType = requesttype; 165 + rq->dr.bRequest = request; 166 + rq->dr.wValue = cpu_to_le16(value); 167 + rq->dr.wIndex = cpu_to_le16(index); 168 + rq->dr.wLength = cpu_to_le16((request == 3) ? sizeof(rq->reg) : 0); 169 + usb_fill_control_urb(rq->urb, usbdev, (requesttype & 0x80) ? usb_rcvctrlpipe(usbdev, 0) : usb_sndctrlpipe(usbdev, 0), 170 + (unsigned char *)&rq->dr, 171 + (request == 3) ? rq->reg : NULL, (request == 3) ? sizeof(rq->reg) : 0, async_complete, rq); 172 + /* rq->urb->transfer_flags |= URB_ASYNC_UNLINK; */ 173 + spin_lock_irqsave(&priv->asynclock, flags); 174 + list_add_tail(&rq->asynclist, &priv->asynclist); 175 + spin_unlock_irqrestore(&priv->asynclock, flags); 176 + ret = usb_submit_urb(rq->urb, mem_flags); 177 + if (!ret) { 178 + kref_get(&rq->ref_count); 179 + return rq; 180 + } 181 + kref_put(&rq->ref_count, destroy_async); 182 + err("submit_async_request submit_urb failed with %d", ret); 183 + return NULL; 184 + } 185 + 186 + static unsigned int kill_all_async_requests_priv(struct parport_uss720_private *priv) 187 + { 188 + struct uss720_async_request *rq; 189 + unsigned long flags; 190 + unsigned int ret = 0; 191 + 192 + spin_lock_irqsave(&priv->asynclock, flags); 193 + list_for_each_entry(rq, &priv->asynclist, asynclist) { 194 + usb_unlink_urb(rq->urb); 195 + ret++; 196 + } 197 + spin_unlock_irqrestore(&priv->asynclock, flags); 198 + return ret; 199 + } 200 + 201 + /* --------------------------------------------------------------------- */ 202 + 203 + static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val, unsigned int mem_flags) 204 + { 205 + struct parport_uss720_private *priv; 206 + struct uss720_async_request *rq; 75 207 static const unsigned char regindex[9] = { 76 208 4, 0, 1, 5, 5, 0, 2, 3, 6 77 209 }; 78 210 int ret; 79 211 80 - if (!usbdev) 81 - return -1; 82 - ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev,0), 3, 0xc0, ((unsigned int)reg) << 8, 0, priv->reg, 7, 1000); 83 - if (ret != 7) { 84 - printk(KERN_DEBUG "uss720: get_1284_register(%d) failed, status 0x%x expected 7\n", 85 - (unsigned int)reg, ret); 86 - ret = -1; 87 - } else { 88 - #if 0 89 - printk(KERN_DEBUG "uss720: get_1284_register(%d) return %02x %02x %02x %02x %02x %02x %02x\n", 90 - (unsigned int)reg, (unsigned int)priv->reg[0], (unsigned int)priv->reg[1], 91 - (unsigned int)priv->reg[2], (unsigned int)priv->reg[3], (unsigned int)priv->reg[4], 92 - (unsigned int)priv->reg[5], (unsigned int)priv->reg[6]); 93 - #endif 94 - /* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */ 95 - if (priv->reg[2] & priv->reg[1] & 0x10) 96 - parport_generic_irq(0, pp, NULL); 97 - ret = 0; 212 + if (!pp) 213 + return -EIO; 214 + priv = pp->private_data; 215 + rq = submit_async_request(priv, 3, 0xc0, ((unsigned int)reg) << 8, 0, mem_flags); 216 + if (!rq) { 217 + err("get_1284_register(%u) failed", (unsigned int)reg); 218 + return -EIO; 98 219 } 99 - if (val) 220 + if (!val) { 221 + kref_put(&rq->ref_count, destroy_async); 222 + return 0; 223 + } 224 + if (wait_for_completion_timeout(&rq->compl, HZ)) { 225 + ret = rq->urb->status; 100 226 *val = priv->reg[(reg >= 9) ? 0 : regindex[reg]]; 101 - return ret; 227 + if (ret) 228 + warn("get_1284_register: usb error %d", ret); 229 + kref_put(&rq->ref_count, destroy_async); 230 + return ret; 231 + } 232 + warn("get_1284_register timeout"); 233 + kill_all_async_requests_priv(priv); 234 + return -EIO; 102 235 } 103 236 104 - static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val) 237 + static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val, unsigned int mem_flags) 105 238 { 106 - struct parport_uss720_private *priv = pp->private_data; 107 - struct usb_device *usbdev = priv->usbdev; 108 - int ret; 239 + struct parport_uss720_private *priv; 240 + struct uss720_async_request *rq; 109 241 110 - if (!usbdev) 111 - return -1; 112 - ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev,0), 4, 0x40, (((unsigned int)reg) << 8) | val, 0, NULL, 0, 1000); 113 - if (ret) { 114 - printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x) failed, status 0x%x\n", 115 - (unsigned int)reg, (unsigned int)val, ret); 116 - } else { 117 - #if 0 118 - printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x)\n", 119 - (unsigned int)reg, (unsigned int)val); 120 - #endif 242 + if (!pp) 243 + return -EIO; 244 + priv = pp->private_data; 245 + rq = submit_async_request(priv, 4, 0x40, (((unsigned int)reg) << 8) | val, 0, mem_flags); 246 + if (!rq) { 247 + err("set_1284_register(%u,%u) failed", (unsigned int)reg, (unsigned int)val); 248 + return -EIO; 121 249 } 122 - return ret; 250 + kref_put(&rq->ref_count, destroy_async); 251 + return 0; 123 252 } 124 253 125 254 /* --------------------------------------------------------------------- */ ··· 269 132 { 270 133 struct parport_uss720_private *priv = pp->private_data; 271 134 int mode; 135 + __u8 reg; 272 136 273 - if (get_1284_register(pp, 6, NULL)) 137 + if (get_1284_register(pp, 6, &reg, GFP_KERNEL)) 274 138 return -EIO; 275 139 /* Bits <7:5> contain the mode. */ 276 140 mode = (priv->reg[2] >> 5) & 0x7; ··· 291 153 case ECR_ECP: /* ECP Parallel Port mode */ 292 154 /* Poll slowly. */ 293 155 for (;;) { 294 - if (get_1284_register(pp, 6, NULL)) 156 + if (get_1284_register(pp, 6, &reg, GFP_KERNEL)) 295 157 return -EIO; 296 158 if (priv->reg[2] & 0x01) 297 159 break; ··· 305 167 } 306 168 } 307 169 /* Set the mode. */ 308 - if (set_1284_register(pp, 6, m << 5)) 170 + if (set_1284_register(pp, 6, m << 5, GFP_KERNEL)) 171 + return -EIO; 172 + if (get_1284_register(pp, 6, &reg, GFP_KERNEL)) 309 173 return -EIO; 310 174 return 0; 311 175 } ··· 319 179 { 320 180 unsigned char stat; 321 181 322 - if (get_1284_register(pp, 1, &stat)) 182 + if (get_1284_register(pp, 1, &stat, GFP_KERNEL)) 323 183 return 1; 324 184 return stat & 1; 325 185 } ··· 345 205 346 206 static void parport_uss720_write_data(struct parport *pp, unsigned char d) 347 207 { 348 - set_1284_register(pp, 0, d); 208 + set_1284_register(pp, 0, d, GFP_KERNEL); 349 209 } 350 210 351 211 static unsigned char parport_uss720_read_data(struct parport *pp) 352 212 { 353 213 unsigned char ret; 354 214 355 - if (get_1284_register(pp, 0, &ret)) 215 + if (get_1284_register(pp, 0, &ret, GFP_KERNEL)) 356 216 return 0; 357 217 return ret; 358 218 } ··· 362 222 struct parport_uss720_private *priv = pp->private_data; 363 223 364 224 d = (d & 0xf) | (priv->reg[1] & 0xf0); 365 - if (set_1284_register(pp, 2, d)) 225 + if (set_1284_register(pp, 2, d, GFP_KERNEL)) 366 226 return; 367 227 priv->reg[1] = d; 368 228 } ··· 381 241 mask &= 0x0f; 382 242 val &= 0x0f; 383 243 d = (priv->reg[1] & (~mask)) ^ val; 384 - if (set_1284_register(pp, 2, d)) 244 + if (set_1284_register(pp, 2, d, GFP_KERNEL)) 385 245 return 0; 386 246 priv->reg[1] = d; 387 247 return d & 0xf; ··· 391 251 { 392 252 unsigned char ret; 393 253 394 - if (get_1284_register(pp, 1, &ret)) 254 + if (get_1284_register(pp, 1, &ret, GFP_KERNEL)) 395 255 return 0; 396 256 return ret & 0xf8; 397 257 } ··· 402 262 unsigned char d; 403 263 404 264 d = priv->reg[1] & ~0x10; 405 - if (set_1284_register(pp, 2, d)) 265 + if (set_1284_register(pp, 2, d, GFP_KERNEL)) 406 266 return; 407 267 priv->reg[1] = d; 408 268 } ··· 413 273 unsigned char d; 414 274 415 275 d = priv->reg[1] | 0x10; 416 - if (set_1284_register(pp, 2, d)) 276 + if (set_1284_register(pp, 2, d, GFP_KERNEL)) 417 277 return; 418 278 priv->reg[1] = d; 419 279 } ··· 424 284 unsigned char d; 425 285 426 286 d = priv->reg[1] & ~0x20; 427 - if (set_1284_register(pp, 2, d)) 287 + if (set_1284_register(pp, 2, d, GFP_KERNEL)) 428 288 return; 429 289 priv->reg[1] = d; 430 290 } ··· 435 295 unsigned char d; 436 296 437 297 d = priv->reg[1] | 0x20; 438 - if (set_1284_register(pp, 2, d)) 298 + if (set_1284_register(pp, 2, d, GFP_KERNEL)) 439 299 return; 440 300 priv->reg[1] = d; 441 301 } ··· 450 310 { 451 311 struct parport_uss720_private *priv = pp->private_data; 452 312 453 - if (get_1284_register(pp, 2, NULL)) 313 + #if 0 314 + if (get_1284_register(pp, 2, NULL, GFP_ATOMIC)) 454 315 return; 316 + #endif 455 317 s->u.pc.ctr = priv->reg[1]; 456 318 s->u.pc.ecr = priv->reg[2]; 457 319 } 458 320 459 321 static void parport_uss720_restore_state(struct parport *pp, struct parport_state *s) 460 322 { 461 - set_1284_register(pp, 2, s->u.pc.ctr); 462 - set_1284_register(pp, 6, s->u.pc.ecr); 463 - get_1284_register(pp, 2, NULL); 323 + struct parport_uss720_private *priv = pp->private_data; 324 + 325 + set_1284_register(pp, 2, s->u.pc.ctr, GFP_ATOMIC); 326 + set_1284_register(pp, 6, s->u.pc.ecr, GFP_ATOMIC); 327 + get_1284_register(pp, 2, NULL, GFP_ATOMIC); 328 + priv->reg[1] = s->u.pc.ctr; 329 + priv->reg[2] = s->u.pc.ecr; 464 330 } 465 331 466 332 static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t length, int flags) ··· 477 331 if (change_mode(pp, ECR_EPP)) 478 332 return 0; 479 333 for (; got < length; got++) { 480 - if (get_1284_register(pp, 4, (char *)buf)) 334 + if (get_1284_register(pp, 4, (char *)buf, GFP_KERNEL)) 481 335 break; 482 336 buf++; 483 337 if (priv->reg[0] & 0x01) { ··· 498 352 if (change_mode(pp, ECR_EPP)) 499 353 return 0; 500 354 for (; written < length; written++) { 501 - if (set_1284_register(pp, 4, (char *)buf)) 355 + if (set_1284_register(pp, 4, (char *)buf, GFP_KERNEL)) 502 356 break; 503 357 ((char*)buf)++; 504 - if (get_1284_register(pp, 1, NULL)) 358 + if (get_1284_register(pp, 1, NULL, GFP_KERNEL)) 505 359 break; 506 360 if (priv->reg[0] & 0x01) { 507 361 clear_epp_timeout(pp); ··· 536 390 if (change_mode(pp, ECR_EPP)) 537 391 return 0; 538 392 for (; got < length; got++) { 539 - if (get_1284_register(pp, 3, (char *)buf)) 393 + if (get_1284_register(pp, 3, (char *)buf, GFP_KERNEL)) 540 394 break; 541 395 buf++; 542 396 if (priv->reg[0] & 0x01) { ··· 556 410 if (change_mode(pp, ECR_EPP)) 557 411 return 0; 558 412 for (; written < length; written++) { 559 - if (set_1284_register(pp, 3, *(char *)buf)) 413 + if (set_1284_register(pp, 3, *(char *)buf, GFP_KERNEL)) 560 414 break; 561 415 buf++; 562 - if (get_1284_register(pp, 1, NULL)) 416 + if (get_1284_register(pp, 1, NULL, GFP_KERNEL)) 563 417 break; 564 418 if (priv->reg[0] & 0x01) { 565 419 clear_epp_timeout(pp); ··· 613 467 if (change_mode(pp, ECR_ECP)) 614 468 return 0; 615 469 for (; written < len; written++) { 616 - if (set_1284_register(pp, 5, *(char *)buffer)) 470 + if (set_1284_register(pp, 5, *(char *)buffer, GFP_KERNEL)) 617 471 break; 618 472 buffer++; 619 473 } ··· 682 536 static int uss720_probe(struct usb_interface *intf, 683 537 const struct usb_device_id *id) 684 538 { 685 - struct usb_device *usbdev = interface_to_usbdev(intf); 539 + struct usb_device *usbdev = usb_get_dev(interface_to_usbdev(intf)); 686 540 struct usb_host_interface *interface; 687 541 struct usb_host_endpoint *endpoint; 688 542 struct parport_uss720_private *priv; 689 543 struct parport *pp; 544 + unsigned char reg; 690 545 int i; 691 546 692 - printk(KERN_DEBUG "uss720: probe: vendor id 0x%x, device id 0x%x\n", 693 - le16_to_cpu(usbdev->descriptor.idVendor), 694 - le16_to_cpu(usbdev->descriptor.idProduct)); 547 + dbg("probe: vendor id 0x%x, device id 0x%x\n", 548 + le16_to_cpu(usbdev->descriptor.idVendor), 549 + le16_to_cpu(usbdev->descriptor.idProduct)); 695 550 696 551 /* our known interfaces have 3 alternate settings */ 697 - if (intf->num_altsetting != 3) 552 + if (intf->num_altsetting != 3) { 553 + usb_put_dev(usbdev); 698 554 return -ENODEV; 699 - 555 + } 700 556 i = usb_set_interface(usbdev, intf->altsetting->desc.bInterfaceNumber, 2); 701 - printk(KERN_DEBUG "uss720: set inteface result %d\n", i); 557 + dbg("set inteface result %d", i); 702 558 703 559 interface = intf->cur_altsetting; 704 560 705 561 /* 706 562 * Allocate parport interface 707 563 */ 708 - printk(KERN_INFO "uss720: (C) 1999 by Thomas Sailer, <sailer@ife.ee.ethz.ch>\n"); 709 - 710 - if (!(priv = kmalloc(sizeof(struct parport_uss720_private), GFP_KERNEL))) 564 + if (!(priv = kcalloc(sizeof(struct parport_uss720_private), 1, GFP_KERNEL))) { 565 + usb_put_dev(usbdev); 711 566 return -ENOMEM; 567 + } 568 + priv->pp = NULL; 569 + priv->usbdev = usbdev; 570 + kref_init(&priv->ref_count); 571 + spin_lock_init(&priv->asynclock); 572 + INIT_LIST_HEAD(&priv->asynclist); 712 573 if (!(pp = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &parport_uss720_ops))) { 713 - printk(KERN_WARNING "usb-uss720: could not register parport\n"); 574 + warn("could not register parport"); 714 575 goto probe_abort; 715 576 } 716 577 578 + priv->pp = pp; 717 579 pp->private_data = priv; 718 - priv->usbdev = usbdev; 719 580 pp->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP | PARPORT_MODE_ECP | PARPORT_MODE_COMPAT; 720 581 721 582 /* set the USS720 control register to manual mode, no ECP compression, enable all ints */ 722 - set_1284_register(pp, 7, 0x00); 723 - set_1284_register(pp, 6, 0x30); /* PS/2 mode */ 724 - set_1284_register(pp, 2, 0x0c); 583 + set_1284_register(pp, 7, 0x00, GFP_KERNEL); 584 + set_1284_register(pp, 6, 0x30, GFP_KERNEL); /* PS/2 mode */ 585 + set_1284_register(pp, 2, 0x0c, GFP_KERNEL); 725 586 /* debugging */ 726 - get_1284_register(pp, 0, NULL); 727 - printk("uss720: reg: %02x %02x %02x %02x %02x %02x %02x\n", 728 - priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]); 587 + get_1284_register(pp, 0, &reg, GFP_KERNEL); 588 + dbg("reg: %02x %02x %02x %02x %02x %02x %02x", 589 + priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]); 729 590 730 591 endpoint = &interface->endpoint[2]; 731 - printk(KERN_DEBUG "uss720: epaddr %d interval %d\n", endpoint->desc.bEndpointAddress, endpoint->desc.bInterval); 732 - #if 0 733 - priv->irqpipe = usb_rcvctrlpipe(usbdev, endpoint->bEndpointAddress); 734 - i = usb_request_irq(usbdev, priv->irqpipe, 735 - uss720_irq, endpoint->bInterval, 736 - pp, &priv->irqhandle); 737 - if (i) { 738 - printk (KERN_WARNING "usb-uss720: usb_request_irq failed (0x%x)\n", i); 739 - goto probe_abort_port; 740 - } 741 - #endif 592 + dbg("epaddr %d interval %d", endpoint->desc.bEndpointAddress, endpoint->desc.bInterval); 742 593 parport_announce_port(pp); 743 594 744 - usb_set_intfdata (intf, pp); 595 + usb_set_intfdata(intf, pp); 745 596 return 0; 746 597 747 - #if 0 748 - probe_abort_port: 749 - parport_put_port(pp); 750 - #endif 751 598 probe_abort: 752 - kfree(priv); 599 + kill_all_async_requests_priv(priv); 600 + kref_put(&priv->ref_count, destroy_priv); 753 601 return -ENODEV; 754 602 } 755 603 756 604 static void uss720_disconnect(struct usb_interface *intf) 757 605 { 758 - struct parport *pp = usb_get_intfdata (intf); 606 + struct parport *pp = usb_get_intfdata(intf); 759 607 struct parport_uss720_private *priv; 608 + struct usb_device *usbdev; 760 609 761 - usb_set_intfdata (intf, NULL); 610 + dbg("disconnect"); 611 + usb_set_intfdata(intf, NULL); 762 612 if (pp) { 763 613 priv = pp->private_data; 764 - parport_remove_port(pp); 765 - #if 0 766 - usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe); 767 - #endif 614 + usbdev = priv->usbdev; 768 615 priv->usbdev = NULL; 616 + priv->pp = NULL; 617 + dbg("parport_remove_port"); 618 + parport_remove_port(pp); 769 619 parport_put_port(pp); 770 - kfree(priv); 620 + kill_all_async_requests_priv(priv); 621 + kref_put(&priv->ref_count, destroy_priv); 771 622 } 623 + dbg("disconnect done"); 772 624 } 773 625 774 626 /* table of cables that work through this driver */ ··· 791 647 792 648 /* --------------------------------------------------------------------- */ 793 649 794 - MODULE_AUTHOR( DRIVER_AUTHOR ); 795 - MODULE_DESCRIPTION( DRIVER_DESC ); 650 + MODULE_AUTHOR(DRIVER_AUTHOR); 651 + MODULE_DESCRIPTION(DRIVER_DESC); 796 652 MODULE_LICENSE("GPL"); 797 653 798 654 static int __init uss720_init(void) ··· 803 659 goto out; 804 660 805 661 info(DRIVER_VERSION ":" DRIVER_DESC); 662 + info("NOTE: this is a special purpose driver to allow nonstandard"); 663 + info("protocols (eg. bitbang) over USS720 usb to parallel cables"); 664 + info("If you just want to connect to a printer, use usblp instead"); 806 665 out: 807 666 return retval; 808 667 }
+1 -1
drivers/usb/mon/mon_text.c
··· 79 79 return '-'; 80 80 81 81 if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP) 82 - return 'D'; 82 + return mon_dmapeek(ep->setup, urb->setup_dma, SETUP_MAX); 83 83 if (urb->setup_packet == NULL) 84 84 return 'Z'; /* '0' would be not as pretty. */ 85 85
+4 -1
drivers/usb/serial/cp2101.c
··· 32 32 /* 33 33 * Version Information 34 34 */ 35 - #define DRIVER_VERSION "v0.04" 35 + #define DRIVER_VERSION "v0.05" 36 36 #define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver" 37 37 38 38 /* ··· 54 54 static int debug; 55 55 56 56 static struct usb_device_id id_table [] = { 57 + { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */ 57 58 { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ 58 59 { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ 60 + { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ 61 + { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */ 59 62 { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ 60 63 { } /* Terminating Entry */ 61 64 };
+1 -2
drivers/usb/serial/cypress_m8.c
··· 610 610 timeout = max((HZ*2560)/bps,HZ/10); 611 611 else 612 612 timeout = 2*HZ; 613 - set_current_state(TASK_INTERRUPTIBLE); 614 - schedule_timeout(timeout); 613 + schedule_timeout_interruptible(timeout); 615 614 616 615 dbg("%s - stopping urbs", __FUNCTION__); 617 616 usb_kill_urb (port->interrupt_in_urb);
+1 -1
drivers/usb/serial/ftdi_sio.c
··· 914 914 unsigned interfaces; 915 915 916 916 /* Assume it is not the original SIO device for now. */ 917 - priv->baud_base = 48000000 / 16; 917 + priv->baud_base = 48000000 / 2; 918 918 priv->write_offset = 0; 919 919 920 920 version = le16_to_cpu(udev->descriptor.bcdDevice);
+2 -2
drivers/usb/serial/pl2303.c
··· 95 95 { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) }, 96 96 { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) }, 97 97 { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) }, 98 + { USB_DEVICE( NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID ) }, 98 99 { } /* Terminating entry */ 99 100 }; 100 101 ··· 653 652 timeout = max((HZ*2560)/bps,HZ/10); 654 653 else 655 654 timeout = 2*HZ; 656 - set_current_state(TASK_INTERRUPTIBLE); 657 - schedule_timeout(timeout); 655 + schedule_timeout_interruptible(timeout); 658 656 659 657 /* shutdown our urbs */ 660 658 dbg("%s - shutting down urbs", __FUNCTION__);
+4
drivers/usb/serial/pl2303.h
··· 58 58 59 59 #define SYNTECH_VENDOR_ID 0x0745 60 60 #define SYNTECH_PRODUCT_ID 0x0001 61 + 62 + /* Nokia CA-42 Cable */ 63 + #define NOKIA_CA42_VENDOR_ID 0x078b 64 + #define NOKIA_CA42_PRODUCT_ID 0x1234
+9 -11
drivers/usb/storage/scsiglue.c
··· 227 227 ***********************************************************************/ 228 228 229 229 /* Command timeout and abort */ 230 - /* This is always called with scsi_lock(host) held */ 231 230 static int command_abort(struct scsi_cmnd *srb) 232 231 { 233 232 struct us_data *us = host_to_us(srb->device->host); 234 233 235 234 US_DEBUGP("%s called\n", __FUNCTION__); 236 235 236 + /* us->srb together with the TIMED_OUT, RESETTING, and ABORTING 237 + * bits are protected by the host lock. */ 238 + scsi_lock(us_to_host(us)); 239 + 237 240 /* Is this command still active? */ 238 241 if (us->srb != srb) { 242 + scsi_unlock(us_to_host(us)); 239 243 US_DEBUGP ("-- nothing to abort\n"); 240 244 return FAILED; 241 245 } 242 246 243 247 /* Set the TIMED_OUT bit. Also set the ABORTING bit, but only if 244 248 * a device reset isn't already in progress (to avoid interfering 245 - * with the reset). To prevent races with auto-reset, we must 246 - * stop any ongoing USB transfers while still holding the host 247 - * lock. */ 249 + * with the reset). Note that we must retain the host lock while 250 + * calling usb_stor_stop_transport(); otherwise it might interfere 251 + * with an auto-reset that begins as soon as we release the lock. */ 248 252 set_bit(US_FLIDX_TIMED_OUT, &us->flags); 249 253 if (!test_bit(US_FLIDX_RESETTING, &us->flags)) { 250 254 set_bit(US_FLIDX_ABORTING, &us->flags); 251 255 usb_stor_stop_transport(us); 252 256 } 257 + scsi_unlock(us_to_host(us)); 253 258 254 259 /* Wait for the aborted command to finish */ 255 260 wait_for_completion(&us->notify); 256 - 257 - /* Reacquire the lock and allow USB transfers to resume */ 258 - clear_bit(US_FLIDX_ABORTING, &us->flags); 259 - clear_bit(US_FLIDX_TIMED_OUT, &us->flags); 260 261 return SUCCESS; 261 262 } 262 263 263 264 /* This invokes the transport reset mechanism to reset the state of the 264 265 * device */ 265 - /* This is always called with scsi_lock(host) held */ 266 266 static int device_reset(struct scsi_cmnd *srb) 267 267 { 268 268 struct us_data *us = host_to_us(srb->device->host); ··· 279 279 } 280 280 281 281 /* Simulate a SCSI bus reset by resetting the device's USB port. */ 282 - /* This is always called with scsi_lock(host) held */ 283 282 static int bus_reset(struct scsi_cmnd *srb) 284 283 { 285 284 struct us_data *us = host_to_us(srb->device->host); ··· 290 291 result = usb_stor_port_reset(us); 291 292 up(&(us->dev_semaphore)); 292 293 293 - /* lock the host for the return */ 294 294 return result < 0 ? FAILED : SUCCESS; 295 295 } 296 296
+35
drivers/usb/storage/unusual_devs.h
··· 86 86 US_SC_DEVICE, US_PR_DEVICE, NULL, 87 87 US_FL_IGNORE_RESIDUE ), 88 88 89 + /* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net> 90 + * and Olaf Hering <olh@suse.de> (different bcd's, same vendor/product) 91 + * for USB floppies that need the SINGLE_LUN enforcement. 92 + */ 93 + UNUSUAL_DEV( 0x0409, 0x0040, 0x0000, 0x9999, 94 + "NEC", 95 + "NEC USB UF000x", 96 + US_SC_DEVICE, US_PR_DEVICE, NULL, 97 + US_FL_SINGLE_LUN ), 98 + 89 99 /* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au> 90 100 * Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message 91 101 * always fails and confuses drive. ··· 106 96 US_SC_DEVICE, US_PR_DEVICE, NULL, 107 97 US_FL_FIX_INQUIRY ), 108 98 99 + /* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */ 100 + UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, 101 + "SMSC", 102 + "FDC GOLD-2.30", 103 + US_SC_DEVICE, US_PR_DEVICE, NULL, 104 + US_FL_SINGLE_LUN ), 105 + 109 106 #ifdef CONFIG_USB_STORAGE_DPCM 110 107 UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, 111 108 "Microtech", 112 109 "CameraMate (DPCM_USB)", 113 110 US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), 114 111 #endif 112 + 113 + /* 114 + * Pete Zaitcev <zaitcev@yahoo.com>, from Patrick C. F. Ernzer, bz#162559. 115 + * The key does not actually break, but it returns zero sense which 116 + * makes our SCSI stack to print confusing messages. 117 + */ 118 + UNUSUAL_DEV( 0x0457, 0x0150, 0x0100, 0x0100, 119 + "USBest Technology", /* sold by Transcend */ 120 + "USB Mass Storage Device", 121 + US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), 122 + 123 + /* Patch submitted by Daniel Drake <dsd@gentoo.org> 124 + * Device reports nonsense bInterfaceProtocol 6 when connected over USB2 */ 125 + UNUSUAL_DEV( 0x0451, 0x5416, 0x0100, 0x0100, 126 + "Neuros Audio", 127 + "USB 2.0 HD 2.5", 128 + US_SC_DEVICE, US_PR_BULK, NULL, 129 + US_FL_NEED_OVERRIDE ), 115 130 116 131 /* Patch submitted by Philipp Friedrich <philipp@void.at> */ 117 132 UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100,
+8 -3
drivers/usb/storage/usb.c
··· 392 392 /* If an abort request was received we need to signal that 393 393 * the abort has finished. The proper test for this is 394 394 * the TIMED_OUT flag, not srb->result == DID_ABORT, because 395 - * a timeout/abort request might be received after all the 396 - * USB processing was complete. */ 397 - if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) 395 + * the timeout might have occurred after the command had 396 + * already completed with a different result code. */ 397 + if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { 398 398 complete(&(us->notify)); 399 + 400 + /* Allow USB transfers to resume */ 401 + clear_bit(US_FLIDX_ABORTING, &us->flags); 402 + clear_bit(US_FLIDX_TIMED_OUT, &us->flags); 403 + } 399 404 400 405 /* finished working on this command */ 401 406 us->srb = NULL;
+1 -1
drivers/video/console/Kconfig
··· 137 137 138 138 config FONT_8x16 139 139 bool "VGA 8x16 font" if FONTS 140 - depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y 140 + depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y || USB_SISUSBVGA_CON 141 141 default y if !SPARC32 && !SPARC64 && !FONTS 142 142 help 143 143 This is the "high resolution" font for the VGA frame buffer (the one
+4
drivers/video/console/Makefile
··· 33 33 34 34 obj-$(CONFIG_FB_STI) += sticore.o font.o 35 35 36 + ifeq ($(CONFIG_USB_SISUSBVGA_CON),y) 37 + obj-$(CONFIG_USB_SISUSBVGA) += font.o 38 + endif 39 + 36 40 # Targets that kbuild needs to know about 37 41 targets := promcon_tbl.c 38 42
+1 -1
include/linux/usbdevice_fs.h
··· 32 32 #define _LINUX_USBDEVICE_FS_H 33 33 34 34 #include <linux/types.h> 35 - #include <linux/compat.h> 36 35 37 36 /* --------------------------------------------------------------------- */ 38 37 ··· 124 125 }; 125 126 126 127 #ifdef CONFIG_COMPAT 128 + #include <linux/compat.h> 127 129 struct usbdevfs_urb32 { 128 130 unsigned char type; 129 131 unsigned char endpoint;