···11+Apple Touchpad Driver (appletouch)22+----------------------------------33+ Copyright (C) 2005 Stelian Pop <stelian@popies.net>44+55+appletouch is a Linux kernel driver for the USB touchpad found on post66+February 2005 Apple Alu Powerbooks.77+88+This driver is derived from Johannes Berg's appletrackpad driver[1], but it has99+been improved in some areas:1010+ * appletouch is a full kernel driver, no userspace program is necessary1111+ * appletouch can be interfaced with the synaptics X11 driver, in order1212+ to have touchpad acceleration, scrolling, etc.1313+1414+Credits go to Johannes Berg for reverse-engineering the touchpad protocol,1515+Frank Arnold for further improvements, and Alex Harper for some additional1616+information about the inner workings of the touchpad sensors.1717+1818+Usage:1919+------2020+2121+In order to use the touchpad in the basic mode, compile the driver and load2222+the module. A new input device will be detected and you will be able to read2323+the mouse data from /dev/input/mice (using gpm, or X11).2424+2525+In X11, you can configure the touchpad to use the synaptics X11 driver, which2626+will give additional functionalities, like acceleration, scrolling, 2 finger2727+tap for middle button mouse emulation, 3 finger tap for right button mouse2828+emulation, etc. In order to do this, make sure you're using a recent version of2929+the synaptics driver (tested with 0.14.2, available from [2]), and configure a3030+new input device in your X11 configuration file (take a look below for an3131+example). For additional configuration, see the synaptics driver documentation.3232+3333+ Section "InputDevice"3434+ Identifier "Synaptics Touchpad"3535+ Driver "synaptics"3636+ Option "SendCoreEvents" "true"3737+ Option "Device" "/dev/input/mice"3838+ Option "Protocol" "auto-dev"3939+ Option "LeftEdge" "0"4040+ Option "RightEdge" "850"4141+ Option "TopEdge" "0"4242+ Option "BottomEdge" "645"4343+ Option "MinSpeed" "0.4"4444+ Option "MaxSpeed" "1"4545+ Option "AccelFactor" "0.02"4646+ Option "FingerLow" "0"4747+ Option "FingerHigh" "30"4848+ Option "MaxTapMove" "20"4949+ Option "MaxTapTime" "100"5050+ Option "HorizScrollDelta" "0"5151+ Option "VertScrollDelta" "30"5252+ Option "SHMConfig" "on"5353+ EndSection5454+5555+ Section "ServerLayout"5656+ ...5757+ InputDevice "Mouse"5858+ InputDevice "Synaptics Touchpad"5959+ ...6060+ EndSection6161+6262+Fuzz problems:6363+--------------6464+6565+The touchpad sensors are very sensitive to heat, and will generate a lot of6666+noise when the temperature changes. This is especially true when you power-on6767+the laptop for the first time.6868+6969+The appletouch driver tries to handle this noise and auto adapt itself, but it7070+is not perfect. If finger movements are not recognized anymore, try reloading7171+the driver.7272+7373+You can activate debugging using the 'debug' module parameter. A value of 07474+deactivates any debugging, 1 activates tracing of invalid samples, 2 activates7575+full tracing (each sample is being traced):7676+ modprobe appletouch debug=17777+ or7878+ echo "1" > /sys/module/appletouch/parameters/debug7979+8080+Links:8181+------8282+8383+[1]: http://johannes.sipsolutions.net/PowerBook/touchpad/8484+[2]: http://web.telia.com/~u89404340/touchpad/index.html
+8-5
Documentation/usb/proc_usb_info.txt
···20202121 to /etc/fstab. This will mount usbfs at each reboot.2222 You can then issue `cat /proc/bus/usb/devices` to extract2323- USB device information, and user mode drivers can use usbfs 2323+ USB device information, and user mode drivers can use usbfs2424 to interact with USB devices.25252626 There are a number of mount options supported by usbfs.···3232 still see references to the older "usbdevfs" name.33333434For more information on mounting the usbfs file system, see the3535-"USB Device Filesystem" section of the USB Guide. The latest copy 3535+"USB Device Filesystem" section of the USB Guide. The latest copy3636of the USB Guide can be found at http://www.linux-usb.org/37373838···133133 are the only transfers that reserve bandwidth. Control and bulk134134 transfers use all other bandwidth, including reserved bandwidth that135135 is not used for transfers (such as for short packets).136136-136136+137137 The percentage is how much of the "reserved" bandwidth is scheduled by138138 those transfers. For a low or full speed bus (loosely, "USB 1.1"),139139 90% of the bus bandwidth is reserved. For a high speed bus (loosely,···197197| | |__NumberOfInterfaces198198| |__ "*" indicates the active configuration (others are " ")199199|__Config info tag200200-200200+201201 USB devices may have multiple configurations, each of which act202202 rather differently. For example, a bus-powered configuration203203 might be much less capable than one that is self-powered. Only···228228 For example, default settings may not use more than a small229229 amount of periodic bandwidth. To use significant fractions230230 of bus bandwidth, drivers must select a non-default altsetting.231231-231231+232232 Only one setting for an interface may be active at a time, and233233 only one driver may bind to an interface at a time. Most devices234234 have only one alternate setting per interface.···297297C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA298298I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub299299E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms300300+300301T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4301302D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1302303P: Vendor=0451 ProdID=1446 Rev= 1.00303304C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA304305I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub305306E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms307307+306308T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0307309D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1308310P: Vendor=04b4 ProdID=0001 Rev= 0.00309311C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA310312I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=mouse311313E: Ad=81(I) Atr=03(Int.) MxPS= 3 Ivl= 10ms314314+312315T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0313316D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1314317P: Vendor=0565 ProdID=0001 Rev= 1.08
+8-4
drivers/usb/class/audio.c
···631631 i = u->flags;632632 spin_unlock_irqrestore(&as->lock, flags);633633 while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) {634634- set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);635635- schedule_timeout(1);634634+ if (notkilled)635635+ schedule_timeout_interruptible(1);636636+ else637637+ schedule_timeout_uninterruptible(1);636638 spin_lock_irqsave(&as->lock, flags);637639 i = u->flags;638640 spin_unlock_irqrestore(&as->lock, flags);···11041102 i = u->flags;11051103 spin_unlock_irqrestore(&as->lock, flags);11061104 while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) {11071107- set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);11081108- schedule_timeout(1);11051105+ if (notkilled)11061106+ schedule_timeout_interruptible(1);11071107+ else11081108+ schedule_timeout_uninterruptible(1);11091109 spin_lock_irqsave(&as->lock, flags);11101110 i = u->flags;11111111 spin_unlock_irqrestore(&as->lock, flags);
+1-2
drivers/usb/core/hcd.c
···16061606 return IRQ_NONE;1607160716081608 hcd->saw_irq = 1;16091609- if (hcd->state != start && hcd->state == HC_STATE_HALT)16091609+ if (hcd->state == HC_STATE_HALT)16101610 usb_hc_died (hcd);16111611 return IRQ_HANDLED;16121612}···16301630 spin_lock_irqsave (&hcd_root_hub_lock, flags);16311631 if (hcd->rh_registered) {16321632 hcd->poll_rh = 0;16331633- del_timer(&hcd->rh_timer);1634163316351634 /* make khubd clean up old urbs and devices */16361635 usb_set_device_state (hcd->self.root_hub,
+6-5
drivers/usb/core/hub.c
···435435static void hub_power_on(struct usb_hub *hub)436436{437437 int port1;438438+ unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2;438439439440 /* if hub supports power switching, enable power on each port */440441 if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) < 2) {···445444 USB_PORT_FEAT_POWER);446445 }447446448448- /* Wait for power to be enabled */449449- msleep(hub->descriptor->bPwrOn2PwrGood * 2);447447+ /* Wait at least 100 msec for power to become stable */448448+ msleep(max(pgood_delay, (unsigned) 100));450449}451450452451static void hub_quiesce(struct usb_hub *hub)···14611460 port1, status);14621461 else {14631462 status = hub_port_wait_reset(hub, port1, udev, delay);14641464- if (status)14631463+ if (status && status != -ENOTCONN)14651464 dev_dbg(hub->intfdev,14661465 "port_wait_reset: err = %d\n",14671466 status);···14701469 /* return on disconnect or reset */14711470 switch (status) {14721471 case 0:14731473- /* TRSTRCY = 10 ms */14741474- msleep(10);14721472+ /* TRSTRCY = 10 ms; plus some extra */14731473+ msleep(10 + 40);14751474 /* FALL THROUGH */14761475 case -ENOTCONN:14771476 case -ENODEV:
···400400 return -EIO;401401 }402402 break;403403+ case PCI_VENDOR_ID_NVIDIA:404404+ /* NVidia reports that certain chips don't handle405405+ * QH, ITD, or SITD addresses above 2GB. (But TD,406406+ * data buffer, and periodic schedule are normal.)407407+ */408408+ switch (pdev->device) {409409+ case 0x003c: /* MCP04 */410410+ case 0x005b: /* CK804 */411411+ case 0x00d8: /* CK8 */412412+ case 0x00e8: /* CK8S */413413+ if (pci_set_consistent_dma_mask(pdev,414414+ DMA_31BIT_MASK) < 0)415415+ ehci_warn (ehci, "can't enable NVidia "416416+ "workaround for >2GB RAM\n");417417+ break;418418+ }419419+ break;403420 }404421405422 /* optional debug port, normally in the first BAR */···776759 if (time_before (jiffies, ehci->next_statechange))777760 msleep (100);778761779779- /* If any port is suspended, we know we can/must resume the HC. */762762+ /* If any port is suspended (or owned by the companion),763763+ * we know we can/must resume the HC (and mustn't reset it).764764+ */780765 for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) {781766 u32 status;782767 port--;783768 status = readl (&ehci->regs->port_status [port]);784784- if (status & PORT_SUSPEND) {769769+ if (!(status & PORT_POWER))770770+ continue;771771+ if (status & (PORT_SUSPEND | PORT_OWNER)) {785772 down (&hcd->self.root_hub->serialize);786773 retval = ehci_hub_resume (hcd);787774 up (&hcd->self.root_hub->serialize);···11471126 case QH_STATE_UNLINK: /* wait for hw to finish? */11481127idle_timeout:11491128 spin_unlock_irqrestore (&ehci->lock, flags);11501150- set_current_state (TASK_UNINTERRUPTIBLE);11511151- schedule_timeout (1);11291129+ schedule_timeout_uninterruptible(1);11521130 goto rescan;11531131 case QH_STATE_IDLE: /* fully unlinked */11541132 if (list_empty (&qh->qtd_list)) {
···382382 goto sanitize;383383 }384384 spin_unlock_irqrestore (&ohci->lock, flags);385385- set_current_state (TASK_UNINTERRUPTIBLE);386386- schedule_timeout (1);385385+ schedule_timeout_uninterruptible(1);387386 goto rescan;388387 case ED_IDLE: /* fully unlinked */389388 if (list_empty (&ed->td_list)) {···484485 // flush the writes485486 (void) ohci_readl (ohci, &ohci->regs->control);486487488488+ /* Read the number of ports unless overridden */489489+ if (ohci->num_ports == 0)490490+ ohci->num_ports = roothub_a(ohci) & RH_A_NDP;491491+487492 if (ohci->hcca)488493 return 0;489494···564561 msleep(temp);565562 temp = roothub_a (ohci);566563 if (!(temp & RH_A_NPS)) {567567- unsigned ports = temp & RH_A_NDP; 568568-569564 /* power down each port */570570- for (temp = 0; temp < ports; temp++)565565+ for (temp = 0; temp < ohci->num_ports; temp++)571566 ohci_writel (ohci, RH_PS_LSDA,572567 &ohci->regs->roothub.portstatus [temp]);573568 }···721720722721 if (ints & OHCI_INTR_RD) {723722 ohci_vdbg (ohci, "resume detect\n");723723+ ohci_writel (ohci, OHCI_INTR_RD, ®s->intrstatus);724724 if (hcd->state != HC_STATE_QUIESCING)725725 schedule_work(&ohci->rh_resume);726726 }···863861 * and that if we try to turn them back on the root hub864862 * will respond to CSC processing.865863 */866866- i = roothub_a (ohci) & RH_A_NDP;864864+ i = ohci->num_ports;867865 while (i--)868866 ohci_writel (ohci, RH_PS_PSS,869867 &ohci->regs->roothub.portstatus [temp]);
+11-11
drivers/usb/host/ohci-hub.c
···184184 if (status != -EINPROGRESS)185185 return status;186186187187- temp = roothub_a (ohci) & RH_A_NDP;187187+ temp = ohci->num_ports;188188 enables = 0;189189 while (temp--) {190190 u32 stat = ohci_readl (ohci,···304304ohci_hub_status_data (struct usb_hcd *hcd, char *buf)305305{306306 struct ohci_hcd *ohci = hcd_to_ohci (hcd);307307- int ports, i, changed = 0, length = 1;307307+ int i, changed = 0, length = 1;308308 int can_suspend = hcd->can_wakeup;309309 unsigned long flags;310310···319319 goto done;320320 }321321322322- ports = roothub_a (ohci) & RH_A_NDP; 323323- if (ports > MAX_ROOT_PORTS) {324324- ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ports,322322+ /* undocumented erratum seen on at least rev D */323323+ if ((ohci->flags & OHCI_QUIRK_AMD756)324324+ && (roothub_a (ohci) & RH_A_NDP) > MAX_ROOT_PORTS) {325325+ ohci_warn (ohci, "bogus NDP, rereads as NDP=%d\n",325326 ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP);326327 /* retry later; "should not happen" */327328 goto done;···333332 buf [0] = changed = 1;334333 else335334 buf [0] = 0;336336- if (ports > 7) {335335+ if (ohci->num_ports > 7) {337336 buf [1] = 0;338337 length++;339338 }340339341340 /* look at each port */342342- for (i = 0; i < ports; i++) {341341+ for (i = 0; i < ohci->num_ports; i++) {343342 u32 status = roothub_portstatus (ohci, i);344343345344 if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC···396395 struct usb_hub_descriptor *desc397396) {398397 u32 rh = roothub_a (ohci);399399- int ports = rh & RH_A_NDP; 400398 u16 temp;401399402400 desc->bDescriptorType = 0x29;403401 desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24;404402 desc->bHubContrCurrent = 0;405403406406- desc->bNbrPorts = ports;407407- temp = 1 + (ports / 8);404404+ desc->bNbrPorts = ohci->num_ports;405405+ temp = 1 + (ohci->num_ports / 8);408406 desc->bDescLength = 7 + 2 * temp;409407410408 temp = 0;···421421 rh = roothub_b (ohci);422422 memset(desc->bitmap, 0xff, sizeof(desc->bitmap));423423 desc->bitmap [0] = rh & RH_B_DR;424424- if (ports > 7) {424424+ if (ohci->num_ports > 7) {425425 desc->bitmap [1] = (rh & RH_B_DR) >> 8;426426 desc->bitmap [2] = 0xff;427427 } else
+10-38
drivers/usb/host/ohci-pxa27x.c
···7575 return 0;7676}77777878-/*7979- If you select PMM_PERPORT_MODE, you should set the port power8080- */8181-static int pxa27x_ohci_set_port_power( int port )8282-{8383- if ( (pxa27x_ohci_pmm_state==PMM_PERPORT_MODE)8484- && (port>0) && (port<PXA_UHC_MAX_PORTNUM) ) {8585- UHCRHPS(port) |= 0x100;8686- return 0;8787- }8888- return -1;8989-}9090-9191-/*9292- If you select PMM_PERPORT_MODE, you should set the port power9393- */9494-static int pxa27x_ohci_clear_port_power( int port )9595-{9696- if ( (pxa27x_ohci_pmm_state==PMM_PERPORT_MODE) 9797- && (port>0) && (port<PXA_UHC_MAX_PORTNUM) ) {9898- UHCRHPS(port) |= 0x200;9999- return 0;100100- }101101-102102- return -1;103103-}104104-10578extern int usb_disabled(void);1067910780/*-------------------------------------------------------------------------*/···103130 Polarity Low to active low. Supply power to USB ports. */104131 UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &105132 ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);133133+134134+ pxa27x_ohci_pmm_state = PMM_PERPORT_MODE;106135 }107136108137 UHCHR &= ~UHCHR_SSE;109138110139 UHCHIE = (UHCHIE_UPRIE | UHCHIE_RWIE);140140+141141+ /* Clear any OTG Pin Hold */142142+ if (PSSR & PSSR_OTGPH)143143+ PSSR |= PSSR_OTGPH;111144}112145113146static void pxa27x_stop_hc(struct platform_device *dev)···177198 pxa27x_start_hc(dev);178199179200 /* Select Power Management Mode */180180- pxa27x_ohci_select_pmm( PMM_PERPORT_MODE );181181-182182- /* If choosing PMM_PERPORT_MODE, we should set the port power before we use it. */183183- if (pxa27x_ohci_set_port_power(1) < 0)184184- printk(KERN_ERR "Setting port 1 power failed.\n");185185-186186- if (pxa27x_ohci_clear_port_power(2) < 0)187187- printk(KERN_ERR "Setting port 2 power failed.\n");188188-189189- if (pxa27x_ohci_clear_port_power(3) < 0)190190- printk(KERN_ERR "Setting port 3 power failed.\n");201201+ pxa27x_ohci_select_pmm(pxa27x_ohci_pmm_state);191202192203 ohci_hcd_init(hcd_to_ohci(hcd));193204···226257 int ret;227258228259 ohci_dbg (ohci, "ohci_pxa27x_start, ohci:%p", ohci);260260+261261+ /* The value of NDP in roothub_a is incorrect on this hardware */262262+ ohci->num_ports = 3;229263230264 if ((ret = ohci_init(ohci)) < 0)231265 return ret;
+1
drivers/usb/host/ohci.h
···383383 /*384384 * driver state385385 */386386+ int num_ports;386387 int load [NUM_INTS];387388 u32 hc_control; /* copy of hc control reg */388389 unsigned long next_statechange; /* suspend/resume */
+22-40
drivers/usb/host/uhci-hcd.c
···9797/* to make sure it doesn't hog all of the bandwidth */9898#define DEPTH_INTERVAL 59999100100-static inline void restart_timer(struct uhci_hcd *uhci)101101-{102102- mod_timer(&uhci->stall_timer, jiffies + msecs_to_jiffies(100));103103-}104104-105105-#include "uhci-hub.c"106100#include "uhci-debug.c"107101#include "uhci-q.c"102102+#include "uhci-hub.c"108103109104/*110105 * Make sure the controller is completely inactive, unable to···155160{156161 reset_hc(uhci);157162 uhci->hc_inaccessible = 1;158158- del_timer(&uhci->stall_timer);159163}160164161165/*···281287 /* Enable resume-detect interrupts if they work.282288 * Then enter Global Suspend mode, still configured.283289 */284284- int_enable = (resume_detect_interrupts_are_broken(uhci) ?285285- 0 : USBINTR_RESUME);290290+ uhci->working_RD = 1;291291+ int_enable = USBINTR_RESUME;292292+ if (resume_detect_interrupts_are_broken(uhci)) {293293+ uhci->working_RD = int_enable = 0;294294+ }286295 outw(int_enable, uhci->io_addr + USBINTR);287296 outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD);288297 mb();···312315313316 uhci->rh_state = new_state;314317 uhci->is_stopped = UHCI_IS_STOPPED;315315- del_timer(&uhci->stall_timer);316318 uhci_to_hcd(uhci)->poll_rh = !int_enable;317319318320 uhci_scan_schedule(uhci, NULL);···331335 mb();332336 uhci->rh_state = UHCI_RH_RUNNING;333337 uhci_to_hcd(uhci)->poll_rh = 1;334334- restart_timer(uhci);335338}336339337340static void wakeup_rh(struct uhci_hcd *uhci)···369374 mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);370375}371376372372-static void stall_callback(unsigned long _uhci)373373-{374374- struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci;375375- unsigned long flags;376376-377377- spin_lock_irqsave(&uhci->lock, flags);378378- uhci_scan_schedule(uhci, NULL);379379- check_fsbr(uhci);380380-381381- if (!uhci->is_stopped)382382- restart_timer(uhci);383383- spin_unlock_irqrestore(&uhci->lock, flags);384384-}385385-386377static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)387378{388379 struct uhci_hcd *uhci = hcd_to_uhci(hcd);···399418 "host controller halted, "400419 "very bad!\n");401420 hc_died(uhci);402402- spin_unlock_irqrestore(&uhci->lock, flags);403403- return IRQ_HANDLED;421421+422422+ /* Force a callback in case there are423423+ * pending unlinks */424424+ mod_timer(&hcd->rh_timer, jiffies);404425 }405426 spin_unlock_irqrestore(&uhci->lock, flags);406427 }···410427411428 if (status & USBSTS_RD)412429 usb_hcd_poll_rh_status(hcd);413413-414414- spin_lock_irqsave(&uhci->lock, flags);415415- uhci_scan_schedule(uhci, regs);416416- spin_unlock_irqrestore(&uhci->lock, flags);430430+ else {431431+ spin_lock_irqsave(&uhci->lock, flags);432432+ uhci_scan_schedule(uhci, regs);433433+ spin_unlock_irqrestore(&uhci->lock, flags);434434+ }417435418436 return IRQ_HANDLED;419437}···579595580596 init_waitqueue_head(&uhci->waitqh);581597582582- init_timer(&uhci->stall_timer);583583- uhci->stall_timer.function = stall_callback;584584- uhci->stall_timer.data = (unsigned long) uhci;585585-586598 uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl),587599 &dma_handle, 0);588600 if (!uhci->fl) {···725745 struct uhci_hcd *uhci = hcd_to_uhci(hcd);726746727747 spin_lock_irq(&uhci->lock);728728- reset_hc(uhci);748748+ if (!uhci->hc_inaccessible)749749+ reset_hc(uhci);729750 uhci_scan_schedule(uhci, NULL);730751 spin_unlock_irq(&uhci->lock);731752732732- del_timer_sync(&uhci->stall_timer);733753 release_uhci(uhci);734754}735755···791811 */792812 pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);793813 uhci->hc_inaccessible = 1;814814+ hcd->poll_rh = 0;794815795816 /* FIXME: Enable non-PME# remote wakeup? */796817797818done:798819 spin_unlock_irq(&uhci->lock);799799- if (rc == 0)800800- del_timer_sync(&hcd->rh_timer);801820 return rc;802821}803822···829850830851 spin_unlock_irq(&uhci->lock);831852832832- if (hcd->poll_rh)853853+ if (!uhci->working_RD) {854854+ /* Suspended root hub needs to be polled */855855+ hcd->poll_rh = 1;833856 usb_hcd_poll_rh_status(hcd);857857+ }834858 return 0;835859}836860#endif
+3-8
drivers/usb/host/uhci-hcd.h
···345345346346/*347347 * This describes the full uhci information.348348- *349349- * Note how the "proper" USB information is just350350- * a subset of what the full implementation needs.351348 */352349struct uhci_hcd {353350···356359357360 struct dma_pool *qh_pool;358361 struct dma_pool *td_pool;359359-360360- struct usb_bus *bus;361362362363 struct uhci_td *term_td; /* Terminating TD, see UHCI bug */363364 struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */···375380 unsigned int scan_in_progress:1; /* Schedule scan is running */376381 unsigned int need_rescan:1; /* Redo the schedule scan */377382 unsigned int hc_inaccessible:1; /* HC is suspended or dead */383383+ unsigned int working_RD:1; /* Suspended root hub doesn't384384+ need to be polled */378385379386 /* Support for port suspend/resume/reset */380387 unsigned long port_c_suspend; /* Bit-arrays of ports */···402405 /* List of URB's awaiting completion callback */403406 struct list_head complete_list; /* P: uhci->lock */404407405405- int rh_numports;406406-407407- struct timer_list stall_timer;408408+ int rh_numports; /* Number of root-hub ports */408409409410 wait_queue_head_t waitqh; /* endpoint_disable waiters */410411};
+6-5
drivers/usb/host/uhci-hub.c
···145145{146146 struct uhci_hcd *uhci = hcd_to_uhci(hcd);147147 unsigned long flags;148148- int status;148148+ int status = 0;149149150150 spin_lock_irqsave(&uhci->lock, flags);151151- if (uhci->hc_inaccessible) {152152- status = 0;153153- goto done;154154- }155151152152+ uhci_scan_schedule(uhci, NULL);153153+ if (uhci->hc_inaccessible)154154+ goto done;155155+ check_fsbr(uhci);156156 uhci_check_ports(uhci);157157+157158 status = get_hub_status_data(uhci, buf);158159159160 switch (uhci->rh_state) {
···286286287287 To compile this driver as a module, choose M here: the module will288288 be called keyspan_remote.289289+290290+config USB_APPLETOUCH291291+ tristate "Apple USB Touchpad support"292292+ depends on USB && INPUT293293+ ---help---294294+ Say Y here if you want to use an Apple USB Touchpad.295295+296296+ These are the touchpads that can be found on post-February 2005297297+ Apple Powerbooks (prior models have a Synaptics touchpad connected298298+ to the ADB bus).299299+300300+ This driver provides a basic mouse driver but can be interfaced301301+ with the synaptics X11 driver to provide acceleration and302302+ scrolling in X11.303303+304304+ For further information, see305305+ <file:Documentation/input/appletouch.txt>.306306+307307+ To compile this driver as a module, choose M here: the308308+ module will be called appletouch.
···11+/*22+ * Apple USB Touchpad (for post-February 2005 PowerBooks) driver33+ *44+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)55+ * Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net)66+ * Copyright (C) 2005 Stelian Pop (stelian@popies.net)77+ * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de)88+ * Copyright (C) 2005 Peter Osterlund (petero2@telia.com)99+ *1010+ * Thanks to Alex Harper <basilisk@foobox.net> for his inputs.1111+ *1212+ * This program is free software; you can redistribute it and/or modify1313+ * it under the terms of the GNU General Public License as published by1414+ * the Free Software Foundation; either version 2 of the License, or1515+ * (at your option) any later version.1616+ *1717+ * This program is distributed in the hope that it will be useful,1818+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1919+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the2020+ * GNU General Public License for more details.2121+ *2222+ * You should have received a copy of the GNU General Public License2323+ * along with this program; if not, write to the Free Software2424+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.2525+ *2626+ */2727+2828+#include <linux/config.h>2929+#include <linux/kernel.h>3030+#include <linux/errno.h>3131+#include <linux/init.h>3232+#include <linux/slab.h>3333+#include <linux/module.h>3434+#include <linux/usb.h>3535+#include <linux/input.h>3636+#include <linux/usb_input.h>3737+3838+/* Apple has powerbooks which have the keyboard with different Product IDs */3939+#define APPLE_VENDOR_ID 0x05AC4040+4141+#define ATP_DEVICE(prod) \4242+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \4343+ USB_DEVICE_ID_MATCH_INT_CLASS | \4444+ USB_DEVICE_ID_MATCH_INT_PROTOCOL, \4545+ .idVendor = APPLE_VENDOR_ID, \4646+ .idProduct = (prod), \4747+ .bInterfaceClass = 0x03, \4848+ .bInterfaceProtocol = 0x024949+5050+/* table of devices that work with this driver */5151+static struct usb_device_id atp_table [] = {5252+ { ATP_DEVICE(0x020E) },5353+ { ATP_DEVICE(0x020F) },5454+ { ATP_DEVICE(0x030A) },5555+ { ATP_DEVICE(0x030B) },5656+ { } /* Terminating entry */5757+};5858+MODULE_DEVICE_TABLE (usb, atp_table);5959+6060+/* size of a USB urb transfer */6161+#define ATP_DATASIZE 816262+6363+/*6464+ * number of sensors. Note that only 16 instead of 26 X (horizontal)6565+ * sensors exist on 12" and 15" PowerBooks. All models have 16 Y6666+ * (vertical) sensors.6767+ */6868+#define ATP_XSENSORS 266969+#define ATP_YSENSORS 167070+7171+/* amount of fuzz this touchpad generates */7272+#define ATP_FUZZ 167373+7474+/* maximum pressure this driver will report */7575+#define ATP_PRESSURE 3007676+/*7777+ * multiplication factor for the X and Y coordinates.7878+ * We try to keep the touchpad aspect ratio while still doing only simple7979+ * arithmetics.8080+ * The factors below give coordinates like:8181+ * 0 <= x < 960 on 12" and 15" Powerbooks8282+ * 0 <= x < 1600 on 17" Powerbooks8383+ * 0 <= y < 6468484+ */8585+#define ATP_XFACT 648686+#define ATP_YFACT 438787+8888+/*8989+ * Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is9090+ * ignored.9191+ */9292+#define ATP_THRESHOLD 59393+9494+/* Structure to hold all of our device specific stuff */9595+struct atp {9696+ struct usb_device * udev; /* usb device */9797+ struct urb * urb; /* usb request block */9898+ signed char * data; /* transferred data */9999+ int open; /* non-zero if opened */100100+ struct input_dev input; /* input dev */101101+ int valid; /* are the sensors valid ? */102102+ int x_old; /* last reported x/y, */103103+ int y_old; /* used for smoothing */104104+ /* current value of the sensors */105105+ signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS];106106+ /* last value of the sensors */107107+ signed char xy_old[ATP_XSENSORS + ATP_YSENSORS];108108+ /* accumulated sensors */109109+ int xy_acc[ATP_XSENSORS + ATP_YSENSORS];110110+};111111+112112+#define dbg_dump(msg, tab) \113113+ if (debug > 1) { \114114+ int i; \115115+ printk("appletouch: %s %lld", msg, (long long)jiffies); \116116+ for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) \117117+ printk(" %02x", tab[i]); \118118+ printk("\n"); \119119+ }120120+121121+#define dprintk(format, a...) \122122+ do { \123123+ if (debug) printk(format, ##a); \124124+ } while (0)125125+126126+MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold");127127+MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");128128+MODULE_LICENSE("GPL");129129+130130+static int debug = 1;131131+module_param(debug, int, 0644);132132+MODULE_PARM_DESC(debug, "Activate debugging output");133133+134134+static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,135135+ int *z, int *fingers)136136+{137137+ int i;138138+ /* values to calculate mean */139139+ int pcum = 0, psum = 0;140140+141141+ *fingers = 0;142142+143143+ for (i = 0; i < nb_sensors; i++) {144144+ if (xy_sensors[i] < ATP_THRESHOLD)145145+ continue;146146+ if ((i - 1 < 0) || (xy_sensors[i - 1] < ATP_THRESHOLD))147147+ (*fingers)++;148148+ pcum += xy_sensors[i] * i;149149+ psum += xy_sensors[i];150150+ }151151+152152+ if (psum > 0) {153153+ *z = psum;154154+ return pcum * fact / psum;155155+ }156156+157157+ return 0;158158+}159159+160160+static inline void atp_report_fingers(struct input_dev *input, int fingers)161161+{162162+ input_report_key(input, BTN_TOOL_FINGER, fingers == 1);163163+ input_report_key(input, BTN_TOOL_DOUBLETAP, fingers == 2);164164+ input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2);165165+}166166+167167+static void atp_complete(struct urb* urb, struct pt_regs* regs)168168+{169169+ int x, y, x_z, y_z, x_f, y_f;170170+ int retval, i;171171+ struct atp *dev = urb->context;172172+173173+ switch (urb->status) {174174+ case 0:175175+ /* success */176176+ break;177177+ case -ECONNRESET:178178+ case -ENOENT:179179+ case -ESHUTDOWN:180180+ /* This urb is terminated, clean up */181181+ dbg("%s - urb shutting down with status: %d",182182+ __FUNCTION__, urb->status);183183+ return;184184+ default:185185+ dbg("%s - nonzero urb status received: %d",186186+ __FUNCTION__, urb->status);187187+ goto exit;188188+ }189189+190190+ /* drop incomplete datasets */191191+ if (dev->urb->actual_length != ATP_DATASIZE) {192192+ dprintk("appletouch: incomplete data package.\n");193193+ goto exit;194194+ }195195+196196+ /* reorder the sensors values */197197+ for (i = 0; i < 8; i++) {198198+ /* X values */199199+ dev->xy_cur[i ] = dev->data[5 * i + 2];200200+ dev->xy_cur[i + 8] = dev->data[5 * i + 4];201201+ dev->xy_cur[i + 16] = dev->data[5 * i + 42];202202+ if (i < 2)203203+ dev->xy_cur[i + 24] = dev->data[5 * i + 44];204204+205205+ /* Y values */206206+ dev->xy_cur[i + 26] = dev->data[5 * i + 1];207207+ dev->xy_cur[i + 34] = dev->data[5 * i + 3];208208+ }209209+210210+ dbg_dump("sample", dev->xy_cur);211211+212212+ if (!dev->valid) {213213+ /* first sample */214214+ dev->valid = 1;215215+ dev->x_old = dev->y_old = -1;216216+ memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));217217+218218+ /* 17" Powerbooks have 10 extra X sensors */219219+ for (i = 16; i < ATP_XSENSORS; i++)220220+ if (dev->xy_cur[i]) {221221+ printk("appletouch: 17\" model detected.\n");222222+ input_set_abs_params(&dev->input, ABS_X, 0,223223+ (ATP_XSENSORS - 1) *224224+ ATP_XFACT - 1,225225+ ATP_FUZZ, 0);226226+ break;227227+ }228228+229229+ goto exit;230230+ }231231+232232+ for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) {233233+ /* accumulate the change */234234+ signed char change = dev->xy_old[i] - dev->xy_cur[i];235235+ dev->xy_acc[i] -= change;236236+237237+ /* prevent down drifting */238238+ if (dev->xy_acc[i] < 0)239239+ dev->xy_acc[i] = 0;240240+ }241241+242242+ memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));243243+244244+ dbg_dump("accumulator", dev->xy_acc);245245+246246+ x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS,247247+ ATP_XFACT, &x_z, &x_f);248248+ y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,249249+ ATP_YFACT, &y_z, &y_f);250250+251251+ if (x && y) {252252+ if (dev->x_old != -1) {253253+ x = (dev->x_old * 3 + x) >> 2;254254+ y = (dev->y_old * 3 + y) >> 2;255255+ dev->x_old = x;256256+ dev->y_old = y;257257+258258+ if (debug > 1)259259+ printk("appletouch: X: %3d Y: %3d "260260+ "Xz: %3d Yz: %3d\n",261261+ x, y, x_z, y_z);262262+263263+ input_report_key(&dev->input, BTN_TOUCH, 1);264264+ input_report_abs(&dev->input, ABS_X, x);265265+ input_report_abs(&dev->input, ABS_Y, y);266266+ input_report_abs(&dev->input, ABS_PRESSURE,267267+ min(ATP_PRESSURE, x_z + y_z));268268+ atp_report_fingers(&dev->input, max(x_f, y_f));269269+ }270270+ dev->x_old = x;271271+ dev->y_old = y;272272+ }273273+ else if (!x && !y) {274274+275275+ dev->x_old = dev->y_old = -1;276276+ input_report_key(&dev->input, BTN_TOUCH, 0);277277+ input_report_abs(&dev->input, ABS_PRESSURE, 0);278278+ atp_report_fingers(&dev->input, 0);279279+280280+ /* reset the accumulator on release */281281+ memset(dev->xy_acc, 0, sizeof(dev->xy_acc));282282+ }283283+284284+ input_report_key(&dev->input, BTN_LEFT, !!dev->data[80]);285285+286286+ input_sync(&dev->input);287287+288288+exit:289289+ retval = usb_submit_urb(dev->urb, GFP_ATOMIC);290290+ if (retval) {291291+ err("%s - usb_submit_urb failed with result %d",292292+ __FUNCTION__, retval);293293+ }294294+}295295+296296+static int atp_open(struct input_dev *input)297297+{298298+ struct atp *dev = input->private;299299+300300+ if (usb_submit_urb(dev->urb, GFP_ATOMIC))301301+ return -EIO;302302+303303+ dev->open = 1;304304+ return 0;305305+}306306+307307+static void atp_close(struct input_dev *input)308308+{309309+ struct atp *dev = input->private;310310+311311+ usb_kill_urb(dev->urb);312312+ dev->open = 0;313313+}314314+315315+static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id)316316+{317317+ struct atp *dev = NULL;318318+ struct usb_host_interface *iface_desc;319319+ struct usb_endpoint_descriptor *endpoint;320320+ int int_in_endpointAddr = 0;321321+ int i, retval = -ENOMEM;322322+323323+ /* allocate memory for our device state and initialize it */324324+ dev = kmalloc(sizeof(struct atp), GFP_KERNEL);325325+ if (dev == NULL) {326326+ err("Out of memory");327327+ goto err_kmalloc;328328+ }329329+ memset(dev, 0, sizeof(struct atp));330330+331331+ dev->udev = interface_to_usbdev(iface);332332+333333+ /* set up the endpoint information */334334+ /* use only the first interrupt-in endpoint */335335+ iface_desc = iface->cur_altsetting;336336+ for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {337337+ endpoint = &iface_desc->endpoint[i].desc;338338+ if (!int_in_endpointAddr &&339339+ (endpoint->bEndpointAddress & USB_DIR_IN) &&340340+ ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)341341+ == USB_ENDPOINT_XFER_INT)) {342342+ /* we found an interrupt in endpoint */343343+ int_in_endpointAddr = endpoint->bEndpointAddress;344344+ break;345345+ }346346+ }347347+ if (!int_in_endpointAddr) {348348+ retval = -EIO;349349+ err("Could not find int-in endpoint");350350+ goto err_endpoint;351351+ }352352+353353+ /* save our data pointer in this interface device */354354+ usb_set_intfdata(iface, dev);355355+356356+ dev->urb = usb_alloc_urb(0, GFP_KERNEL);357357+ if (!dev->urb) {358358+ retval = -ENOMEM;359359+ goto err_usballoc;360360+ }361361+ dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL,362362+ &dev->urb->transfer_dma);363363+ if (!dev->data) {364364+ retval = -ENOMEM;365365+ goto err_usbbufalloc;366366+ }367367+ usb_fill_int_urb(dev->urb, dev->udev,368368+ usb_rcvintpipe(dev->udev, int_in_endpointAddr),369369+ dev->data, ATP_DATASIZE, atp_complete, dev, 1);370370+371371+ init_input_dev(&dev->input);372372+ dev->input.name = "appletouch";373373+ dev->input.dev = &iface->dev;374374+ dev->input.private = dev;375375+ dev->input.open = atp_open;376376+ dev->input.close = atp_close;377377+378378+ usb_to_input_id(dev->udev, &dev->input.id);379379+380380+ set_bit(EV_ABS, dev->input.evbit);381381+382382+ /*383383+ * 12" and 15" Powerbooks only have 16 x sensors,384384+ * 17" models are detected later.385385+ */386386+ input_set_abs_params(&dev->input, ABS_X, 0,387387+ (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);388388+ input_set_abs_params(&dev->input, ABS_Y, 0,389389+ (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);390390+ input_set_abs_params(&dev->input, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);391391+392392+ set_bit(EV_KEY, dev->input.evbit);393393+ set_bit(BTN_TOUCH, dev->input.keybit);394394+ set_bit(BTN_TOOL_FINGER, dev->input.keybit);395395+ set_bit(BTN_TOOL_DOUBLETAP, dev->input.keybit);396396+ set_bit(BTN_TOOL_TRIPLETAP, dev->input.keybit);397397+ set_bit(BTN_LEFT, dev->input.keybit);398398+399399+ input_register_device(&dev->input);400400+401401+ printk(KERN_INFO "input: appletouch connected\n");402402+403403+ return 0;404404+405405+err_usbbufalloc:406406+ usb_free_urb(dev->urb);407407+err_usballoc:408408+ usb_set_intfdata(iface, NULL);409409+err_endpoint:410410+ kfree(dev);411411+err_kmalloc:412412+ return retval;413413+}414414+415415+static void atp_disconnect(struct usb_interface *iface)416416+{417417+ struct atp *dev = usb_get_intfdata(iface);418418+419419+ usb_set_intfdata(iface, NULL);420420+ if (dev) {421421+ usb_kill_urb(dev->urb);422422+ input_unregister_device(&dev->input);423423+ usb_free_urb(dev->urb);424424+ usb_buffer_free(dev->udev, ATP_DATASIZE,425425+ dev->data, dev->urb->transfer_dma);426426+ kfree(dev);427427+ }428428+ printk(KERN_INFO "input: appletouch disconnected\n");429429+}430430+431431+static int atp_suspend(struct usb_interface *iface, pm_message_t message)432432+{433433+ struct atp *dev = usb_get_intfdata(iface);434434+ usb_kill_urb(dev->urb);435435+ dev->valid = 0;436436+ return 0;437437+}438438+439439+static int atp_resume(struct usb_interface *iface)440440+{441441+ struct atp *dev = usb_get_intfdata(iface);442442+ if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC))443443+ return -EIO;444444+445445+ return 0;446446+}447447+448448+static struct usb_driver atp_driver = {449449+ .owner = THIS_MODULE,450450+ .name = "appletouch",451451+ .probe = atp_probe,452452+ .disconnect = atp_disconnect,453453+ .suspend = atp_suspend,454454+ .resume = atp_resume,455455+ .id_table = atp_table,456456+};457457+458458+static int __init atp_init(void)459459+{460460+ return usb_register(&atp_driver);461461+}462462+463463+static void __exit atp_exit(void)464464+{465465+ usb_deregister(&atp_driver);466466+}467467+468468+module_init(atp_init);469469+module_exit(atp_exit);
···44 depends on USB && USB_EHCI_HCD55 ---help---66 Say Y here if you intend to attach a USB2VGA dongle based on a77- Net2280 and a SiS315 chip. 88-99- Note that this device requires a USB 2.0 host controller. It will not 77+ Net2280 and a SiS315 chip.88+99+ Note that this device requires a USB 2.0 host controller. It will not1010 work with USB 1.x controllers.11111212- To compile this driver as a module, choose M here: the module will be1313- called sisusb. If unsure, say N.1212+ To compile this driver as a module, choose M here; the module will be1313+ called sisusbvga. If unsure, say N.1414+1515+config USB_SISUSBVGA_CON1616+ bool "Text console and mode switching support" if USB_SISUSBVGA1717+ depends on VT1818+ select FONT_8x161919+ ---help---2020+ Say Y here if you want a VGA text console via the USB dongle or2121+ want to support userland applications that utilize the driver's2222+ display mode switching capabilities.2323+2424+ Note that this console supports VGA/EGA text mode only.2525+2626+ By default, the console part of the driver will not kick in when2727+ the driver is initialized. If you want the driver to take over2828+ one or more of the consoles, you need to specify the number of2929+ the first and last consoles (starting at 1) as driver parameters.3030+3131+ For example, if the driver is compiled as a module:3232+3333+ modprobe sisusbvga first=1 last=53434+3535+ If you use hotplug, add this to your modutils config files with3636+ the "options" keyword, such as eg.3737+3838+ options sisusbvga first=1 last=53939+4040+ If the driver is compiled into the kernel image, the parameters4141+ must be given in the kernel command like, such as4242+4343+ sisusbvga.first=1 sisusbvga.last=54444+4545+1446
+3-1
drivers/usb/misc/sisusbvga/Makefile
···22# Makefile for the sisusb driver (if driver is inside kernel tree).33#4455-obj-$(CONFIG_USB_SISUSBVGA) += sisusb.o55+obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga.o66+77+sisusbvga-objs := sisusb.o sisusb_init.o sisusb_con.o68
+426-37
drivers/usb/misc/sisusbvga/sisusb.c
···11/*22 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles33 *44+ * Main part55+ *46 * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria57 *68 * If distributed as part of the Linux kernel, this code is licensed under the···5048#include <linux/kref.h>5149#include <linux/usb.h>5250#include <linux/smp_lock.h>5151+#include <linux/vmalloc.h>53525453#include "sisusb.h"5454+5555+#ifdef INCL_SISUSB_CON5656+#include <linux/font.h>5757+#endif55585659#define SISUSB_DONTSYNC57605861/* Forward declarations / clean-up routines */59626363+#ifdef INCL_SISUSB_CON6464+int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data);6565+int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data);6666+int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data);6767+int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data);6868+int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand, u8 myor);6969+int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor);7070+int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand);7171+7272+int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);7373+int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data);7474+int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data);7575+int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data);7676+int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,7777+ u32 dest, int length, size_t *bytes_written);7878+7979+int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);8080+8181+extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);8282+extern int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);8383+8484+extern void sisusb_init_concode(void);8585+extern int sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last);8686+extern void sisusb_console_exit(struct sisusb_usb_data *sisusb);8787+8888+extern void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location);8989+9090+extern int sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,9191+ u8 *arg, int cmapsz, int ch512, int dorecalc,9292+ struct vc_data *c, int fh, int uplock);9393+9494+static int sisusb_first_vc = 0;9595+static int sisusb_last_vc = 0;9696+module_param_named(first, sisusb_first_vc, int, 0);9797+module_param_named(last, sisusb_last_vc, int, 0);9898+MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)");9999+MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)");100100+#endif101101+60102static struct usb_driver sisusb_driver;611036262-static DECLARE_MUTEX(disconnect_sem);104104+DECLARE_MUTEX(disconnect_sem);6310564106static void65107sisusb_free_buffers(struct sisusb_usb_data *sisusb)···685639686640/* The following routines assume being used to transfer byte, word,687641 * long etc.688688- * This means that they assume "data" in machine endianness format.642642+ * This means that643643+ * - the write routines expect "data" in machine endianness format.644644+ * The data will be converted to leXX in sisusb_xxx_packet.645645+ * - the read routines can expect read data in machine-endianess.689646 */690647691648static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,···888839 if (get_user(swap16, (u16 __user *)userbuffer))889840 return -EFAULT;890841 } else891891- swap16 = (kernbuffer[0] << 8) | kernbuffer[1];842842+ swap16 = *((u16 *)kernbuffer);892843893844 ret = sisusb_write_memio_word(sisusb,894845 SISUSB_TYPE_MEM,···904855 if (userbuffer) {905856 if (copy_from_user(&buf, userbuffer, 3))906857 return -EFAULT;907907-858858+#ifdef __BIG_ENDIAN908859 swap32 = (buf[0] << 16) |909860 (buf[1] << 8) |910861 buf[2];862862+#else863863+ swap32 = (buf[2] << 16) |864864+ (buf[1] << 8) |865865+ buf[0];866866+#endif911867 } else868868+#ifdef __BIG_ENDIAN912869 swap32 = (kernbuffer[0] << 16) |913870 (kernbuffer[1] << 8) |914871 kernbuffer[2];872872+#else873873+ swap32 = (kernbuffer[2] << 16) |874874+ (kernbuffer[1] << 8) |875875+ kernbuffer[0];876876+#endif915877916878 ret = sisusb_write_memio_24bit(sisusb,917879 SISUSB_TYPE_MEM,···939879 if (get_user(swap32, (u32 __user *)userbuffer))940880 return -EFAULT;941881 } else942942- swap32 = (kernbuffer[0] << 24) |943943- (kernbuffer[1] << 16) |944944- (kernbuffer[2] << 8) |945945- kernbuffer[3];882882+ swap32 = *((u32 *)kernbuffer);946883947884 ret = sisusb_write_memio_long(sisusb,948885 SISUSB_TYPE_MEM,···1061100410621005 return ret ? -EIO : 0;10631006}10071007+10081008+/* Remember: Read data in packet is in machine-endianess! So for10091009+ * byte, word, 24bit, long no endian correction is necessary.10101010+ */1064101110651012static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,10661013 u32 addr, u8 *data)···12521191 (u16 __user *)userbuffer))12531192 return -EFAULT;12541193 } else {12551255- kernbuffer[0] = swap16 >> 8;12561256- kernbuffer[1] = swap16 & 0xff;11941194+ *((u16 *)kernbuffer) = swap16;12571195 }12581196 }12591197 return ret;···12621202 addr, &swap32);12631203 if (!ret) {12641204 (*bytes_read) += 3;12051205+#ifdef __BIG_ENDIAN12651206 buf[0] = (swap32 >> 16) & 0xff;12661207 buf[1] = (swap32 >> 8) & 0xff;12671208 buf[2] = swap32 & 0xff;12091209+#else12101210+ buf[2] = (swap32 >> 16) & 0xff;12111211+ buf[1] = (swap32 >> 8) & 0xff;12121212+ buf[0] = swap32 & 0xff;12131213+#endif12681214 if (userbuffer) {12691215 if (copy_to_user(userbuffer, &buf[0], 3))12701216 return -EFAULT;···1294122812951229 userbuffer += 4;12961230 } else {12971297- kernbuffer[0] = (swap32 >> 24) & 0xff;12981298- kernbuffer[1] = (swap32 >> 16) & 0xff;12991299- kernbuffer[2] = (swap32 >> 8) & 0xff;13001300- kernbuffer[3] = swap32 & 0xff;12311231+ *((u32 *)kernbuffer) = swap32;13011232 kernbuffer += 4;13021233 }13031234 addr += 4;···1352128913531290/* High level: Gfx (indexed) register access */1354129113551355-static int12921292+#ifdef INCL_SISUSB_CON12931293+int12941294+sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data)12951295+{12961296+ return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);12971297+}12981298+12991299+int13001300+sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data)13011301+{13021302+ return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);13031303+}13041304+#endif13051305+13061306+#ifndef INCL_SISUSB_CON13071307+static13081308+#endif13091309+int13561310sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)13571311{13581312 int ret;···13781298 return ret;13791299}1380130013811381-static int13011301+#ifndef INCL_SISUSB_CON13021302+static13031303+#endif13041304+int13821305sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)13831306{13841307 int ret;···13901307 return ret;13911308}1392130913931393-static int13101310+#ifndef INCL_SISUSB_CON13111311+static13121312+#endif13131313+int13941314sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,13951315 u8 myand, u8 myor)13961316{···14221336 return ret;14231337}1424133814251425-static int13391339+#ifndef INCL_SISUSB_CON13401340+static13411341+#endif13421342+int14261343sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor)14271344{14281345 return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));14291346}1430134714311431-static int13481348+#ifndef INCL_SISUSB_CON13491349+static13501350+#endif13511351+int14321352sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand)14331353{14341354 return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00));14351355}13561356+13571357+/* Write/read video ram */13581358+13591359+#ifdef INCL_SISUSB_CON13601360+int13611361+sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data)13621362+{13631363+ return(sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));13641364+}13651365+13661366+int13671367+sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)13681368+{13691369+ return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));13701370+}13711371+13721372+int13731373+sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data)13741374+{13751375+ return(sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));13761376+}13771377+13781378+int13791379+sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data)13801380+{13811381+ return(sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));13821382+}13831383+13841384+int13851385+sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,13861386+ u32 dest, int length, size_t *bytes_written)13871387+{13881388+ return(sisusb_write_mem_bulk(sisusb, dest, src, length, NULL, 0, bytes_written));13891389+}13901390+13911391+#ifdef SISUSBENDIANTEST13921392+int13931393+sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,13941394+ u32 src, int length, size_t *bytes_written)13951395+{13961396+ return(sisusb_read_mem_bulk(sisusb, src, dest, length, NULL, bytes_written));13971397+}13981398+#endif13991399+#endif14001400+14011401+#ifdef SISUSBENDIANTEST14021402+static void14031403+sisusb_testreadwrite(struct sisusb_usb_data *sisusb)14041404+{14051405+ static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };14061406+ char destbuffer[10];14071407+ size_t dummy;14081408+ int i,j;14091409+14101410+ sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy);14111411+14121412+ for(i = 1; i <= 7; i++) {14131413+ printk(KERN_DEBUG "sisusb: rwtest %d bytes\n", i);14141414+ sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy);14151415+ for(j = 0; j < i; j++) {14161416+ printk(KERN_DEBUG "sisusb: rwtest read[%d] = %x\n", j, destbuffer[j]);14171417+ }14181418+ }14191419+}14201420+#endif1436142114371422/* access pci config registers (reg numbers 0, 4, 8, etc) */14381423···24272270 return ret;24282271}2429227222732273+22742274+#ifdef INCL_SISUSB_CON22752275+22762276+/* Set up default text mode:22772277+ - Set text mode (0x03)22782278+ - Upload default font22792279+ - Upload user font (if available)22802280+*/22812281+22822282+int22832283+sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)22842284+{22852285+ int ret = 0, slot = sisusb->font_slot, i;22862286+ struct font_desc *myfont;22872287+ u8 *tempbuf;22882288+ u16 *tempbufb;22892289+ size_t written;22902290+ static char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";22912291+ static char bootlogo[] = "(o_ //\\ V_/_";22922292+22932293+ /* sisusb->lock is down */22942294+22952295+ if (!sisusb->SiS_Pr)22962296+ return 1;22972297+22982298+ sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;22992299+ sisusb->SiS_Pr->sisusb = (void *)sisusb;23002300+23012301+ /* Set mode 0x03 */23022302+ SiSUSBSetMode(sisusb->SiS_Pr, 0x03);23032303+23042304+ if (!(myfont = find_font("VGA8x16")))23052305+ return 1;23062306+23072307+ if (!(tempbuf = vmalloc(8192)))23082308+ return 1;23092309+23102310+ for (i = 0; i < 256; i++)23112311+ memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);23122312+23132313+ /* Upload default font */23142314+ ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, 0, 1, NULL, 16, 0);23152315+23162316+ vfree(tempbuf);23172317+23182318+ /* Upload user font (and reset current slot) */23192319+ if (sisusb->font_backup) {23202320+ ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,23212321+ 8192, sisusb->font_backup_512, 1, NULL,23222322+ sisusb->font_backup_height, 0);23232323+ if (slot != 2)23242324+ sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,23252325+ NULL, 16, 0);23262326+ }23272327+23282328+ if (init && !sisusb->scrbuf) {23292329+23302330+ if ((tempbuf = vmalloc(8192))) {23312331+23322332+ i = 4096;23332333+ tempbufb = (u16 *)tempbuf;23342334+ while (i--)23352335+ *(tempbufb++) = 0x0720;23362336+23372337+ i = 0;23382338+ tempbufb = (u16 *)tempbuf;23392339+ while (bootlogo[i]) {23402340+ *(tempbufb++) = 0x0700 | bootlogo[i++];23412341+ if (!(i % 4))23422342+ tempbufb += 76;23432343+ }23442344+23452345+ i = 0;23462346+ tempbufb = (u16 *)tempbuf + 6;23472347+ while (bootstring[i])23482348+ *(tempbufb++) = 0x0700 | bootstring[i++];23492349+23502350+ ret |= sisusb_copy_memory(sisusb, tempbuf,23512351+ sisusb->vrambase, 8192, &written);23522352+23532353+ vfree(tempbuf);23542354+23552355+ }23562356+23572357+ } else if (sisusb->scrbuf) {23582358+23592359+ ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,23602360+ sisusb->vrambase, sisusb->scrbuf_size, &written);23612361+23622362+ }23632363+23642364+ if (sisusb->sisusb_cursor_size_from >= 0 &&23652365+ sisusb->sisusb_cursor_size_to >= 0) {23662366+ sisusb_setidxreg(sisusb, SISCR, 0x0a,23672367+ sisusb->sisusb_cursor_size_from);23682368+ sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,23692369+ sisusb->sisusb_cursor_size_to);23702370+ } else {23712371+ sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);23722372+ sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);23732373+ sisusb->sisusb_cursor_size_to = -1;23742374+ }23752375+23762376+ slot = sisusb->sisusb_cursor_loc;23772377+ if(slot < 0) slot = 0;23782378+23792379+ sisusb->sisusb_cursor_loc = -1;23802380+ sisusb->bad_cursor_pos = 1;23812381+23822382+ sisusb_set_cursor(sisusb, slot);23832383+23842384+ sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));23852385+ sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));23862386+23872387+ sisusb->textmodedestroyed = 0;23882388+23892389+ /* sisusb->lock is down */23902390+23912391+ return ret;23922392+}23932393+23942394+#endif23952395+24302396/* fops */2431239724322398static int···26092329 }26102330 }2611233126122612- /* increment usage count for the device */23322332+ /* Increment usage count for our sisusb */26132333 kref_get(&sisusb->kref);2614233426152335 sisusb->isopen = 1;···2620234026212341 up(&disconnect_sem);2622234226232623- printk(KERN_DEBUG "sisusbvga[%d]: opened", sisusb->minor);26242624-26252343 return 0;26262344}2627234526282628-static void23462346+void26292347sisusb_delete(struct kref *kref)26302348{26312349 struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);···26372359 sisusb->sisusb_dev = NULL;26382360 sisusb_free_buffers(sisusb);26392361 sisusb_free_urbs(sisusb);23622362+#ifdef INCL_SISUSB_CON23632363+ kfree(sisusb->SiS_Pr);23642364+#endif26402365 kfree(sisusb);26412366}26422367···26752394 kref_put(&sisusb->kref, sisusb_delete);2676239526772396 up(&disconnect_sem);26782678-26792679- printk(KERN_DEBUG "sisusbvga[%d]: released", myminor);2680239726812398 return 0;26822399}···30122733 int retval, port, length;30132734 u32 address;3014273527362736+ /* All our commands require the device27372737+ * to be initialized.27382738+ */27392739+ if (!sisusb->devinit)27402740+ return -ENODEV;27412741+30152742 port = y->data3 -30162743 SISUSB_PCI_PSEUDO_IOPORTBASE +30172744 SISUSB_PCI_IOPORTBASE;···30592774 break;3060277530612776 case SUCMD_CLRSCR:27772777+ /* Gfx core must be initialized */27782778+ if (!sisusb->gfxinit)27792779+ return -ENODEV;27802780+30622781 length = (y->data0 << 16) | (y->data1 << 8) | y->data2;30632782 address = y->data3 -30642783 SISUSB_PCI_PSEUDO_MEMBASE +···30702781 retval = sisusb_clear_vram(sisusb, address, length);30712782 break;3072278327842784+ case SUCMD_HANDLETEXTMODE:27852785+ retval = 0;27862786+#ifdef INCL_SISUSB_CON27872787+ /* Gfx core must be initialized, SiS_Pr must exist */27882788+ if (!sisusb->gfxinit || !sisusb->SiS_Pr)27892789+ return -ENODEV;27902790+27912791+ switch (y->data0) {27922792+ case 0:27932793+ retval = sisusb_reset_text_mode(sisusb, 0);27942794+ break;27952795+ case 1:27962796+ sisusb->textmodedestroyed = 1;27972797+ break;27982798+ }27992799+#endif28002800+ break;28012801+28022802+#ifdef INCL_SISUSB_CON28032803+ case SUCMD_SETMODE:28042804+ /* Gfx core must be initialized, SiS_Pr must exist */28052805+ if (!sisusb->gfxinit || !sisusb->SiS_Pr)28062806+ return -ENODEV;28072807+28082808+ retval = 0;28092809+28102810+ sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;28112811+ sisusb->SiS_Pr->sisusb = (void *)sisusb;28122812+28132813+ if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))28142814+ retval = -EINVAL;28152815+28162816+ break;28172817+28182818+ case SUCMD_SETVESAMODE:28192819+ /* Gfx core must be initialized, SiS_Pr must exist */28202820+ if (!sisusb->gfxinit || !sisusb->SiS_Pr)28212821+ return -ENODEV;28222822+28232823+ retval = 0;28242824+28252825+ sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;28262826+ sisusb->SiS_Pr->sisusb = (void *)sisusb;28272827+28282828+ if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))28292829+ retval = -EINVAL;28302830+28312831+ break;28322832+#endif28332833+30732834 default:30742835 retval = -EINVAL;30752836 }3076283730773077- if(retval > 0)28382838+ if (retval > 0)30782839 retval = -EIO;3079284030802841 return retval;···31742835 x.sisusb_vramsize = sisusb->vramsize;31752836 x.sisusb_minor = sisusb->minor;31762837 x.sisusb_fbdevactive= 0;28382838+#ifdef INCL_SISUSB_CON28392839+ x.sisusb_conactive = sisusb->haveconsole ? 1 : 0;28402840+#else28412841+ x.sisusb_conactive = 0;28422842+#endif3177284331782844 if (copy_to_user((void __user *)arg, &x, sizeof(x)))31792845 retval = -EFAULT;···32392895};3240289632412897static struct usb_class_driver usb_sisusb_class = {28982898+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)32422899 .name = "usb/sisusbvga%d",32433243- .fops = &usb_sisusb_fops,32442900 .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,29012901+#else29022902+ .name = "sisusbvga%d",29032903+#endif29042904+ .fops = &usb_sisusb_fops,32452905 .minor_base = SISUSB_MINOR32462906};32472907···33422994 printk(KERN_INFO "sisusbvga[%d]: Allocated %d output buffers\n",33432995 sisusb->minor, sisusb->numobufs);3344299629972997+#ifdef INCL_SISUSB_CON29982998+ /* Allocate our SiS_Pr */29992999+ if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) {30003000+ printk(KERN_ERR30013001+ "sisusbvga[%d]: Failed to allocate SiS_Pr\n",30023002+ sisusb->minor);30033003+ }30043004+#endif30053005+33453006 /* Do remaining init stuff */3346300733473008 init_waitqueue_head(&sisusb->wait_q);3348300933493010 usb_set_intfdata(intf, sisusb);30113011+30123012+ usb_get_dev(sisusb->sisusb_dev);30133013+30143014+ sisusb->present = 1;3350301533513016#ifdef SISUSB_OLD_CONFIG_COMPAT33523017 {···33753014 sisusb->minor);33763015 else33773016 sisusb->ioctl32registered = 1;33783378-33793017 }33803018#endif3381301933823382- sisusb->present = 1;33833383-33843020 if (dev->speed == USB_SPEED_HIGH) {33853385- if (sisusb_init_gfxdevice(sisusb, 1))30213021+ int initscreen = 1;30223022+#ifdef INCL_SISUSB_CON30233023+ if (sisusb_first_vc > 0 &&30243024+ sisusb_last_vc > 0 &&30253025+ sisusb_first_vc <= sisusb_last_vc &&30263026+ sisusb_last_vc <= MAX_NR_CONSOLES)30273027+ initscreen = 0;30283028+#endif30293029+ if (sisusb_init_gfxdevice(sisusb, initscreen))33863030 printk(KERN_ERR33873031 "sisusbvga[%d]: Failed to early "33883032 "initialize device\n",···34003034 sisusb->minor);3401303534023036 sisusb->ready = 1;30373037+30383038+#ifdef SISUSBENDIANTEST30393039+ printk(KERN_DEBUG "sisusb: *** RWTEST ***\n");30403040+ sisusb_testreadwrite(sisusb);30413041+ printk(KERN_DEBUG "sisusb: *** RWTEST END ***\n");30423042+#endif30433043+30443044+#ifdef INCL_SISUSB_CON30453045+ sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);30463046+#endif3403304734043048 return 0;34053049···34293053 struct sisusb_usb_data *sisusb;34303054 int minor;3431305534323432- down(&disconnect_sem);34333433-34343056 /* This should *not* happen */34353435- if (!(sisusb = usb_get_intfdata(intf))) {34363436- up(&disconnect_sem);30573057+ if (!(sisusb = usb_get_intfdata(intf)))34373058 return;34383438- }30593059+30603060+#ifdef INCL_SISUSB_CON30613061+ sisusb_console_exit(sisusb);30623062+#endif30633063+30643064+ /* The above code doesn't need the disconnect30653065+ * semaphore to be down; its meaning is to30663066+ * protect all other routines from the disconnect30673067+ * case, not the other way round.30683068+ */30693069+ down(&disconnect_sem);3439307034403071 down(&sisusb->lock);34413072···35063123{35073124 int retval;3508312531263126+#ifdef INCL_SISUSB_CON31273127+ sisusb_init_concode();31283128+#endif31293129+35093130 if (!(retval = usb_register(&sisusb_driver))) {31313131+35103132 printk(KERN_INFO "sisusb: Driver version %d.%d.%d\n",35113133 SISUSB_VERSION, SISUSB_REVISION, SISUSB_PATCHLEVEL);35123134 printk(KERN_INFO35133135 "sisusb: Copyright (C) 2005 Thomas Winischhofer\n");31363136+35143137 }3515313835163139 return retval;···35313142module_exit(usb_sisusb_exit);3532314335333144MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");35343534-MODULE_DESCRIPTION("sisusb - Driver for Net2280/SiS315-based USB2VGA dongles");31453145+MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");35353146MODULE_LICENSE("GPL");35363147
+61-12
drivers/usb/misc/sisusbvga/sisusb.h
···4646#endif4747#endif48484949+/* For older kernels, support for text consoles is by default5050+ * off. To ensable text console support, change the following:5151+ */5252+#if 05353+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)5454+#define CONFIG_USB_SISUSBVGA_CON5555+#endif5656+#endif5757+4958/* Version Information */50595160#define SISUSB_VERSION 05261#define SISUSB_REVISION 05353-#define SISUSB_PATCHLEVEL 76262+#define SISUSB_PATCHLEVEL 86363+6464+/* Include console and mode switching code? */6565+6666+#ifdef CONFIG_USB_SISUSBVGA_CON6767+#define INCL_SISUSB_CON 16868+#endif6969+7070+#ifdef INCL_SISUSB_CON7171+#include <linux/console.h>7272+#include <linux/vt_kern.h>7373+#include "sisusb_struct.h"7474+#endif54755576/* USB related */56775757-#define SISUSB_MINOR 133 /* FIXME */7878+#define SISUSB_MINOR 133 /* official */58795980/* Size of the sisusb input/output buffers */6081#define SISUSB_IBUF_SIZE 0x01000···152131 unsigned char gfxinit; /* graphics core initialized? */153132 unsigned short chipid, chipvendor;154133 unsigned short chiprevision;134134+#ifdef INCL_SISUSB_CON135135+ struct SiS_Private *SiS_Pr;136136+ unsigned long scrbuf;137137+ unsigned int scrbuf_size;138138+ int haveconsole, con_first, con_last;139139+ int havethisconsole[MAX_NR_CONSOLES];140140+ int textmodedestroyed;141141+ unsigned int sisusb_num_columns; /* real number, not vt's idea */142142+ int cur_start_addr, con_rolled_over;143143+ int sisusb_cursor_loc, bad_cursor_pos;144144+ int sisusb_cursor_size_from;145145+ int sisusb_cursor_size_to;146146+ int current_font_height, current_font_512;147147+ int font_backup_size, font_backup_height, font_backup_512;148148+ char *font_backup;149149+ int font_slot;150150+ struct vc_data *sisusb_display_fg;151151+ int is_gfx;152152+ int con_blanked;153153+#endif155154};156155157156#define to_sisusb_dev(d) container_of(d, struct sisusb_usb_data, kref)···290249291250 __u32 sisusb_fbdevactive; /* != 0 if framebuffer device active */292251293293- __u8 sisusb_reserved[32]; /* for future use */252252+ __u32 sisusb_conactive; /* != 0 if console driver active */253253+254254+ __u8 sisusb_reserved[28]; /* for future use */294255};295256296257struct sisusb_command {···304261 __u32 data4; /* for future use */305262};306263307307-#define SUCMD_GET 0x01 /* for all: data0 = index, data3 = port */308308-#define SUCMD_SET 0x02 /* data1 = value */309309-#define SUCMD_SETOR 0x03 /* data1 = or */310310-#define SUCMD_SETAND 0x04 /* data1 = and */311311-#define SUCMD_SETANDOR 0x05 /* data1 = and, data2 = or */312312-#define SUCMD_SETMASK 0x06 /* data1 = data, data2 = mask */264264+#define SUCMD_GET 0x01 /* for all: data0 = index, data3 = port */265265+#define SUCMD_SET 0x02 /* data1 = value */266266+#define SUCMD_SETOR 0x03 /* data1 = or */267267+#define SUCMD_SETAND 0x04 /* data1 = and */268268+#define SUCMD_SETANDOR 0x05 /* data1 = and, data2 = or */269269+#define SUCMD_SETMASK 0x06 /* data1 = data, data2 = mask */313270314314-#define SUCMD_CLRSCR 0x07 /* data0:1:2 = length, data3 = address */271271+#define SUCMD_CLRSCR 0x07 /* data0:1:2 = length, data3 = address */272272+273273+#define SUCMD_HANDLETEXTMODE 0x08 /* Reset/destroy text mode */274274+275275+#define SUCMD_SETMODE 0x09 /* Set a display mode (data3 = SiS mode) */276276+#define SUCMD_SETVESAMODE 0x0a /* Set a display mode (data3 = VESA mode) */315277316278#define SISUSB_COMMAND _IOWR(0xF3,0x3D,struct sisusb_command)317317-#define SISUSB_GET_CONFIG_SIZE _IOR(0xF3,0x3E,__u32)318318-#define SISUSB_GET_CONFIG _IOR(0xF3,0x3F,struct sisusb_info)279279+#define SISUSB_GET_CONFIG_SIZE _IOR(0xF3,0x3E,__u32)280280+#define SISUSB_GET_CONFIG _IOR(0xF3,0x3F,struct sisusb_info)281281+319282320283#endif /* SISUSB_H */321284
+1658
drivers/usb/misc/sisusbvga/sisusb_con.c
···11+/*22+ * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles33+ *44+ * VGA text mode console part55+ *66+ * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria77+ *88+ * If distributed as part of the Linux kernel, this code is licensed under the99+ * terms of the GPL v2.1010+ *1111+ * Otherwise, the following license terms apply:1212+ *1313+ * * Redistribution and use in source and binary forms, with or without1414+ * * modification, are permitted provided that the following conditions1515+ * * are met:1616+ * * 1) Redistributions of source code must retain the above copyright1717+ * * notice, this list of conditions and the following disclaimer.1818+ * * 2) Redistributions in binary form must reproduce the above copyright1919+ * * notice, this list of conditions and the following disclaimer in the2020+ * * documentation and/or other materials provided with the distribution.2121+ * * 3) The name of the author may not be used to endorse or promote products2222+ * * derived from this software without specific psisusbr written permission.2323+ * *2424+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR2525+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES2626+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.2727+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,2828+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT2929+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,3030+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY3131+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT3232+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF3333+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.3434+ *3535+ * Author: Thomas Winischhofer <thomas@winischhofer.net>3636+ *3737+ * Portions based on vgacon.c which are3838+ * Created 28 Sep 1997 by Geert Uytterhoeven3939+ * Rewritten by Martin Mares <mj@ucw.cz>, July 19984040+ * based on code Copyright (C) 1991, 1992 Linus Torvalds4141+ * 1995 Jay Estabrook4242+ *4343+ * A note on using in_atomic() in here: We can't handle console4444+ * calls from non-schedulable context due to our USB-dependend4545+ * nature. For now, this driver just ignores any calls if it4646+ * detects this state.4747+ *4848+ */4949+5050+#include <linux/config.h>5151+#include <linux/version.h>5252+#include <linux/module.h>5353+#include <linux/kernel.h>5454+#include <linux/signal.h>5555+#include <linux/sched.h>5656+#include <linux/fs.h>5757+#include <linux/tty.h>5858+#include <linux/console.h>5959+#include <linux/string.h>6060+#include <linux/kd.h>6161+#include <linux/init.h>6262+#include <linux/slab.h>6363+#include <linux/vt_kern.h>6464+#include <linux/selection.h>6565+#include <linux/spinlock.h>6666+#include <linux/kref.h>6767+#include <linux/smp_lock.h>6868+#include <linux/ioport.h>6969+#include <linux/interrupt.h>7070+#include <linux/vmalloc.h>7171+7272+#include "sisusb.h"7373+7474+#ifdef INCL_SISUSB_CON7575+extern int sisusb_setreg(struct sisusb_usb_data *, int, u8);7676+extern int sisusb_getreg(struct sisusb_usb_data *, int, u8 *);7777+extern int sisusb_setidxreg(struct sisusb_usb_data *, int, u8, u8);7878+extern int sisusb_getidxreg(struct sisusb_usb_data *, int, u8, u8 *);7979+extern int sisusb_setidxregor(struct sisusb_usb_data *, int, u8, u8);8080+extern int sisusb_setidxregand(struct sisusb_usb_data *, int, u8, u8);8181+extern int sisusb_setidxregandor(struct sisusb_usb_data *, int, u8, u8, u8);8282+8383+extern int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);8484+extern int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data);8585+extern int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data);8686+extern int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data);8787+extern int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,8888+ u32 dest, int length, size_t *bytes_written);8989+9090+extern void sisusb_delete(struct kref *kref);9191+extern int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);9292+9393+extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);9494+9595+#define sisusbcon_writew(val, addr) (*(addr) = (val))9696+#define sisusbcon_readw(addr) (*(addr))9797+#define sisusbcon_memmovew(d, s, c) memmove(d, s, c)9898+#define sisusbcon_memcpyw(d, s, c) memcpy(d, s, c)9999+100100+/* vc_data -> sisusb conversion table */101101+static struct sisusb_usb_data *mysisusbs[MAX_NR_CONSOLES];102102+103103+/* Forward declaration */104104+static const struct consw sisusb_con;105105+106106+extern struct semaphore disconnect_sem;107107+108108+static inline void109109+sisusbcon_memsetw(u16 *s, u16 c, unsigned int count)110110+{111111+ count /= 2;112112+ while (count--)113113+ sisusbcon_writew(c, s++);114114+}115115+116116+static inline void117117+sisusb_initialize(struct sisusb_usb_data *sisusb)118118+{119119+ /* Reset cursor and start address */120120+ if (sisusb_setidxreg(sisusb, SISCR, 0x0c, 0x00))121121+ return;122122+ if (sisusb_setidxreg(sisusb, SISCR, 0x0d, 0x00))123123+ return;124124+ if (sisusb_setidxreg(sisusb, SISCR, 0x0e, 0x00))125125+ return;126126+ sisusb_setidxreg(sisusb, SISCR, 0x0f, 0x00);127127+}128128+129129+static inline void130130+sisusbcon_set_start_address(struct sisusb_usb_data *sisusb, struct vc_data *c)131131+{132132+ sisusb->cur_start_addr = (c->vc_visible_origin - sisusb->scrbuf) / 2;133133+134134+ sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));135135+ sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));136136+}137137+138138+void139139+sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location)140140+{141141+ if (sisusb->sisusb_cursor_loc == location)142142+ return;143143+144144+ sisusb->sisusb_cursor_loc = location;145145+146146+ /* Hardware bug: Text cursor appears twice or not at all147147+ * at some positions. Work around it with the cursor skew148148+ * bits.149149+ */150150+151151+ if ((location & 0x0007) == 0x0007) {152152+ sisusb->bad_cursor_pos = 1;153153+ location--;154154+ if (sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0x1f, 0x20))155155+ return;156156+ } else if (sisusb->bad_cursor_pos) {157157+ if (sisusb_setidxregand(sisusb, SISCR, 0x0b, 0x1f))158158+ return;159159+ sisusb->bad_cursor_pos = 0;160160+ }161161+162162+ if (sisusb_setidxreg(sisusb, SISCR, 0x0e, (location >> 8)))163163+ return;164164+ sisusb_setidxreg(sisusb, SISCR, 0x0f, (location & 0xff));165165+}166166+167167+static inline struct sisusb_usb_data *168168+sisusb_get_sisusb(unsigned short console)169169+{170170+ return mysisusbs[console];171171+}172172+173173+static inline int174174+sisusb_sisusb_valid(struct sisusb_usb_data *sisusb)175175+{176176+ if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev)177177+ return 0;178178+179179+ return 1;180180+}181181+182182+static struct sisusb_usb_data *183183+sisusb_get_sisusb_lock_and_check(unsigned short console)184184+{185185+ struct sisusb_usb_data *sisusb;186186+187187+ /* We can't handle console calls in non-schedulable188188+ * context due to our locks and the USB transport.189189+ * So we simply ignore them. This should only affect190190+ * some calls to printk.191191+ */192192+ if (in_atomic())193193+ return NULL;194194+195195+ if (!(sisusb = sisusb_get_sisusb(console)))196196+ return NULL;197197+198198+ down(&sisusb->lock);199199+200200+ if (!sisusb_sisusb_valid(sisusb) ||201201+ !sisusb->havethisconsole[console]) {202202+ up(&sisusb->lock);203203+ return NULL;204204+ }205205+206206+ return sisusb;207207+}208208+209209+static int210210+sisusb_is_inactive(struct vc_data *c, struct sisusb_usb_data *sisusb)211211+{212212+ if (sisusb->is_gfx ||213213+ sisusb->textmodedestroyed ||214214+ c->vc_mode != KD_TEXT)215215+ return 1;216216+217217+ return 0;218218+}219219+220220+/* con_startup console interface routine */221221+static const char *222222+sisusbcon_startup(void)223223+{224224+ return "SISUSBCON";225225+}226226+227227+/* con_init console interface routine */228228+static void229229+sisusbcon_init(struct vc_data *c, int init)230230+{231231+ struct sisusb_usb_data *sisusb;232232+ int cols, rows;233233+234234+ /* This is called by take_over_console(),235235+ * ie by us/under our control. It is236236+ * only called after text mode and fonts237237+ * are set up/restored.238238+ */239239+240240+ down(&disconnect_sem);241241+242242+ if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {243243+ up(&disconnect_sem);244244+ return;245245+ }246246+247247+ down(&sisusb->lock);248248+249249+ if (!sisusb_sisusb_valid(sisusb)) {250250+ up(&sisusb->lock);251251+ up(&disconnect_sem);252252+ return;253253+ }254254+255255+ c->vc_can_do_color = 1;256256+257257+ c->vc_complement_mask = 0x7700;258258+259259+ c->vc_hi_font_mask = sisusb->current_font_512 ? 0x0800 : 0;260260+261261+ sisusb->haveconsole = 1;262262+263263+ sisusb->havethisconsole[c->vc_num] = 1;264264+265265+ /* We only support 640x400 */266266+ c->vc_scan_lines = 400;267267+268268+ c->vc_font.height = sisusb->current_font_height;269269+270270+ /* We only support width = 8 */271271+ cols = 80;272272+ rows = c->vc_scan_lines / c->vc_font.height;273273+274274+ /* Increment usage count for our sisusb.275275+ * Doing so saves us from upping/downing276276+ * the disconnect semaphore; we can't277277+ * lose our sisusb until this is undone278278+ * in con_deinit. For all other console279279+ * interface functions, it suffices to280280+ * use sisusb->lock and do a quick check281281+ * of sisusb for device disconnection.282282+ */283283+ kref_get(&sisusb->kref);284284+285285+ if (!*c->vc_uni_pagedir_loc)286286+ con_set_default_unimap(c);287287+288288+ up(&sisusb->lock);289289+290290+ up(&disconnect_sem);291291+292292+ if (init) {293293+ c->vc_cols = cols;294294+ c->vc_rows = rows;295295+ } else296296+ vc_resize(c, cols, rows);297297+}298298+299299+/* con_deinit console interface routine */300300+static void301301+sisusbcon_deinit(struct vc_data *c)302302+{303303+ struct sisusb_usb_data *sisusb;304304+ int i;305305+306306+ /* This is called by take_over_console()307307+ * and others, ie not under our control.308308+ */309309+310310+ down(&disconnect_sem);311311+312312+ if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {313313+ up(&disconnect_sem);314314+ return;315315+ }316316+317317+ down(&sisusb->lock);318318+319319+ /* Clear ourselves in mysisusbs */320320+ mysisusbs[c->vc_num] = NULL;321321+322322+ sisusb->havethisconsole[c->vc_num] = 0;323323+324324+ /* Free our font buffer if all consoles are gone */325325+ if (sisusb->font_backup) {326326+ for(i = 0; i < MAX_NR_CONSOLES; i++) {327327+ if (sisusb->havethisconsole[c->vc_num])328328+ break;329329+ }330330+ if (i == MAX_NR_CONSOLES) {331331+ vfree(sisusb->font_backup);332332+ sisusb->font_backup = NULL;333333+ }334334+ }335335+336336+ up(&sisusb->lock);337337+338338+ /* decrement the usage count on our sisusb */339339+ kref_put(&sisusb->kref, sisusb_delete);340340+341341+ up(&disconnect_sem);342342+}343343+344344+/* interface routine */345345+static u8346346+sisusbcon_build_attr(struct vc_data *c, u8 color, u8 intensity,347347+ u8 blink, u8 underline, u8 reverse)348348+{349349+ u8 attr = color;350350+351351+ if (underline)352352+ attr = (attr & 0xf0) | c->vc_ulcolor;353353+ else if (intensity == 0)354354+ attr = (attr & 0xf0) | c->vc_halfcolor;355355+356356+ if (reverse)357357+ attr = ((attr) & 0x88) |358358+ ((((attr) >> 4) |359359+ ((attr) << 4)) & 0x77);360360+361361+ if (blink)362362+ attr ^= 0x80;363363+364364+ if (intensity == 2)365365+ attr ^= 0x08;366366+367367+ return attr;368368+}369369+370370+/* Interface routine */371371+static void372372+sisusbcon_invert_region(struct vc_data *vc, u16 *p, int count)373373+{374374+ /* Invert a region. This is called with a pointer375375+ * to the console's internal screen buffer. So we376376+ * simply do the inversion there and rely on377377+ * a call to putc(s) to update the real screen.378378+ */379379+380380+ while (count--) {381381+ u16 a = sisusbcon_readw(p);382382+383383+ a = ((a) & 0x88ff) |384384+ (((a) & 0x7000) >> 4) |385385+ (((a) & 0x0700) << 4);386386+387387+ sisusbcon_writew(a, p++);388388+ }389389+}390390+391391+#define SISUSB_VADDR(x,y) \392392+ ((u16 *)c->vc_origin + \393393+ (y) * sisusb->sisusb_num_columns + \394394+ (x))395395+396396+#define SISUSB_HADDR(x,y) \397397+ ((u16 *)(sisusb->vrambase + (c->vc_origin - sisusb->scrbuf)) + \398398+ (y) * sisusb->sisusb_num_columns + \399399+ (x))400400+401401+/* Interface routine */402402+static void403403+sisusbcon_putc(struct vc_data *c, int ch, int y, int x)404404+{405405+ struct sisusb_usb_data *sisusb;406406+ ssize_t written;407407+408408+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))409409+ return;410410+411411+ /* sisusb->lock is down */412412+413413+ /* Don't need to put the character into buffer ourselves,414414+ * because the vt does this BEFORE calling us.415415+ */416416+#if 0417417+ sisusbcon_writew(ch, SISUSB_VADDR(x, y));418418+#endif419419+420420+ if (sisusb_is_inactive(c, sisusb)) {421421+ up(&sisusb->lock);422422+ return;423423+ }424424+425425+426426+ sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),427427+ (u32)SISUSB_HADDR(x, y), 2, &written);428428+429429+ up(&sisusb->lock);430430+}431431+432432+/* Interface routine */433433+static void434434+sisusbcon_putcs(struct vc_data *c, const unsigned short *s,435435+ int count, int y, int x)436436+{437437+ struct sisusb_usb_data *sisusb;438438+ ssize_t written;439439+ u16 *dest;440440+ int i;441441+442442+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))443443+ return;444444+445445+ /* sisusb->lock is down */446446+447447+ /* Need to put the characters into the buffer ourselves,448448+ * because the vt does this AFTER calling us.449449+ */450450+451451+ dest = SISUSB_VADDR(x, y);452452+453453+ for (i = count; i > 0; i--)454454+ sisusbcon_writew(sisusbcon_readw(s++), dest++);455455+456456+ if (sisusb_is_inactive(c, sisusb)) {457457+ up(&sisusb->lock);458458+ return;459459+ }460460+461461+ sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),462462+ (u32)SISUSB_HADDR(x, y), count * 2, &written);463463+464464+ up(&sisusb->lock);465465+}466466+467467+/* Interface routine */468468+static void469469+sisusbcon_clear(struct vc_data *c, int y, int x, int height, int width)470470+{471471+ struct sisusb_usb_data *sisusb;472472+ u16 eattr = c->vc_video_erase_char;473473+ ssize_t written;474474+ int i, length, cols;475475+ u16 *dest;476476+477477+ if (width <= 0 || height <= 0)478478+ return;479479+480480+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))481481+ return;482482+483483+ /* sisusb->lock is down */484484+485485+ /* Need to clear buffer ourselves, because the vt does486486+ * this AFTER calling us.487487+ */488488+489489+ dest = SISUSB_VADDR(x, y);490490+491491+ cols = sisusb->sisusb_num_columns;492492+493493+ if (width > cols)494494+ width = cols;495495+496496+ if (x == 0 && width >= c->vc_cols) {497497+498498+ sisusbcon_memsetw(dest, eattr, height * cols * 2);499499+500500+ } else {501501+502502+ for (i = height; i > 0; i--, dest += cols)503503+ sisusbcon_memsetw(dest, eattr, width * 2);504504+505505+ }506506+507507+ if (sisusb_is_inactive(c, sisusb)) {508508+ up(&sisusb->lock);509509+ return;510510+ }511511+512512+ length = ((height * cols) - x - (cols - width - x)) * 2;513513+514514+515515+ sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(x, y),516516+ (u32)SISUSB_HADDR(x, y), length, &written);517517+518518+ up(&sisusb->lock);519519+}520520+521521+/* Interface routine */522522+static void523523+sisusbcon_bmove(struct vc_data *c, int sy, int sx,524524+ int dy, int dx, int height, int width)525525+{526526+ struct sisusb_usb_data *sisusb;527527+ ssize_t written;528528+ int cols, length;529529+#if 0530530+ u16 *src, *dest;531531+ int i;532532+#endif533533+534534+ if (width <= 0 || height <= 0)535535+ return;536536+537537+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))538538+ return;539539+540540+ /* sisusb->lock is down */541541+542542+ cols = sisusb->sisusb_num_columns;543543+544544+ /* Don't need to move data outselves, because545545+ * vt does this BEFORE calling us.546546+ * This is only used by vt's insert/deletechar.547547+ */548548+#if 0549549+ if (sx == 0 && dx == 0 && width >= c->vc_cols && width <= cols) {550550+551551+ sisusbcon_memmovew(SISUSB_VADDR(0, dy), SISUSB_VADDR(0, sy),552552+ height * width * 2);553553+554554+ } else if (dy < sy || (dy == sy && dx < sx)) {555555+556556+ src = SISUSB_VADDR(sx, sy);557557+ dest = SISUSB_VADDR(dx, dy);558558+559559+ for (i = height; i > 0; i--) {560560+ sisusbcon_memmovew(dest, src, width * 2);561561+ src += cols;562562+ dest += cols;563563+ }564564+565565+ } else {566566+567567+ src = SISUSB_VADDR(sx, sy + height - 1);568568+ dest = SISUSB_VADDR(dx, dy + height - 1);569569+570570+ for (i = height; i > 0; i--) {571571+ sisusbcon_memmovew(dest, src, width * 2);572572+ src -= cols;573573+ dest -= cols;574574+ }575575+576576+ }577577+#endif578578+579579+ if (sisusb_is_inactive(c, sisusb)) {580580+ up(&sisusb->lock);581581+ return;582582+ }583583+584584+ length = ((height * cols) - dx - (cols - width - dx)) * 2;585585+586586+587587+ sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(dx, dy),588588+ (u32)SISUSB_HADDR(dx, dy), length, &written);589589+590590+ up(&sisusb->lock);591591+}592592+593593+/* interface routine */594594+static int595595+sisusbcon_switch(struct vc_data *c)596596+{597597+ struct sisusb_usb_data *sisusb;598598+ ssize_t written;599599+ int length;600600+601601+ /* Returnvalue 0 means we have fully restored screen,602602+ * and vt doesn't need to call do_update_region().603603+ * Returnvalue != 0 naturally means the opposite.604604+ */605605+606606+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))607607+ return 0;608608+609609+ /* sisusb->lock is down */610610+611611+ /* Don't write to screen if in gfx mode */612612+ if (sisusb_is_inactive(c, sisusb)) {613613+ up(&sisusb->lock);614614+ return 0;615615+ }616616+617617+ /* That really should not happen. It would mean we are618618+ * being called while the vc is using its private buffer619619+ * as origin.620620+ */621621+ if (c->vc_origin == (unsigned long)c->vc_screenbuf) {622622+ up(&sisusb->lock);623623+ printk(KERN_DEBUG "sisusb: ASSERT ORIGIN != SCREENBUF!\n");624624+ return 0;625625+ }626626+627627+ /* Check that we don't copy too much */628628+ length = min((int)c->vc_screenbuf_size,629629+ (int)(sisusb->scrbuf + sisusb->scrbuf_size - c->vc_origin));630630+631631+ /* Restore the screen contents */632632+ sisusbcon_memcpyw((u16 *)c->vc_origin, (u16 *)c->vc_screenbuf,633633+ length);634634+635635+ sisusb_copy_memory(sisusb, (unsigned char *)c->vc_origin,636636+ (u32)SISUSB_HADDR(0, 0),637637+ length, &written);638638+639639+ up(&sisusb->lock);640640+641641+ return 0;642642+}643643+644644+/* interface routine */645645+static void646646+sisusbcon_save_screen(struct vc_data *c)647647+{648648+ struct sisusb_usb_data *sisusb;649649+ int length;650650+651651+ /* Save the current screen contents to vc's private652652+ * buffer.653653+ */654654+655655+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))656656+ return;657657+658658+ /* sisusb->lock is down */659659+660660+ if (sisusb_is_inactive(c, sisusb)) {661661+ up(&sisusb->lock);662662+ return;663663+ }664664+665665+ /* Check that we don't copy too much */666666+ length = min((int)c->vc_screenbuf_size,667667+ (int)(sisusb->scrbuf + sisusb->scrbuf_size - c->vc_origin));668668+669669+ /* Save the screen contents to vc's private buffer */670670+ sisusbcon_memcpyw((u16 *)c->vc_screenbuf, (u16 *)c->vc_origin,671671+ length);672672+673673+ up(&sisusb->lock);674674+}675675+676676+/* interface routine */677677+static int678678+sisusbcon_set_palette(struct vc_data *c, unsigned char *table)679679+{680680+ struct sisusb_usb_data *sisusb;681681+ int i, j;682682+683683+ /* Return value not used by vt */684684+685685+ if (!CON_IS_VISIBLE(c))686686+ return -EINVAL;687687+688688+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))689689+ return -EINVAL;690690+691691+ /* sisusb->lock is down */692692+693693+ if (sisusb_is_inactive(c, sisusb)) {694694+ up(&sisusb->lock);695695+ return -EINVAL;696696+ }697697+698698+ for (i = j = 0; i < 16; i++) {699699+ if (sisusb_setreg(sisusb, SISCOLIDX, table[i]))700700+ break;701701+ if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))702702+ break;703703+ if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))704704+ break;705705+ if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))706706+ break;707707+ }708708+709709+ up(&sisusb->lock);710710+711711+ return 0;712712+}713713+714714+/* interface routine */715715+static int716716+sisusbcon_blank(struct vc_data *c, int blank, int mode_switch)717717+{718718+ struct sisusb_usb_data *sisusb;719719+ u8 sr1, cr17, pmreg, cr63;720720+ ssize_t written;721721+ int ret = 0;722722+723723+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))724724+ return 0;725725+726726+ /* sisusb->lock is down */727727+728728+ if (mode_switch)729729+ sisusb->is_gfx = blank ? 1 : 0;730730+731731+ if (sisusb_is_inactive(c, sisusb)) {732732+ up(&sisusb->lock);733733+ return 0;734734+ }735735+736736+ switch (blank) {737737+738738+ case 1: /* Normal blanking: Clear screen */739739+ case -1:740740+ sisusbcon_memsetw((u16 *)c->vc_origin,741741+ c->vc_video_erase_char,742742+ c->vc_screenbuf_size);743743+ sisusb_copy_memory(sisusb,744744+ (unsigned char *)c->vc_origin,745745+ (u32)(sisusb->vrambase +746746+ (c->vc_origin - sisusb->scrbuf)),747747+ c->vc_screenbuf_size, &written);748748+ sisusb->con_blanked = 1;749749+ ret = 1;750750+ break;751751+752752+ default: /* VESA blanking */753753+ switch (blank) {754754+ case 0: /* Unblank */755755+ sr1 = 0x00;756756+ cr17 = 0x80;757757+ pmreg = 0x00;758758+ cr63 = 0x00;759759+ ret = 1;760760+ sisusb->con_blanked = 0;761761+ break;762762+ case VESA_VSYNC_SUSPEND + 1:763763+ sr1 = 0x20;764764+ cr17 = 0x80;765765+ pmreg = 0x80;766766+ cr63 = 0x40;767767+ break;768768+ case VESA_HSYNC_SUSPEND + 1:769769+ sr1 = 0x20;770770+ cr17 = 0x80;771771+ pmreg = 0x40;772772+ cr63 = 0x40;773773+ break;774774+ case VESA_POWERDOWN + 1:775775+ sr1 = 0x20;776776+ cr17 = 0x00;777777+ pmreg = 0xc0;778778+ cr63 = 0x40;779779+ break;780780+ default:781781+ up(&sisusb->lock);782782+ return -EINVAL;783783+ }784784+785785+ sisusb_setidxregandor(sisusb, SISSR, 0x01, ~0x20, sr1);786786+ sisusb_setidxregandor(sisusb, SISCR, 0x17, 0x7f, cr17);787787+ sisusb_setidxregandor(sisusb, SISSR, 0x1f, 0x3f, pmreg);788788+ sisusb_setidxregandor(sisusb, SISCR, 0x63, 0xbf, cr63);789789+790790+ }791791+792792+ up(&sisusb->lock);793793+794794+ return ret;795795+}796796+797797+/* interface routine */798798+static int799799+sisusbcon_scrolldelta(struct vc_data *c, int lines)800800+{801801+ struct sisusb_usb_data *sisusb;802802+ int margin = c->vc_size_row * 4;803803+ int ul, we, p, st;804804+805805+ /* The return value does not seem to be used */806806+807807+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))808808+ return 0;809809+810810+ /* sisusb->lock is down */811811+812812+ if (sisusb_is_inactive(c, sisusb)) {813813+ up(&sisusb->lock);814814+ return 0;815815+ }816816+817817+ if (!lines) /* Turn scrollback off */818818+ c->vc_visible_origin = c->vc_origin;819819+ else {820820+821821+ if (sisusb->con_rolled_over >822822+ (c->vc_scr_end - sisusb->scrbuf) + margin) {823823+824824+ ul = c->vc_scr_end - sisusb->scrbuf;825825+ we = sisusb->con_rolled_over + c->vc_size_row;826826+827827+ } else {828828+829829+ ul = 0;830830+ we = sisusb->scrbuf_size;831831+832832+ }833833+834834+ p = (c->vc_visible_origin - sisusb->scrbuf - ul + we) % we +835835+ lines * c->vc_size_row;836836+837837+ st = (c->vc_origin - sisusb->scrbuf - ul + we) % we;838838+839839+ if (st < 2 * margin)840840+ margin = 0;841841+842842+ if (p < margin)843843+ p = 0;844844+845845+ if (p > st - margin)846846+ p = st;847847+848848+ c->vc_visible_origin = sisusb->scrbuf + (p + ul) % we;849849+ }850850+851851+ sisusbcon_set_start_address(sisusb, c);852852+853853+ up(&sisusb->lock);854854+855855+ return 1;856856+}857857+858858+/* Interface routine */859859+static void860860+sisusbcon_cursor(struct vc_data *c, int mode)861861+{862862+ struct sisusb_usb_data *sisusb;863863+ int from, to, baseline;864864+865865+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))866866+ return;867867+868868+ /* sisusb->lock is down */869869+870870+ if (sisusb_is_inactive(c, sisusb)) {871871+ up(&sisusb->lock);872872+ return;873873+ }874874+875875+ if (c->vc_origin != c->vc_visible_origin) {876876+ c->vc_visible_origin = c->vc_origin;877877+ sisusbcon_set_start_address(sisusb, c);878878+ }879879+880880+ if (mode == CM_ERASE) {881881+ sisusb_setidxregor(sisusb, SISCR, 0x0a, 0x20);882882+ sisusb->sisusb_cursor_size_to = -1;883883+ up(&sisusb->lock);884884+ return;885885+ }886886+887887+ sisusb_set_cursor(sisusb, (c->vc_pos - sisusb->scrbuf) / 2);888888+889889+ baseline = c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2);890890+891891+ switch (c->vc_cursor_type & 0x0f) {892892+ case CUR_BLOCK: from = 1;893893+ to = c->vc_font.height;894894+ break;895895+ case CUR_TWO_THIRDS: from = c->vc_font.height / 3;896896+ to = baseline;897897+ break;898898+ case CUR_LOWER_HALF: from = c->vc_font.height / 2;899899+ to = baseline;900900+ break;901901+ case CUR_LOWER_THIRD: from = (c->vc_font.height * 2) / 3;902902+ to = baseline;903903+ break;904904+ case CUR_NONE: from = 31;905905+ to = 30;906906+ break;907907+ default:908908+ case CUR_UNDERLINE: from = baseline - 1;909909+ to = baseline;910910+ break;911911+ }912912+913913+ if (sisusb->sisusb_cursor_size_from != from ||914914+ sisusb->sisusb_cursor_size_to != to) {915915+916916+ sisusb_setidxreg(sisusb, SISCR, 0x0a, from);917917+ sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0, to);918918+919919+ sisusb->sisusb_cursor_size_from = from;920920+ sisusb->sisusb_cursor_size_to = to;921921+ }922922+923923+ up(&sisusb->lock);924924+}925925+926926+static int927927+sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb,928928+ int t, int b, int dir, int lines)929929+{930930+ int cols = sisusb->sisusb_num_columns;931931+ int length = ((b - t) * cols) * 2;932932+ u16 eattr = c->vc_video_erase_char;933933+ ssize_t written;934934+935935+ /* sisusb->lock is down */936936+937937+ /* Scroll an area which does not match the938938+ * visible screen's dimensions. This needs939939+ * to be done separately, as it does not940940+ * use hardware panning.941941+ */942942+943943+ switch (dir) {944944+945945+ case SM_UP:946946+ sisusbcon_memmovew(SISUSB_VADDR(0, t),947947+ SISUSB_VADDR(0, t + lines),948948+ (b - t - lines) * cols * 2);949949+ sisusbcon_memsetw(SISUSB_VADDR(0, b - lines), eattr,950950+ lines * cols * 2);951951+ break;952952+953953+ case SM_DOWN:954954+ sisusbcon_memmovew(SISUSB_VADDR(0, t + lines),955955+ SISUSB_VADDR(0, t),956956+ (b - t - lines) * cols * 2);957957+ sisusbcon_memsetw(SISUSB_VADDR(0, t), eattr,958958+ lines * cols * 2);959959+ break;960960+ }961961+962962+ sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(0, t),963963+ (u32)SISUSB_HADDR(0, t), length, &written);964964+965965+ up(&sisusb->lock);966966+967967+ return 1;968968+}969969+970970+/* Interface routine */971971+static int972972+sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines)973973+{974974+ struct sisusb_usb_data *sisusb;975975+ u16 eattr = c->vc_video_erase_char;976976+ ssize_t written;977977+ int copyall = 0;978978+ unsigned long oldorigin;979979+ unsigned int delta = lines * c->vc_size_row;980980+ u32 originoffset;981981+982982+ /* Returning != 0 means we have done the scrolling successfully.983983+ * Returning 0 makes vt do the scrolling on its own.984984+ * Note that con_scroll is only called if the console is985985+ * visible. In that case, the origin should be our buffer,986986+ * not the vt's private one.987987+ */988988+989989+ if (!lines)990990+ return 1;991991+992992+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))993993+ return 0;994994+995995+ /* sisusb->lock is down */996996+997997+ if (sisusb_is_inactive(c, sisusb)) {998998+ up(&sisusb->lock);999999+ return 0;10001000+ }10011001+10021002+ /* Special case */10031003+ if (t || b != c->vc_rows)10041004+ return sisusbcon_scroll_area(c, sisusb, t, b, dir, lines);10051005+10061006+ if (c->vc_origin != c->vc_visible_origin) {10071007+ c->vc_visible_origin = c->vc_origin;10081008+ sisusbcon_set_start_address(sisusb, c);10091009+ }10101010+10111011+ /* limit amount to maximum realistic size */10121012+ if (lines > c->vc_rows)10131013+ lines = c->vc_rows;10141014+10151015+ oldorigin = c->vc_origin;10161016+10171017+ switch (dir) {10181018+10191019+ case SM_UP:10201020+10211021+ if (c->vc_scr_end + delta >=10221022+ sisusb->scrbuf + sisusb->scrbuf_size) {10231023+ sisusbcon_memcpyw((u16 *)sisusb->scrbuf,10241024+ (u16 *)(oldorigin + delta),10251025+ c->vc_screenbuf_size - delta);10261026+ c->vc_origin = sisusb->scrbuf;10271027+ sisusb->con_rolled_over = oldorigin - sisusb->scrbuf;10281028+ copyall = 1;10291029+ } else10301030+ c->vc_origin += delta;10311031+10321032+ sisusbcon_memsetw(10331033+ (u16 *)(c->vc_origin + c->vc_screenbuf_size - delta),10341034+ eattr, delta);10351035+10361036+ break;10371037+10381038+ case SM_DOWN:10391039+10401040+ if (oldorigin - delta < sisusb->scrbuf) {10411041+ sisusbcon_memmovew((u16 *)(sisusb->scrbuf +10421042+ sisusb->scrbuf_size -10431043+ c->vc_screenbuf_size +10441044+ delta),10451045+ (u16 *)oldorigin,10461046+ c->vc_screenbuf_size - delta);10471047+ c->vc_origin = sisusb->scrbuf +10481048+ sisusb->scrbuf_size -10491049+ c->vc_screenbuf_size;10501050+ sisusb->con_rolled_over = 0;10511051+ copyall = 1;10521052+ } else10531053+ c->vc_origin -= delta;10541054+10551055+ c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;10561056+10571057+ scr_memsetw((u16 *)(c->vc_origin), eattr, delta);10581058+10591059+ break;10601060+ }10611061+10621062+ originoffset = (u32)(c->vc_origin - sisusb->scrbuf);10631063+10641064+ if (copyall)10651065+ sisusb_copy_memory(sisusb,10661066+ (char *)c->vc_origin,10671067+ (u32)(sisusb->vrambase + originoffset),10681068+ c->vc_screenbuf_size, &written);10691069+ else if (dir == SM_UP)10701070+ sisusb_copy_memory(sisusb,10711071+ (char *)c->vc_origin + c->vc_screenbuf_size - delta,10721072+ (u32)sisusb->vrambase + originoffset +10731073+ c->vc_screenbuf_size - delta,10741074+ delta, &written);10751075+ else10761076+ sisusb_copy_memory(sisusb,10771077+ (char *)c->vc_origin,10781078+ (u32)(sisusb->vrambase + originoffset),10791079+ delta, &written);10801080+10811081+ c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;10821082+ c->vc_visible_origin = c->vc_origin;10831083+10841084+ sisusbcon_set_start_address(sisusb, c);10851085+10861086+ c->vc_pos = c->vc_pos - oldorigin + c->vc_origin;10871087+10881088+ up(&sisusb->lock);10891089+10901090+ return 1;10911091+}10921092+10931093+/* Interface routine */10941094+static int10951095+sisusbcon_set_origin(struct vc_data *c)10961096+{10971097+ struct sisusb_usb_data *sisusb;10981098+10991099+ /* Returning != 0 means we were successful.11001100+ * Returning 0 will vt make to use its own11011101+ * screenbuffer as the origin.11021102+ */11031103+11041104+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))11051105+ return 0;11061106+11071107+ /* sisusb->lock is down */11081108+11091109+ if (sisusb_is_inactive(c, sisusb) || sisusb->con_blanked) {11101110+ up(&sisusb->lock);11111111+ return 0;11121112+ }11131113+11141114+ c->vc_origin = c->vc_visible_origin = sisusb->scrbuf;11151115+11161116+ sisusbcon_set_start_address(sisusb, c);11171117+11181118+ sisusb->con_rolled_over = 0;11191119+11201120+ up(&sisusb->lock);11211121+11221122+ return 1;11231123+}11241124+11251125+/* Interface routine */11261126+static int11271127+sisusbcon_resize(struct vc_data *c, unsigned int newcols, unsigned int newrows)11281128+{11291129+ struct sisusb_usb_data *sisusb;11301130+ int fh;11311131+11321132+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))11331133+ return -ENODEV;11341134+11351135+ fh = sisusb->current_font_height;11361136+11371137+ up(&sisusb->lock);11381138+11391139+ /* We are quite unflexible as regards resizing. The vt code11401140+ * handles sizes where the line length isn't equal the pitch11411141+ * quite badly. As regards the rows, our panning tricks only11421142+ * work well if the number of rows equals the visible number11431143+ * of rows.11441144+ */11451145+11461146+ if (newcols != 80 || c->vc_scan_lines / fh != newrows)11471147+ return -EINVAL;11481148+11491149+ return 0;11501150+}11511151+11521152+int11531153+sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,11541154+ u8 *arg, int cmapsz, int ch512, int dorecalc,11551155+ struct vc_data *c, int fh, int uplock)11561156+{11571157+ int font_select = 0x00, i, err = 0;11581158+ u32 offset = 0;11591159+ u8 dummy;11601160+11611161+ /* sisusb->lock is down */11621162+11631163+ /*11641164+ * The default font is kept in slot 0.11651165+ * A user font is loaded in slot 2 (256 ch)11661166+ * or 2+3 (512 ch).11671167+ */11681168+11691169+ if ((slot != 0 && slot != 2) || !fh) {11701170+ if (uplock)11711171+ up(&sisusb->lock);11721172+ return -EINVAL;11731173+ }11741174+11751175+ if (set)11761176+ sisusb->font_slot = slot;11771177+11781178+ /* Default font is always 256 */11791179+ if (slot == 0)11801180+ ch512 = 0;11811181+ else11821182+ offset = 4 * cmapsz;11831183+11841184+ font_select = (slot == 0) ? 0x00 : (ch512 ? 0x0e : 0x0a);11851185+11861186+ err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x01); /* Reset */11871187+ err |= sisusb_setidxreg(sisusb, SISSR, 0x02, 0x04); /* Write to plane 2 */11881188+ err |= sisusb_setidxreg(sisusb, SISSR, 0x04, 0x07); /* Memory mode a0-bf */11891189+ err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x03); /* Reset */11901190+11911191+ if (err)11921192+ goto font_op_error;11931193+11941194+ err |= sisusb_setidxreg(sisusb, SISGR, 0x04, 0x03); /* Select plane read 2 */11951195+ err |= sisusb_setidxreg(sisusb, SISGR, 0x05, 0x00); /* Disable odd/even */11961196+ err |= sisusb_setidxreg(sisusb, SISGR, 0x06, 0x00); /* Address range a0-bf */11971197+11981198+ if (err)11991199+ goto font_op_error;12001200+12011201+ if (arg) {12021202+ if (set)12031203+ for (i = 0; i < cmapsz; i++) {12041204+ err |= sisusb_writeb(sisusb,12051205+ sisusb->vrambase + offset + i,12061206+ arg[i]);12071207+ if (err)12081208+ break;12091209+ }12101210+ else12111211+ for (i = 0; i < cmapsz; i++) {12121212+ err |= sisusb_readb(sisusb,12131213+ sisusb->vrambase + offset + i,12141214+ &arg[i]);12151215+ if (err)12161216+ break;12171217+ }12181218+12191219+ /*12201220+ * In 512-character mode, the character map is not contiguous if12211221+ * we want to remain EGA compatible -- which we do12221222+ */12231223+12241224+ if (ch512) {12251225+ if (set)12261226+ for (i = 0; i < cmapsz; i++) {12271227+ err |= sisusb_writeb(sisusb,12281228+ sisusb->vrambase + offset +12291229+ (2 * cmapsz) + i,12301230+ arg[cmapsz + i]);12311231+ if (err)12321232+ break;12331233+ }12341234+ else12351235+ for (i = 0; i < cmapsz; i++) {12361236+ err |= sisusb_readb(sisusb,12371237+ sisusb->vrambase + offset +12381238+ (2 * cmapsz) + i,12391239+ &arg[cmapsz + i]);12401240+ if (err)12411241+ break;12421242+ }12431243+ }12441244+ }12451245+12461246+ if (err)12471247+ goto font_op_error;12481248+12491249+ err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x01); /* Reset */12501250+ err |= sisusb_setidxreg(sisusb, SISSR, 0x02, 0x03); /* Write to planes 0+1 */12511251+ err |= sisusb_setidxreg(sisusb, SISSR, 0x04, 0x03); /* Memory mode a0-bf */12521252+ if (set)12531253+ sisusb_setidxreg(sisusb, SISSR, 0x03, font_select);12541254+ err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x03); /* Reset end */12551255+12561256+ if (err)12571257+ goto font_op_error;12581258+12591259+ err |= sisusb_setidxreg(sisusb, SISGR, 0x04, 0x00); /* Select plane read 0 */12601260+ err |= sisusb_setidxreg(sisusb, SISGR, 0x05, 0x10); /* Enable odd/even */12611261+ err |= sisusb_setidxreg(sisusb, SISGR, 0x06, 0x06); /* Address range b8-bf */12621262+12631263+ if (err)12641264+ goto font_op_error;12651265+12661266+ if ((set) && (ch512 != sisusb->current_font_512)) {12671267+12681268+ /* Font is shared among all our consoles.12691269+ * And so is the hi_font_mask.12701270+ */12711271+ for (i = 0; i < MAX_NR_CONSOLES; i++) {12721272+ struct vc_data *c = vc_cons[i].d;12731273+ if (c && c->vc_sw == &sisusb_con)12741274+ c->vc_hi_font_mask = ch512 ? 0x0800 : 0;12751275+ }12761276+12771277+ sisusb->current_font_512 = ch512;12781278+12791279+ /* color plane enable register:12801280+ 256-char: enable intensity bit12811281+ 512-char: disable intensity bit */12821282+ sisusb_getreg(sisusb, SISINPSTAT, &dummy);12831283+ sisusb_setreg(sisusb, SISAR, 0x12);12841284+ sisusb_setreg(sisusb, SISAR, ch512 ? 0x07 : 0x0f);12851285+12861286+ sisusb_getreg(sisusb, SISINPSTAT, &dummy);12871287+ sisusb_setreg(sisusb, SISAR, 0x20);12881288+ sisusb_getreg(sisusb, SISINPSTAT, &dummy);12891289+ }12901290+12911291+ if (dorecalc) {12921292+12931293+ /*12941294+ * Adjust the screen to fit a font of a certain height12951295+ */12961296+12971297+ unsigned char ovr, vde, fsr;12981298+ int rows = 0, maxscan = 0;12991299+13001300+ if (c) {13011301+13021302+ /* Number of video rows */13031303+ rows = c->vc_scan_lines / fh;13041304+ /* Scan lines to actually display-1 */13051305+ maxscan = rows * fh - 1;13061306+13071307+ /*printk(KERN_DEBUG "sisusb recalc rows %d maxscan %d fh %d sl %d\n",13081308+ rows, maxscan, fh, c->vc_scan_lines);*/13091309+13101310+ sisusb_getidxreg(sisusb, SISCR, 0x07, &ovr);13111311+ vde = maxscan & 0xff;13121312+ ovr = (ovr & 0xbd) |13131313+ ((maxscan & 0x100) >> 7) |13141314+ ((maxscan & 0x200) >> 3);13151315+ sisusb_setidxreg(sisusb, SISCR, 0x07, ovr);13161316+ sisusb_setidxreg(sisusb, SISCR, 0x12, vde);13171317+13181318+ }13191319+13201320+ sisusb_getidxreg(sisusb, SISCR, 0x09, &fsr);13211321+ fsr = (fsr & 0xe0) | (fh - 1);13221322+ sisusb_setidxreg(sisusb, SISCR, 0x09, fsr);13231323+ sisusb->current_font_height = fh;13241324+13251325+ sisusb->sisusb_cursor_size_from = -1;13261326+ sisusb->sisusb_cursor_size_to = -1;13271327+13281328+ }13291329+13301330+ if (uplock)13311331+ up(&sisusb->lock);13321332+13331333+ if (dorecalc && c) {13341334+ int i, rows = c->vc_scan_lines / fh;13351335+13361336+ /* Now adjust our consoles' size */13371337+13381338+ for (i = 0; i < MAX_NR_CONSOLES; i++) {13391339+ struct vc_data *vc = vc_cons[i].d;13401340+13411341+ if (vc && vc->vc_sw == &sisusb_con) {13421342+ if (CON_IS_VISIBLE(vc)) {13431343+ vc->vc_sw->con_cursor(vc, CM_DRAW);13441344+ }13451345+ vc->vc_font.height = fh;13461346+ vc_resize(vc, 0, rows);13471347+ }13481348+ }13491349+ }13501350+13511351+ return 0;13521352+13531353+font_op_error:13541354+ if (uplock)13551355+ up(&sisusb->lock);13561356+13571357+ return -EIO;13581358+}13591359+13601360+/* Interface routine */13611361+static int13621362+sisusbcon_font_set(struct vc_data *c, struct console_font *font,13631363+ unsigned flags)13641364+{13651365+ struct sisusb_usb_data *sisusb;13661366+ unsigned charcount = font->charcount;13671367+13681368+ if (font->width != 8 || (charcount != 256 && charcount != 512))13691369+ return -EINVAL;13701370+13711371+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))13721372+ return -ENODEV;13731373+13741374+ /* sisusb->lock is down */13751375+13761376+ /* Save the user-provided font into a buffer. This13771377+ * is used for restoring text mode after quitting13781378+ * from X and for the con_getfont routine.13791379+ */13801380+ if (sisusb->font_backup) {13811381+ if (sisusb->font_backup_size < charcount) {13821382+ vfree(sisusb->font_backup);13831383+ sisusb->font_backup = NULL;13841384+ }13851385+ }13861386+13871387+ if (!sisusb->font_backup)13881388+ sisusb->font_backup = vmalloc(charcount * 32);13891389+13901390+ if (sisusb->font_backup) {13911391+ memcpy(sisusb->font_backup, font->data, charcount * 32);13921392+ sisusb->font_backup_size = charcount;13931393+ sisusb->font_backup_height = font->height;13941394+ sisusb->font_backup_512 = (charcount == 512) ? 1 : 0;13951395+ }13961396+13971397+ /* do_font_op ups sisusb->lock */13981398+13991399+ return sisusbcon_do_font_op(sisusb, 1, 2, font->data,14001400+ 8192, (charcount == 512),14011401+ (!(flags & KD_FONT_FLAG_DONT_RECALC)) ? 1 : 0,14021402+ c, font->height, 1);14031403+}14041404+14051405+/* Interface routine */14061406+static int14071407+sisusbcon_font_get(struct vc_data *c, struct console_font *font)14081408+{14091409+ struct sisusb_usb_data *sisusb;14101410+14111411+ if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))14121412+ return -ENODEV;14131413+14141414+ /* sisusb->lock is down */14151415+14161416+ font->width = 8;14171417+ font->height = c->vc_font.height;14181418+ font->charcount = 256;14191419+14201420+ if (!font->data) {14211421+ up(&sisusb->lock);14221422+ return 0;14231423+ }14241424+14251425+ if (!sisusb->font_backup) {14261426+ up(&sisusb->lock);14271427+ return -ENODEV;14281428+ }14291429+14301430+ /* Copy 256 chars only, like vgacon */14311431+ memcpy(font->data, sisusb->font_backup, 256 * 32);14321432+14331433+ up(&sisusb->lock);14341434+14351435+ return 0;14361436+}14371437+14381438+/*14391439+ * The console `switch' structure for the sisusb console14401440+ */14411441+14421442+static const struct consw sisusb_con = {14431443+ .owner = THIS_MODULE,14441444+ .con_startup = sisusbcon_startup,14451445+ .con_init = sisusbcon_init,14461446+ .con_deinit = sisusbcon_deinit,14471447+ .con_clear = sisusbcon_clear,14481448+ .con_putc = sisusbcon_putc,14491449+ .con_putcs = sisusbcon_putcs,14501450+ .con_cursor = sisusbcon_cursor,14511451+ .con_scroll = sisusbcon_scroll,14521452+ .con_bmove = sisusbcon_bmove,14531453+ .con_switch = sisusbcon_switch,14541454+ .con_blank = sisusbcon_blank,14551455+ .con_font_set = sisusbcon_font_set,14561456+ .con_font_get = sisusbcon_font_get,14571457+ .con_set_palette = sisusbcon_set_palette,14581458+ .con_scrolldelta = sisusbcon_scrolldelta,14591459+ .con_build_attr = sisusbcon_build_attr,14601460+ .con_invert_region = sisusbcon_invert_region,14611461+ .con_set_origin = sisusbcon_set_origin,14621462+ .con_save_screen = sisusbcon_save_screen,14631463+ .con_resize = sisusbcon_resize,14641464+};14651465+14661466+/* Our very own dummy console driver */14671467+14681468+static const char *sisusbdummycon_startup(void)14691469+{14701470+ return "SISUSBVGADUMMY";14711471+}14721472+14731473+static void sisusbdummycon_init(struct vc_data *vc, int init)14741474+{14751475+ vc->vc_can_do_color = 1;14761476+ if (init) {14771477+ vc->vc_cols = 80;14781478+ vc->vc_rows = 25;14791479+ } else14801480+ vc_resize(vc, 80, 25);14811481+}14821482+14831483+static int sisusbdummycon_dummy(void)14841484+{14851485+ return 0;14861486+}14871487+14881488+#define SISUSBCONDUMMY (void *)sisusbdummycon_dummy14891489+14901490+const struct consw sisusb_dummy_con = {14911491+ .owner = THIS_MODULE,14921492+ .con_startup = sisusbdummycon_startup,14931493+ .con_init = sisusbdummycon_init,14941494+ .con_deinit = SISUSBCONDUMMY,14951495+ .con_clear = SISUSBCONDUMMY,14961496+ .con_putc = SISUSBCONDUMMY,14971497+ .con_putcs = SISUSBCONDUMMY,14981498+ .con_cursor = SISUSBCONDUMMY,14991499+ .con_scroll = SISUSBCONDUMMY,15001500+ .con_bmove = SISUSBCONDUMMY,15011501+ .con_switch = SISUSBCONDUMMY,15021502+ .con_blank = SISUSBCONDUMMY,15031503+ .con_font_set = SISUSBCONDUMMY,15041504+ .con_font_get = SISUSBCONDUMMY,15051505+ .con_font_default = SISUSBCONDUMMY,15061506+ .con_font_copy = SISUSBCONDUMMY,15071507+ .con_set_palette = SISUSBCONDUMMY,15081508+ .con_scrolldelta = SISUSBCONDUMMY,15091509+};15101510+15111511+int15121512+sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)15131513+{15141514+ int i, ret, minor = sisusb->minor;15151515+15161516+ down(&disconnect_sem);15171517+15181518+ down(&sisusb->lock);15191519+15201520+ /* Erm.. that should not happen */15211521+ if (sisusb->haveconsole || !sisusb->SiS_Pr) {15221522+ up(&sisusb->lock);15231523+ up(&disconnect_sem);15241524+ return 1;15251525+ }15261526+15271527+ sisusb->con_first = first;15281528+ sisusb->con_last = last;15291529+15301530+ if (first > last ||15311531+ first > MAX_NR_CONSOLES ||15321532+ last > MAX_NR_CONSOLES) {15331533+ up(&sisusb->lock);15341534+ up(&disconnect_sem);15351535+ return 1;15361536+ }15371537+15381538+ /* If gfxcore not initialized or no consoles given, quit graciously */15391539+ if (!sisusb->gfxinit || first < 1 || last < 1) {15401540+ up(&sisusb->lock);15411541+ up(&disconnect_sem);15421542+ return 0;15431543+ }15441544+15451545+ sisusb->sisusb_cursor_loc = -1;15461546+ sisusb->sisusb_cursor_size_from = -1;15471547+ sisusb->sisusb_cursor_size_to = -1;15481548+15491549+ /* Set up text mode (and upload default font) */15501550+ if (sisusb_reset_text_mode(sisusb, 1)) {15511551+ up(&sisusb->lock);15521552+ up(&disconnect_sem);15531553+ printk(KERN_ERR15541554+ "sisusbvga[%d]: Failed to set up text mode\n",15551555+ minor);15561556+ return 1;15571557+ }15581558+15591559+ /* Initialize some gfx registers */15601560+ sisusb_initialize(sisusb);15611561+15621562+ for (i = first - 1; i <= last - 1; i++) {15631563+ /* Save sisusb for our interface routines */15641564+ mysisusbs[i] = sisusb;15651565+ }15661566+15671567+ /* Initial console setup */15681568+ sisusb->sisusb_num_columns = 80;15691569+15701570+ /* Use a 32K buffer (matches b8000-bffff area) */15711571+ sisusb->scrbuf_size = 32 * 1024;15721572+15731573+ /* Allocate screen buffer */15741574+ if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) {15751575+ up(&sisusb->lock);15761576+ up(&disconnect_sem);15771577+ printk(KERN_ERR15781578+ "sisusbvga[%d]: Failed to allocate screen buffer\n",15791579+ minor);15801580+ return 1;15811581+ }15821582+15831583+ up(&sisusb->lock);15841584+ up(&disconnect_sem);15851585+15861586+ /* Now grab the desired console(s) */15871587+ ret = take_over_console(&sisusb_con, first - 1, last - 1, 0);15881588+15891589+ if (!ret)15901590+ sisusb->haveconsole = 1;15911591+ else {15921592+ for (i = first - 1; i <= last - 1; i++)15931593+ mysisusbs[i] = NULL;15941594+ }15951595+15961596+ return ret;15971597+}15981598+15991599+void16001600+sisusb_console_exit(struct sisusb_usb_data *sisusb)16011601+{16021602+ int i;16031603+16041604+ /* This is called if the device is disconnected16051605+ * and while disconnect and lock semaphores16061606+ * are up. This should be save because we16071607+ * can't lose our sisusb any other way but by16081608+ * disconnection (and hence, the disconnect16091609+ * sema is for protecting all other access16101610+ * functions from disconnection, not the16111611+ * other way round).16121612+ */16131613+16141614+ /* Now what do we do in case of disconnection:16151615+ * One alternative would be to simply call16161616+ * give_up_console(). Nah, not a good idea.16171617+ * give_up_console() is obviously buggy as it16181618+ * only discards the consw pointer from the16191619+ * driver_map, but doesn't adapt vc->vc_sw16201620+ * of the affected consoles. Hence, the next16211621+ * call to any of the console functions will16221622+ * eventually take a trip to oops county.16231623+ * Also, give_up_console for some reason16241624+ * doesn't decrement our module refcount.16251625+ * Instead, we switch our consoles to a private16261626+ * dummy console. This, of course, keeps our16271627+ * refcount up as well, but it works perfectly.16281628+ */16291629+16301630+ if (sisusb->haveconsole) {16311631+ for (i = 0; i < MAX_NR_CONSOLES; i++)16321632+ if (sisusb->havethisconsole[i])16331633+ take_over_console(&sisusb_dummy_con, i, i, 0);16341634+ /* At this point, con_deinit for all our16351635+ * consoles is executed by take_over_console().16361636+ */16371637+ sisusb->haveconsole = 0;16381638+ }16391639+16401640+ vfree((void *)sisusb->scrbuf);16411641+ sisusb->scrbuf = 0;16421642+16431643+ vfree(sisusb->font_backup);16441644+ sisusb->font_backup = NULL;16451645+}16461646+16471647+void __init sisusb_init_concode(void)16481648+{16491649+ int i;16501650+16511651+ for (i = 0; i < MAX_NR_CONSOLES; i++)16521652+ mysisusbs[i] = NULL;16531653+}16541654+16551655+#endif /* INCL_CON */16561656+16571657+16581658+
+1047
drivers/usb/misc/sisusbvga/sisusb_init.c
···11+/*22+ * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles33+ *44+ * Display mode initializing code55+ *66+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria77+ *88+ * If distributed as part of the Linux kernel, this code is licensed under the99+ * terms of the GPL v2.1010+ *1111+ * Otherwise, the following license terms apply:1212+ *1313+ * * Redistribution and use in source and binary forms, with or without1414+ * * modification, are permitted provided that the following conditions1515+ * * are met:1616+ * * 1) Redistributions of source code must retain the above copyright1717+ * * notice, this list of conditions and the following disclaimer.1818+ * * 2) Redistributions in binary form must reproduce the above copyright1919+ * * notice, this list of conditions and the following disclaimer in the2020+ * * documentation and/or other materials provided with the distribution.2121+ * * 3) The name of the author may not be used to endorse or promote products2222+ * * derived from this software without specific prior written permission.2323+ * *2424+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR2525+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES2626+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.2727+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,2828+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT2929+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,3030+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY3131+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT3232+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF3333+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.3434+ *3535+ * Author: Thomas Winischhofer <thomas@winischhofer.net>3636+ *3737+ */3838+3939+#include <linux/config.h>4040+#include <linux/version.h>4141+#include <linux/module.h>4242+#include <linux/kernel.h>4343+#include <linux/errno.h>4444+#include <linux/poll.h>4545+#include <linux/init.h>4646+#include <linux/slab.h>4747+#include <linux/spinlock.h>4848+#include <linux/kref.h>4949+5050+#include "sisusb.h"5151+5252+#ifdef INCL_SISUSB_CON5353+5454+#include "sisusb_init.h"5555+5656+/*********************************************/5757+/* POINTER INITIALIZATION */5858+/*********************************************/5959+6060+static void6161+SiSUSB_InitPtr(struct SiS_Private *SiS_Pr)6262+{6363+ SiS_Pr->SiS_ModeResInfo = SiSUSB_ModeResInfo;6464+ SiS_Pr->SiS_StandTable = SiSUSB_StandTable;6565+6666+ SiS_Pr->SiS_SModeIDTable = SiSUSB_SModeIDTable;6767+ SiS_Pr->SiS_EModeIDTable = SiSUSB_EModeIDTable;6868+ SiS_Pr->SiS_RefIndex = SiSUSB_RefIndex;6969+ SiS_Pr->SiS_CRT1Table = SiSUSB_CRT1Table;7070+7171+ SiS_Pr->SiS_VCLKData = SiSUSB_VCLKData;7272+}7373+7474+/*********************************************/7575+/* HELPER: Get ModeID */7676+/*********************************************/7777+7878+unsigned short7979+SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth)8080+{8181+ unsigned short ModeIndex = 0;8282+8383+ switch (HDisplay)8484+ {8585+ case 320:8686+ if (VDisplay == 200)8787+ ModeIndex = ModeIndex_320x200[Depth];8888+ else if (VDisplay == 240)8989+ ModeIndex = ModeIndex_320x240[Depth];9090+ break;9191+ case 400:9292+ if (VDisplay == 300)9393+ ModeIndex = ModeIndex_400x300[Depth];9494+ break;9595+ case 512:9696+ if (VDisplay == 384)9797+ ModeIndex = ModeIndex_512x384[Depth];9898+ break;9999+ case 640:100100+ if (VDisplay == 480)101101+ ModeIndex = ModeIndex_640x480[Depth];102102+ else if (VDisplay == 400)103103+ ModeIndex = ModeIndex_640x400[Depth];104104+ break;105105+ case 720:106106+ if (VDisplay == 480)107107+ ModeIndex = ModeIndex_720x480[Depth];108108+ else if (VDisplay == 576)109109+ ModeIndex = ModeIndex_720x576[Depth];110110+ break;111111+ case 768:112112+ if (VDisplay == 576)113113+ ModeIndex = ModeIndex_768x576[Depth];114114+ break;115115+ case 800:116116+ if (VDisplay == 600)117117+ ModeIndex = ModeIndex_800x600[Depth];118118+ else if (VDisplay == 480)119119+ ModeIndex = ModeIndex_800x480[Depth];120120+ break;121121+ case 848:122122+ if (VDisplay == 480)123123+ ModeIndex = ModeIndex_848x480[Depth];124124+ break;125125+ case 856:126126+ if (VDisplay == 480)127127+ ModeIndex = ModeIndex_856x480[Depth];128128+ break;129129+ case 960:130130+ if (VDisplay == 540)131131+ ModeIndex = ModeIndex_960x540[Depth];132132+ else if (VDisplay == 600)133133+ ModeIndex = ModeIndex_960x600[Depth];134134+ break;135135+ case 1024:136136+ if (VDisplay == 576)137137+ ModeIndex = ModeIndex_1024x576[Depth];138138+ else if (VDisplay == 768)139139+ ModeIndex = ModeIndex_1024x768[Depth];140140+ break;141141+ case 1152:142142+ if (VDisplay == 864)143143+ ModeIndex = ModeIndex_1152x864[Depth];144144+ break;145145+ case 1280:146146+ switch (VDisplay) {147147+ case 720:148148+ ModeIndex = ModeIndex_1280x720[Depth];149149+ break;150150+ case 768:151151+ ModeIndex = ModeIndex_1280x768[Depth];152152+ break;153153+ case 1024:154154+ ModeIndex = ModeIndex_1280x1024[Depth];155155+ break;156156+ }157157+ }158158+159159+ return ModeIndex;160160+}161161+162162+/*********************************************/163163+/* HELPER: SetReg, GetReg */164164+/*********************************************/165165+166166+static void167167+SiS_SetReg(struct SiS_Private *SiS_Pr, unsigned long port,168168+ unsigned short index, unsigned short data)169169+{170170+ sisusb_setidxreg(SiS_Pr->sisusb, port, index, data);171171+}172172+173173+static void174174+SiS_SetRegByte(struct SiS_Private *SiS_Pr, unsigned long port,175175+ unsigned short data)176176+{177177+ sisusb_setreg(SiS_Pr->sisusb, port, data);178178+}179179+180180+static unsigned char181181+SiS_GetReg(struct SiS_Private *SiS_Pr, unsigned long port,182182+ unsigned short index)183183+{184184+ u8 data;185185+186186+ sisusb_getidxreg(SiS_Pr->sisusb, port, index, &data);187187+188188+ return data;189189+}190190+191191+static unsigned char192192+SiS_GetRegByte(struct SiS_Private *SiS_Pr, unsigned long port)193193+{194194+ u8 data;195195+196196+ sisusb_getreg(SiS_Pr->sisusb, port, &data);197197+198198+ return data;199199+}200200+201201+static void202202+SiS_SetRegANDOR(struct SiS_Private *SiS_Pr, unsigned long port,203203+ unsigned short index, unsigned short DataAND,204204+ unsigned short DataOR)205205+{206206+ sisusb_setidxregandor(SiS_Pr->sisusb, port, index, DataAND, DataOR);207207+}208208+209209+static void210210+SiS_SetRegAND(struct SiS_Private *SiS_Pr, unsigned long port,211211+ unsigned short index, unsigned short DataAND)212212+{213213+ sisusb_setidxregand(SiS_Pr->sisusb, port, index, DataAND);214214+}215215+216216+static void217217+SiS_SetRegOR(struct SiS_Private *SiS_Pr,unsigned long port,218218+ unsigned short index, unsigned short DataOR)219219+{220220+ sisusb_setidxregor(SiS_Pr->sisusb, port, index, DataOR);221221+}222222+223223+/*********************************************/224224+/* HELPER: DisplayOn, DisplayOff */225225+/*********************************************/226226+227227+static void228228+SiS_DisplayOn(struct SiS_Private *SiS_Pr)229229+{230230+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0xDF);231231+}232232+233233+/*********************************************/234234+/* HELPER: Init Port Addresses */235235+/*********************************************/236236+237237+void238238+SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr)239239+{240240+ SiS_Pr->SiS_P3c4 = BaseAddr + 0x14;241241+ SiS_Pr->SiS_P3d4 = BaseAddr + 0x24;242242+ SiS_Pr->SiS_P3c0 = BaseAddr + 0x10;243243+ SiS_Pr->SiS_P3ce = BaseAddr + 0x1e;244244+ SiS_Pr->SiS_P3c2 = BaseAddr + 0x12;245245+ SiS_Pr->SiS_P3ca = BaseAddr + 0x1a;246246+ SiS_Pr->SiS_P3c6 = BaseAddr + 0x16;247247+ SiS_Pr->SiS_P3c7 = BaseAddr + 0x17;248248+ SiS_Pr->SiS_P3c8 = BaseAddr + 0x18;249249+ SiS_Pr->SiS_P3c9 = BaseAddr + 0x19;250250+ SiS_Pr->SiS_P3cb = BaseAddr + 0x1b;251251+ SiS_Pr->SiS_P3cc = BaseAddr + 0x1c;252252+ SiS_Pr->SiS_P3cd = BaseAddr + 0x1d;253253+ SiS_Pr->SiS_P3da = BaseAddr + 0x2a;254254+ SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;255255+}256256+257257+/*********************************************/258258+/* HELPER: GetSysFlags */259259+/*********************************************/260260+261261+static void262262+SiS_GetSysFlags(struct SiS_Private *SiS_Pr)263263+{264264+ SiS_Pr->SiS_MyCR63 = 0x63;265265+}266266+267267+/*********************************************/268268+/* HELPER: Init PCI & Engines */269269+/*********************************************/270270+271271+static void272272+SiSInitPCIetc(struct SiS_Private *SiS_Pr)273273+{274274+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x20, 0xa1);275275+ /* - Enable 2D (0x40)276276+ * - Enable 3D (0x02)277277+ * - Enable 3D vertex command fetch (0x10)278278+ * - Enable 3D command parser (0x08)279279+ * - Enable 3D G/L transformation engine (0x80)280280+ */281281+ SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1E, 0xDA);282282+}283283+284284+/*********************************************/285285+/* HELPER: SET SEGMENT REGISTERS */286286+/*********************************************/287287+288288+static void289289+SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value)290290+{291291+ unsigned short temp;292292+293293+ value &= 0x00ff;294294+ temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0xf0;295295+ temp |= (value >> 4);296296+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp);297297+ temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0xf0;298298+ temp |= (value & 0x0f);299299+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp);300300+}301301+302302+static void303303+SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value)304304+{305305+ unsigned short temp;306306+307307+ value &= 0x00ff;308308+ temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0x0f;309309+ temp |= (value & 0xf0);310310+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp);311311+ temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0x0f;312312+ temp |= (value << 4);313313+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp);314314+}315315+316316+static void317317+SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value)318318+{319319+ SiS_SetSegRegLower(SiS_Pr, value);320320+ SiS_SetSegRegUpper(SiS_Pr, value);321321+}322322+323323+static void324324+SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr)325325+{326326+ SiS_SetSegmentReg(SiS_Pr, 0);327327+}328328+329329+static void330330+SiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value)331331+{332332+ unsigned short temp = value >> 8;333333+334334+ temp &= 0x07;335335+ temp |= (temp << 4);336336+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1d, temp);337337+ SiS_SetSegmentReg(SiS_Pr, value);338338+}339339+340340+static void341341+SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr)342342+{343343+ SiS_SetSegmentRegOver(SiS_Pr, 0);344344+}345345+346346+static void347347+SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr)348348+{349349+ SiS_ResetSegmentReg(SiS_Pr);350350+ SiS_ResetSegmentRegOver(SiS_Pr);351351+}352352+353353+/*********************************************/354354+/* HELPER: SearchModeID */355355+/*********************************************/356356+357357+static int358358+SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,359359+ unsigned short *ModeIdIndex)360360+{361361+ if ((*ModeNo) <= 0x13) {362362+363363+ if ((*ModeNo) != 0x03)364364+ return 0;365365+366366+ (*ModeIdIndex) = 0;367367+368368+ } else {369369+370370+ for(*ModeIdIndex = 0; ;(*ModeIdIndex)++) {371371+372372+ if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == (*ModeNo))373373+ break;374374+375375+ if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF)376376+ return 0;377377+ }378378+379379+ }380380+381381+ return 1;382382+}383383+384384+/*********************************************/385385+/* HELPER: ENABLE CRT1 */386386+/*********************************************/387387+388388+static void389389+SiS_HandleCRT1(struct SiS_Private *SiS_Pr)390390+{391391+ /* Enable CRT1 gating */392392+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, SiS_Pr->SiS_MyCR63, 0xbf);393393+}394394+395395+/*********************************************/396396+/* HELPER: GetColorDepth */397397+/*********************************************/398398+399399+static unsigned short400400+SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,401401+ unsigned short ModeIdIndex)402402+{403403+ static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8};404404+ unsigned short modeflag;405405+ short index;406406+407407+ if (ModeNo <= 0x13) {408408+ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;409409+ } else {410410+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;411411+ }412412+413413+ index = (modeflag & ModeTypeMask) - ModeEGA;414414+ if (index < 0) index = 0;415415+ return ColorDepth[index];416416+}417417+418418+/*********************************************/419419+/* HELPER: GetOffset */420420+/*********************************************/421421+422422+static unsigned short423423+SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,424424+ unsigned short ModeIdIndex, unsigned short rrti)425425+{426426+ unsigned short xres, temp, colordepth, infoflag;427427+428428+ infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;429429+ xres = SiS_Pr->SiS_RefIndex[rrti].XRes;430430+431431+ colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex);432432+433433+ temp = xres / 16;434434+435435+ if (infoflag & InterlaceMode)436436+ temp <<= 1;437437+438438+ temp *= colordepth;439439+440440+ if (xres % 16)441441+ temp += (colordepth >> 1);442442+443443+ return temp;444444+}445445+446446+/*********************************************/447447+/* SEQ */448448+/*********************************************/449449+450450+static void451451+SiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)452452+{453453+ unsigned char SRdata;454454+ int i;455455+456456+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x00, 0x03);457457+458458+ SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20;459459+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, SRdata);460460+461461+ for(i = 2; i <= 4; i++) {462462+ SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i-1];463463+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, SRdata);464464+ }465465+}466466+467467+/*********************************************/468468+/* MISC */469469+/*********************************************/470470+471471+static void472472+SiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)473473+{474474+ unsigned char Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC;475475+476476+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, Miscdata);477477+}478478+479479+/*********************************************/480480+/* CRTC */481481+/*********************************************/482482+483483+static void484484+SiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)485485+{486486+ unsigned char CRTCdata;487487+ unsigned short i;488488+489489+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, 0x11, 0x7f);490490+491491+ for(i = 0; i <= 0x18; i++) {492492+ CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];493493+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, i, CRTCdata);494494+ }495495+}496496+497497+/*********************************************/498498+/* ATT */499499+/*********************************************/500500+501501+static void502502+SiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)503503+{504504+ unsigned char ARdata;505505+ unsigned short i;506506+507507+ for(i = 0; i <= 0x13; i++) {508508+ ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i];509509+ SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);510510+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, i);511511+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, ARdata);512512+ }513513+ SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);514514+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x14);515515+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x00);516516+517517+ SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);518518+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x20);519519+ SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);520520+}521521+522522+/*********************************************/523523+/* GRC */524524+/*********************************************/525525+526526+static void527527+SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)528528+{529529+ unsigned char GRdata;530530+ unsigned short i;531531+532532+ for(i = 0; i <= 0x08; i++) {533533+ GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i];534534+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3ce, i, GRdata);535535+ }536536+537537+ if (SiS_Pr->SiS_ModeType > ModeVGA) {538538+ /* 256 color disable */539539+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3ce, 0x05, 0xBF);540540+ }541541+}542542+543543+/*********************************************/544544+/* CLEAR EXTENDED REGISTERS */545545+/*********************************************/546546+547547+static void548548+SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo)549549+{550550+ int i;551551+552552+ for(i = 0x0A; i <= 0x0E; i++) {553553+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, 0x00);554554+ }555555+556556+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x37, 0xFE);557557+}558558+559559+/*********************************************/560560+/* Get rate index */561561+/*********************************************/562562+563563+static unsigned short564564+SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,565565+ unsigned short ModeIdIndex)566566+{567567+ unsigned short rrti, i, index, temp;568568+569569+ if (ModeNo <= 0x13)570570+ return 0xFFFF;571571+572572+ index = SiS_GetReg(SiS_Pr,SiS_Pr->SiS_P3d4, 0x33) & 0x0F;573573+ if (index > 0) index--;574574+575575+ rrti = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;576576+ ModeNo = SiS_Pr->SiS_RefIndex[rrti].ModeID;577577+578578+ i = 0;579579+ do {580580+ if (SiS_Pr->SiS_RefIndex[rrti + i].ModeID != ModeNo)581581+ break;582582+583583+ temp = SiS_Pr->SiS_RefIndex[rrti + i].Ext_InfoFlag & ModeTypeMask;584584+ if (temp < SiS_Pr->SiS_ModeType)585585+ break;586586+587587+ i++;588588+ index--;589589+ } while(index != 0xFFFF);590590+591591+ i--;592592+593593+ return (rrti + i);594594+}595595+596596+/*********************************************/597597+/* SYNC */598598+/*********************************************/599599+600600+static void601601+SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short rrti)602602+{603603+ unsigned short sync = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag >> 8;604604+ sync &= 0xC0;605605+ sync |= 0x2f;606606+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, sync);607607+}608608+609609+/*********************************************/610610+/* CRTC/2 */611611+/*********************************************/612612+613613+static void614614+SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,615615+ unsigned short ModeIdIndex, unsigned short rrti)616616+{617617+ unsigned char index;618618+ unsigned short temp, i, j, modeflag;619619+620620+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4,0x11,0x7f);621621+622622+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;623623+624624+ index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRT1CRTC;625625+626626+ for(i = 0,j = 0; i <= 7; i++, j++) {627627+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,628628+ SiS_Pr->SiS_CRT1Table[index].CR[i]);629629+ }630630+ for(j = 0x10; i <= 10; i++, j++) {631631+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,632632+ SiS_Pr->SiS_CRT1Table[index].CR[i]);633633+ }634634+ for(j = 0x15; i <= 12; i++, j++) {635635+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,636636+ SiS_Pr->SiS_CRT1Table[index].CR[i]);637637+ }638638+ for(j = 0x0A; i <= 15; i++, j++) {639639+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, j,640640+ SiS_Pr->SiS_CRT1Table[index].CR[i]);641641+ }642642+643643+ temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0;644644+ SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4, 0x0E, temp);645645+646646+ temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5;647647+ if (modeflag & DoubleScanMode) temp |= 0x80;648648+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x09, 0x5F, temp);649649+650650+ if (SiS_Pr->SiS_ModeType > ModeVGA)651651+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x14, 0x4F);652652+}653653+654654+/*********************************************/655655+/* OFFSET & PITCH */656656+/*********************************************/657657+/* (partly overruled by SetPitch() in XF86) */658658+/*********************************************/659659+660660+static void661661+SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,662662+ unsigned short ModeIdIndex, unsigned short rrti)663663+{664664+ unsigned short du = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, rrti);665665+ unsigned short infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;666666+ unsigned short temp;667667+668668+ temp = (du >> 8) & 0x0f;669669+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0E, 0xF0, temp);670670+671671+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x13, (du & 0xFF));672672+673673+ if (infoflag & InterlaceMode) du >>= 1;674674+675675+ du <<= 5;676676+ temp = (du >> 8) & 0xff;677677+ if (du & 0xff) temp++;678678+ temp++;679679+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x10, temp);680680+}681681+682682+/*********************************************/683683+/* VCLK */684684+/*********************************************/685685+686686+static void687687+SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,688688+ unsigned short rrti)689689+{690690+ unsigned short index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK;691691+ unsigned short clka = SiS_Pr->SiS_VCLKData[index].SR2B;692692+ unsigned short clkb = SiS_Pr->SiS_VCLKData[index].SR2C;693693+694694+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4,0x31,0xCF);695695+696696+ SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2B,clka);697697+ SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2C,clkb);698698+ SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2D,0x01);699699+}700700+701701+/*********************************************/702702+/* FIFO */703703+/*********************************************/704704+705705+static void706706+SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo,707707+ unsigned short mi)708708+{709709+ unsigned short modeflag = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag;710710+711711+ /* disable auto-threshold */712712+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x3D, 0xFE);713713+714714+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x08, 0xAE);715715+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x09, 0xF0);716716+717717+ if (ModeNo <= 0x13)718718+ return;719719+720720+ if ((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {721721+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x08, 0x34);722722+ SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x3D, 0x01);723723+ }724724+}725725+726726+/*********************************************/727727+/* MODE REGISTERS */728728+/*********************************************/729729+730730+static void731731+SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,732732+ unsigned short rrti)733733+{734734+ unsigned short data = 0, VCLK = 0, index = 0;735735+736736+ if (ModeNo > 0x13) {737737+ index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK;738738+ VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;739739+ }740740+741741+ if (VCLK >= 166) data |= 0x0c;742742+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x32, 0xf3, data);743743+744744+ if (VCLK >= 166)745745+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1f, 0xe7);746746+747747+ /* DAC speed */748748+ data = 0x03;749749+ if (VCLK >= 260)750750+ data = 0x00;751751+ else if (VCLK >= 160)752752+ data = 0x01;753753+ else if (VCLK >= 135)754754+ data = 0x02;755755+756756+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x07, 0xF8, data);757757+}758758+759759+static void760760+SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,761761+ unsigned short ModeIdIndex, unsigned short rrti)762762+{763763+ unsigned short data, infoflag = 0, modeflag;764764+765765+ if (ModeNo <= 0x13)766766+ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;767767+ else {768768+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;769769+ infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;770770+ }771771+772772+ /* Disable DPMS */773773+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1F, 0x3F);774774+775775+ data = 0;776776+ if (ModeNo > 0x13) {777777+ if (SiS_Pr->SiS_ModeType > ModeEGA) {778778+ data |= 0x02;779779+ data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);780780+ }781781+ if (infoflag & InterlaceMode) data |= 0x20;782782+ }783783+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x06, 0xC0, data);784784+785785+ data = 0;786786+ if (infoflag & InterlaceMode) {787787+ /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */788788+ unsigned short hrs = (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x04) |789789+ ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0xc0) << 2)) - 3;790790+ unsigned short hto = (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x00) |791791+ ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0x03) << 8)) + 5;792792+ data = hrs - (hto >> 1) + 3;793793+ }794794+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x19, (data & 0xFF));795795+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x1a, 0xFC, (data >> 8));796796+797797+ if (modeflag & HalfDCLK)798798+ SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0x08);799799+800800+ data = 0;801801+ if (modeflag & LineCompareOff)802802+ data = 0x08;803803+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0F, 0xB7, data);804804+805805+ if ((SiS_Pr->SiS_ModeType == ModeEGA) && (ModeNo > 0x13))806806+ SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0F, 0x40);807807+808808+ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x31, 0xfb);809809+810810+ data = 0x60;811811+ if (SiS_Pr->SiS_ModeType != ModeText) {812812+ data ^= 0x60;813813+ if (SiS_Pr->SiS_ModeType != ModeEGA)814814+ data ^= 0xA0;815815+ }816816+ SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x21, 0x1F, data);817817+818818+ SiS_SetVCLKState(SiS_Pr, ModeNo, rrti);819819+820820+ if (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x31) & 0x40)821821+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x52, 0x2c);822822+ else823823+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x52, 0x6c);824824+}825825+826826+/*********************************************/827827+/* LOAD DAC */828828+/*********************************************/829829+830830+static void831831+SiS_WriteDAC(struct SiS_Private *SiS_Pr, unsigned long DACData,832832+ unsigned short shiftflag, unsigned short dl, unsigned short ah,833833+ unsigned short al, unsigned short dh)834834+{835835+ unsigned short d1, d2, d3;836836+837837+ switch (dl) {838838+ case 0:839839+ d1 = dh; d2 = ah; d3 = al;840840+ break;841841+ case 1:842842+ d1 = ah; d2 = al; d3 = dh;843843+ break;844844+ default:845845+ d1 = al; d2 = dh; d3 = ah;846846+ }847847+ SiS_SetRegByte(SiS_Pr, DACData, (d1 << shiftflag));848848+ SiS_SetRegByte(SiS_Pr, DACData, (d2 << shiftflag));849849+ SiS_SetRegByte(SiS_Pr, DACData, (d3 << shiftflag));850850+}851851+852852+static void853853+SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short mi)854854+{855855+ unsigned short data, data2, time, i, j, k, m, n, o;856856+ unsigned short si, di, bx, sf;857857+ unsigned long DACAddr, DACData;858858+ const unsigned char *table = NULL;859859+860860+ if (ModeNo < 0x13)861861+ data = SiS_Pr->SiS_SModeIDTable[mi].St_ModeFlag;862862+ else863863+ data = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag;864864+865865+ data &= DACInfoFlag;866866+867867+ j = time = 64;868868+ if (data == 0x00)869869+ table = SiS_MDA_DAC;870870+ else if (data == 0x08)871871+ table = SiS_CGA_DAC;872872+ else if (data == 0x10)873873+ table = SiS_EGA_DAC;874874+ else {875875+ j = 16;876876+ time = 256;877877+ table = SiS_VGA_DAC;878878+ }879879+880880+ DACAddr = SiS_Pr->SiS_P3c8;881881+ DACData = SiS_Pr->SiS_P3c9;882882+ sf = 0;883883+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c6, 0xFF);884884+885885+ SiS_SetRegByte(SiS_Pr, DACAddr, 0x00);886886+887887+ for(i = 0; i < j; i++) {888888+ data = table[i];889889+ for(k = 0; k < 3; k++) {890890+ data2 = 0;891891+ if (data & 0x01) data2 += 0x2A;892892+ if (data & 0x02) data2 += 0x15;893893+ SiS_SetRegByte(SiS_Pr, DACData, (data2 << sf));894894+ data >>= 2;895895+ }896896+ }897897+898898+ if (time == 256) {899899+ for(i = 16; i < 32; i++) {900900+ data = table[i] << sf;901901+ for(k = 0; k < 3; k++)902902+ SiS_SetRegByte(SiS_Pr, DACData, data);903903+ }904904+ si = 32;905905+ for(m = 0; m < 9; m++) {906906+ di = si;907907+ bx = si + 4;908908+ for(n = 0; n < 3; n++) {909909+ for(o = 0; o < 5; o++) {910910+ SiS_WriteDAC(SiS_Pr, DACData, sf, n,911911+ table[di], table[bx], table[si]);912912+ si++;913913+ }914914+ si -= 2;915915+ for(o = 0; o < 3; o++) {916916+ SiS_WriteDAC(SiS_Pr, DACData, sf, n,917917+ table[di], table[si], table[bx]);918918+ si--;919919+ }920920+ }921921+ si += 5;922922+ }923923+ }924924+}925925+926926+/*********************************************/927927+/* SET CRT1 REGISTER GROUP */928928+/*********************************************/929929+930930+static void931931+SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo,932932+ unsigned short ModeIdIndex)933933+{934934+ unsigned short StandTableIndex, rrti;935935+936936+ SiS_Pr->SiS_CRT1Mode = ModeNo;937937+938938+ if (ModeNo <= 0x13)939939+ StandTableIndex = 0;940940+ else941941+ StandTableIndex = 1;942942+943943+ SiS_ResetSegmentRegisters(SiS_Pr);944944+ SiS_SetSeqRegs(SiS_Pr, StandTableIndex);945945+ SiS_SetMiscRegs(SiS_Pr, StandTableIndex);946946+ SiS_SetCRTCRegs(SiS_Pr, StandTableIndex);947947+ SiS_SetATTRegs(SiS_Pr, StandTableIndex);948948+ SiS_SetGRCRegs(SiS_Pr, StandTableIndex);949949+ SiS_ClearExt1Regs(SiS_Pr, ModeNo);950950+951951+ rrti = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);952952+953953+ if (rrti != 0xFFFF) {954954+ SiS_SetCRT1Sync(SiS_Pr, rrti);955955+ SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, rrti);956956+ SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, rrti);957957+ SiS_SetCRT1VCLK(SiS_Pr, ModeNo, rrti);958958+ }959959+960960+ SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex);961961+962962+ SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, rrti);963963+964964+ SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);965965+966966+ SiS_DisplayOn(SiS_Pr);967967+}968968+969969+/*********************************************/970970+/* SiSSetMode() */971971+/*********************************************/972972+973973+int974974+SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)975975+{976976+ unsigned short ModeIdIndex;977977+ unsigned long BaseAddr = SiS_Pr->IOAddress;978978+979979+ SiSUSB_InitPtr(SiS_Pr);980980+ SiSUSBRegInit(SiS_Pr, BaseAddr);981981+ SiS_GetSysFlags(SiS_Pr);982982+983983+ if (!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex)))984984+ return 0;985985+986986+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x05, 0x86);987987+988988+ SiSInitPCIetc(SiS_Pr);989989+990990+ ModeNo &= 0x7f;991991+992992+ SiS_Pr->SiS_ModeType =993993+ SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag & ModeTypeMask;994994+995995+ SiS_Pr->SiS_SetFlag = LowModeTests;996996+997997+ /* Set mode on CRT1 */998998+ SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);999999+10001000+ SiS_HandleCRT1(SiS_Pr);10011001+10021002+ SiS_DisplayOn(SiS_Pr);10031003+ SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c6, 0xFF);10041004+10051005+ /* Store mode number */10061006+ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x34, ModeNo);10071007+10081008+ return 1;10091009+}10101010+10111011+int10121012+SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo)10131013+{10141014+ unsigned short ModeNo = 0;10151015+ int i;10161016+10171017+ SiSUSB_InitPtr(SiS_Pr);10181018+10191019+ if (VModeNo == 0x03) {10201020+10211021+ ModeNo = 0x03;10221022+10231023+ } else {10241024+10251025+ i = 0;10261026+ do {10271027+10281028+ if (SiS_Pr->SiS_EModeIDTable[i].Ext_VESAID == VModeNo) {10291029+ ModeNo = SiS_Pr->SiS_EModeIDTable[i].Ext_ModeID;10301030+ break;10311031+ }10321032+10331033+ } while (SiS_Pr->SiS_EModeIDTable[i++].Ext_ModeID != 0xff);10341034+10351035+ }10361036+10371037+ if (!ModeNo)10381038+ return 0;10391039+10401040+ return SiSUSBSetMode(SiS_Pr, ModeNo);10411041+}10421042+10431043+#endif /* INCL_SISUSB_CON */10441044+10451045+10461046+10471047+
···11+/*22+ * General structure definitions for universal mode switching modules33+ *44+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria55+ *66+ * If distributed as part of the Linux kernel, the following license terms77+ * apply:88+ *99+ * * This program is free software; you can redistribute it and/or modify1010+ * * it under the terms of the GNU General Public License as published by1111+ * * the Free Software Foundation; either version 2 of the named License,1212+ * * or any later version.1313+ * *1414+ * * This program is distributed in the hope that it will be useful,1515+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of1616+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1717+ * * GNU General Public License for more details.1818+ * *1919+ * * You should have received a copy of the GNU General Public License2020+ * * along with this program; if not, write to the Free Software2121+ * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA2222+ *2323+ * Otherwise, the following license terms apply:2424+ *2525+ * * Redistribution and use in source and binary forms, with or without2626+ * * modification, are permitted provided that the following conditions2727+ * * are met:2828+ * * 1) Redistributions of source code must retain the above copyright2929+ * * notice, this list of conditions and the following disclaimer.3030+ * * 2) Redistributions in binary form must reproduce the above copyright3131+ * * notice, this list of conditions and the following disclaimer in the3232+ * * documentation and/or other materials provided with the distribution.3333+ * * 3) The name of the author may not be used to endorse or promote products3434+ * * derived from this software without specific prior written permission.3535+ * *3636+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR3737+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES3838+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.3939+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,4040+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT4141+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,4242+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY4343+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT4444+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF4545+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.4646+ *4747+ * Author: Thomas Winischhofer <thomas@winischhofer.net>4848+ *4949+ */5050+5151+#ifndef _SISUSB_STRUCT_H_5252+#define _SISUSB_STRUCT_H_5353+5454+struct SiS_St {5555+ unsigned char St_ModeID;5656+ unsigned short St_ModeFlag;5757+ unsigned char St_StTableIndex;5858+ unsigned char St_CRT2CRTC;5959+ unsigned char St_ResInfo;6060+ unsigned char VB_StTVFlickerIndex;6161+ unsigned char VB_StTVEdgeIndex;6262+ unsigned char VB_StTVYFilterIndex;6363+ unsigned char St_PDC;6464+};6565+6666+struct SiS_StandTable6767+{6868+ unsigned char CRT_COLS;6969+ unsigned char ROWS;7070+ unsigned char CHAR_HEIGHT;7171+ unsigned short CRT_LEN;7272+ unsigned char SR[4];7373+ unsigned char MISC;7474+ unsigned char CRTC[0x19];7575+ unsigned char ATTR[0x14];7676+ unsigned char GRC[9];7777+};7878+7979+struct SiS_StResInfo_S {8080+ unsigned short HTotal;8181+ unsigned short VTotal;8282+};8383+8484+struct SiS_Ext8585+{8686+ unsigned char Ext_ModeID;8787+ unsigned short Ext_ModeFlag;8888+ unsigned short Ext_VESAID;8989+ unsigned char Ext_RESINFO;9090+ unsigned char VB_ExtTVFlickerIndex;9191+ unsigned char VB_ExtTVEdgeIndex;9292+ unsigned char VB_ExtTVYFilterIndex;9393+ unsigned char VB_ExtTVYFilterIndexROM661;9494+ unsigned char REFindex;9595+ char ROMMODEIDX661;9696+};9797+9898+struct SiS_Ext29999+{100100+ unsigned short Ext_InfoFlag;101101+ unsigned char Ext_CRT1CRTC;102102+ unsigned char Ext_CRTVCLK;103103+ unsigned char Ext_CRT2CRTC;104104+ unsigned char Ext_CRT2CRTC_NS;105105+ unsigned char ModeID;106106+ unsigned short XRes;107107+ unsigned short YRes;108108+ unsigned char Ext_PDC;109109+ unsigned char Ext_FakeCRT2CRTC;110110+ unsigned char Ext_FakeCRT2Clk;111111+};112112+113113+struct SiS_CRT1Table114114+{115115+ unsigned char CR[17];116116+};117117+118118+struct SiS_VCLKData119119+{120120+ unsigned char SR2B,SR2C;121121+ unsigned short CLOCK;122122+};123123+124124+struct SiS_ModeResInfo125125+{126126+ unsigned short HTotal;127127+ unsigned short VTotal;128128+ unsigned char XChar;129129+ unsigned char YChar;130130+};131131+132132+struct SiS_Private133133+{134134+ void *sisusb;135135+136136+ unsigned long IOAddress;137137+138138+ unsigned long SiS_P3c4;139139+ unsigned long SiS_P3d4;140140+ unsigned long SiS_P3c0;141141+ unsigned long SiS_P3ce;142142+ unsigned long SiS_P3c2;143143+ unsigned long SiS_P3ca;144144+ unsigned long SiS_P3c6;145145+ unsigned long SiS_P3c7;146146+ unsigned long SiS_P3c8;147147+ unsigned long SiS_P3c9;148148+ unsigned long SiS_P3cb;149149+ unsigned long SiS_P3cc;150150+ unsigned long SiS_P3cd;151151+ unsigned long SiS_P3da;152152+ unsigned long SiS_Part1Port;153153+154154+ unsigned char SiS_MyCR63;155155+ unsigned short SiS_CRT1Mode;156156+ unsigned short SiS_ModeType;157157+ unsigned short SiS_SetFlag;158158+159159+ const struct SiS_StandTable *SiS_StandTable;160160+ const struct SiS_St *SiS_SModeIDTable;161161+ const struct SiS_Ext *SiS_EModeIDTable;162162+ const struct SiS_Ext2 *SiS_RefIndex;163163+ const struct SiS_CRT1Table *SiS_CRT1Table;164164+ struct SiS_VCLKData *SiS_VCLKData;165165+ const struct SiS_ModeResInfo *SiS_ModeResInfo;166166+};167167+168168+#endif169169+
+272-125
drivers/usb/misc/uss720.c
···33/*44 * uss720.c -- USS720 USB Parport Cable.55 *66- * Copyright (C) 199977- * Thomas Sailer (sailer@ife.ee.ethz.ch)66+ * Copyright (C) 1999, 200577+ * Thomas Sailer (t.sailer@alumni.ethz.ch)88 *99 * This program is free software; you can redistribute it and/or modify1010 * it under the terms of the GNU General Public License as published by···2323 * Based on parport_pc.c2424 *2525 * History:2626- * 0.1 04.08.99 Created2727- * 0.2 07.08.99 Some fixes mainly suggested by Tim Waugh2828- * Interrupt handling currently disabled because2929- * usb_request_irq crashes somewhere within ohci.c3030- * for no apparent reason (that is for me, anyway)3131- * ECP currently untested3232- * 0.3 10.08.99 fixing merge errors3333- * 0.4 13.08.99 Added Vendor/Product ID of Brad Hard's cable3434- * 0.5 20.09.99 usb_control_msg wrapper used3535- * Nov01.00 usb_device_table support by Adam J. Richter3636- * 08.04.01 Identify version on module load. gb2626+ * 0.1 04.08.1999 Created2727+ * 0.2 07.08.1999 Some fixes mainly suggested by Tim Waugh2828+ * Interrupt handling currently disabled because2929+ * usb_request_irq crashes somewhere within ohci.c3030+ * for no apparent reason (that is for me, anyway)3131+ * ECP currently untested3232+ * 0.3 10.08.1999 fixing merge errors3333+ * 0.4 13.08.1999 Added Vendor/Product ID of Brad Hard's cable3434+ * 0.5 20.09.1999 usb_control_msg wrapper used3535+ * Nov01.2000 usb_device_table support by Adam J. Richter3636+ * 08.04.2001 Identify version on module load. gb3737+ * 0.6 02.09.2005 Fix "scheduling in interrupt" problem by making save/restore3838+ * context asynchronous3739 *3840 */39414042/*****************************************************************************/4343+4444+#define DEBUG41454246#include <linux/module.h>4347#include <linux/socket.h>···4945#include <linux/init.h>5046#include <linux/usb.h>5147#include <linux/delay.h>4848+#include <linux/completion.h>4949+#include <linux/kref.h>52505351/*5452 * Version Information5553 */5656-#define DRIVER_VERSION "v0.5"5757-#define DRIVER_AUTHOR "Thomas M. Sailer, sailer@ife.ee.ethz.ch"5454+#define DRIVER_VERSION "v0.6"5555+#define DRIVER_AUTHOR "Thomas M. Sailer, t.sailer@alumni.ethz.ch"5856#define DRIVER_DESC "USB Parport Cable driver for Cables using the Lucent Technologies USS720 Chip"59576058/* --------------------------------------------------------------------- */61596260struct parport_uss720_private {6361 struct usb_device *usbdev;6464- void *irqhandle;6565- unsigned int irqpipe;6666- unsigned char reg[7]; /* USB registers */6262+ struct parport *pp;6363+ struct kref ref_count;6464+ __u8 reg[7]; /* USB registers */6565+ struct list_head asynclist;6666+ spinlock_t asynclock;6767+};6868+6969+struct uss720_async_request {7070+ struct parport_uss720_private *priv;7171+ struct kref ref_count;7272+ struct list_head asynclist;7373+ struct completion compl;7474+ struct urb *urb;7575+ struct usb_ctrlrequest dr;7676+ __u8 reg[7];6777};68786979/* --------------------------------------------------------------------- */70807171-static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val)8181+static void destroy_priv(struct kref *kref)7282{7373- struct parport_uss720_private *priv = pp->private_data;7474- struct usb_device *usbdev = priv->usbdev;8383+ struct parport_uss720_private *priv = container_of(kref, struct parport_uss720_private, ref_count);8484+8585+ usb_put_dev(priv->usbdev);8686+ kfree(priv);8787+ dbg("destroying priv datastructure");8888+}8989+9090+static void destroy_async(struct kref *kref)9191+{9292+ struct uss720_async_request *rq = container_of(kref, struct uss720_async_request, ref_count);9393+ struct parport_uss720_private *priv = rq->priv;9494+ unsigned long flags;9595+9696+ if (likely(rq->urb))9797+ usb_free_urb(rq->urb);9898+ spin_lock_irqsave(&priv->asynclock, flags);9999+ list_del_init(&rq->asynclist);100100+ spin_unlock_irqrestore(&priv->asynclock, flags);101101+ kfree(rq);102102+ kref_put(&priv->ref_count, destroy_priv);103103+}104104+105105+/* --------------------------------------------------------------------- */106106+107107+static void async_complete(struct urb *urb, struct pt_regs *ptregs)108108+{109109+ struct uss720_async_request *rq;110110+ struct parport *pp;111111+ struct parport_uss720_private *priv;112112+113113+ rq = urb->context;114114+ priv = rq->priv;115115+ pp = priv->pp;116116+ if (urb->status) {117117+ err("async_complete: urb error %d", urb->status);118118+ } else if (rq->dr.bRequest == 3) {119119+ memcpy(priv->reg, rq->reg, sizeof(priv->reg));120120+#if 0121121+ dbg("async_complete regs %02x %02x %02x %02x %02x %02x %02x",122122+ (unsigned int)priv->reg[0], (unsigned int)priv->reg[1], (unsigned int)priv->reg[2],123123+ (unsigned int)priv->reg[3], (unsigned int)priv->reg[4], (unsigned int)priv->reg[5],124124+ (unsigned int)priv->reg[6]);125125+#endif126126+ /* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */127127+ if (rq->reg[2] & rq->reg[1] & 0x10 && pp)128128+ parport_generic_irq(0, pp, NULL);129129+ }130130+ complete(&rq->compl);131131+ kref_put(&rq->ref_count, destroy_async);132132+}133133+134134+static struct uss720_async_request *submit_async_request(struct parport_uss720_private *priv,135135+ __u8 request, __u8 requesttype, __u16 value, __u16 index,136136+ unsigned int mem_flags)137137+{138138+ struct usb_device *usbdev;139139+ struct uss720_async_request *rq;140140+ unsigned long flags;141141+ int ret;142142+143143+ if (!priv)144144+ return NULL;145145+ usbdev = priv->usbdev;146146+ if (!usbdev)147147+ return NULL;148148+ rq = kmalloc(sizeof(struct uss720_async_request), mem_flags);149149+ if (!rq) {150150+ err("submit_async_request out of memory");151151+ return NULL;152152+ }153153+ kref_init(&rq->ref_count);154154+ INIT_LIST_HEAD(&rq->asynclist);155155+ init_completion(&rq->compl);156156+ kref_get(&priv->ref_count);157157+ rq->priv = priv;158158+ rq->urb = usb_alloc_urb(0, mem_flags);159159+ if (!rq->urb) {160160+ kref_put(&rq->ref_count, destroy_async);161161+ err("submit_async_request out of memory");162162+ return NULL;163163+ }164164+ rq->dr.bRequestType = requesttype;165165+ rq->dr.bRequest = request;166166+ rq->dr.wValue = cpu_to_le16(value);167167+ rq->dr.wIndex = cpu_to_le16(index);168168+ rq->dr.wLength = cpu_to_le16((request == 3) ? sizeof(rq->reg) : 0);169169+ usb_fill_control_urb(rq->urb, usbdev, (requesttype & 0x80) ? usb_rcvctrlpipe(usbdev, 0) : usb_sndctrlpipe(usbdev, 0),170170+ (unsigned char *)&rq->dr,171171+ (request == 3) ? rq->reg : NULL, (request == 3) ? sizeof(rq->reg) : 0, async_complete, rq);172172+ /* rq->urb->transfer_flags |= URB_ASYNC_UNLINK; */173173+ spin_lock_irqsave(&priv->asynclock, flags);174174+ list_add_tail(&rq->asynclist, &priv->asynclist);175175+ spin_unlock_irqrestore(&priv->asynclock, flags);176176+ ret = usb_submit_urb(rq->urb, mem_flags);177177+ if (!ret) {178178+ kref_get(&rq->ref_count);179179+ return rq;180180+ }181181+ kref_put(&rq->ref_count, destroy_async);182182+ err("submit_async_request submit_urb failed with %d", ret);183183+ return NULL;184184+}185185+186186+static unsigned int kill_all_async_requests_priv(struct parport_uss720_private *priv)187187+{188188+ struct uss720_async_request *rq;189189+ unsigned long flags;190190+ unsigned int ret = 0;191191+192192+ spin_lock_irqsave(&priv->asynclock, flags);193193+ list_for_each_entry(rq, &priv->asynclist, asynclist) {194194+ usb_unlink_urb(rq->urb);195195+ ret++;196196+ }197197+ spin_unlock_irqrestore(&priv->asynclock, flags);198198+ return ret;199199+}200200+201201+/* --------------------------------------------------------------------- */202202+203203+static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val, unsigned int mem_flags)204204+{205205+ struct parport_uss720_private *priv;206206+ struct uss720_async_request *rq;75207 static const unsigned char regindex[9] = {76208 4, 0, 1, 5, 5, 0, 2, 3, 677209 };78210 int ret;792118080- if (!usbdev)8181- return -1;8282- ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev,0), 3, 0xc0, ((unsigned int)reg) << 8, 0, priv->reg, 7, 1000);8383- if (ret != 7) {8484- printk(KERN_DEBUG "uss720: get_1284_register(%d) failed, status 0x%x expected 7\n",8585- (unsigned int)reg, ret);8686- ret = -1;8787- } else {8888-#if 08989- printk(KERN_DEBUG "uss720: get_1284_register(%d) return %02x %02x %02x %02x %02x %02x %02x\n",9090- (unsigned int)reg, (unsigned int)priv->reg[0], (unsigned int)priv->reg[1],9191- (unsigned int)priv->reg[2], (unsigned int)priv->reg[3], (unsigned int)priv->reg[4],9292- (unsigned int)priv->reg[5], (unsigned int)priv->reg[6]);9393-#endif9494- /* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */9595- if (priv->reg[2] & priv->reg[1] & 0x10)9696- parport_generic_irq(0, pp, NULL);9797- ret = 0;212212+ if (!pp)213213+ return -EIO;214214+ priv = pp->private_data;215215+ rq = submit_async_request(priv, 3, 0xc0, ((unsigned int)reg) << 8, 0, mem_flags);216216+ if (!rq) {217217+ err("get_1284_register(%u) failed", (unsigned int)reg);218218+ return -EIO;98219 }9999- if (val)220220+ if (!val) {221221+ kref_put(&rq->ref_count, destroy_async);222222+ return 0;223223+ }224224+ if (wait_for_completion_timeout(&rq->compl, HZ)) {225225+ ret = rq->urb->status;100226 *val = priv->reg[(reg >= 9) ? 0 : regindex[reg]];101101- return ret;227227+ if (ret)228228+ warn("get_1284_register: usb error %d", ret);229229+ kref_put(&rq->ref_count, destroy_async);230230+ return ret;231231+ }232232+ warn("get_1284_register timeout");233233+ kill_all_async_requests_priv(priv);234234+ return -EIO;102235}103236104104-static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val)237237+static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val, unsigned int mem_flags)105238{106106- struct parport_uss720_private *priv = pp->private_data;107107- struct usb_device *usbdev = priv->usbdev;108108- int ret;239239+ struct parport_uss720_private *priv;240240+ struct uss720_async_request *rq;109241110110- if (!usbdev)111111- return -1;112112- ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev,0), 4, 0x40, (((unsigned int)reg) << 8) | val, 0, NULL, 0, 1000);113113- if (ret) {114114- printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x) failed, status 0x%x\n", 115115- (unsigned int)reg, (unsigned int)val, ret);116116- } else {117117-#if 0118118- printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x)\n", 119119- (unsigned int)reg, (unsigned int)val);120120-#endif242242+ if (!pp)243243+ return -EIO;244244+ priv = pp->private_data;245245+ rq = submit_async_request(priv, 4, 0x40, (((unsigned int)reg) << 8) | val, 0, mem_flags);246246+ if (!rq) {247247+ err("set_1284_register(%u,%u) failed", (unsigned int)reg, (unsigned int)val);248248+ return -EIO;121249 }122122- return ret;250250+ kref_put(&rq->ref_count, destroy_async);251251+ return 0;123252}124253125254/* --------------------------------------------------------------------- */···269132{270133 struct parport_uss720_private *priv = pp->private_data;271134 int mode;135135+ __u8 reg;272136273273- if (get_1284_register(pp, 6, NULL))137137+ if (get_1284_register(pp, 6, ®, GFP_KERNEL))274138 return -EIO;275139 /* Bits <7:5> contain the mode. */276140 mode = (priv->reg[2] >> 5) & 0x7;···291153 case ECR_ECP: /* ECP Parallel Port mode */292154 /* Poll slowly. */293155 for (;;) {294294- if (get_1284_register(pp, 6, NULL))156156+ if (get_1284_register(pp, 6, ®, GFP_KERNEL))295157 return -EIO;296158 if (priv->reg[2] & 0x01)297159 break;···305167 }306168 }307169 /* Set the mode. */308308- if (set_1284_register(pp, 6, m << 5))170170+ if (set_1284_register(pp, 6, m << 5, GFP_KERNEL))171171+ return -EIO;172172+ if (get_1284_register(pp, 6, ®, GFP_KERNEL))309173 return -EIO;310174 return 0;311175}···319179{320180 unsigned char stat;321181322322- if (get_1284_register(pp, 1, &stat))182182+ if (get_1284_register(pp, 1, &stat, GFP_KERNEL))323183 return 1;324184 return stat & 1;325185}···345205346206static void parport_uss720_write_data(struct parport *pp, unsigned char d)347207{348348- set_1284_register(pp, 0, d);208208+ set_1284_register(pp, 0, d, GFP_KERNEL);349209}350210351211static unsigned char parport_uss720_read_data(struct parport *pp)352212{353213 unsigned char ret;354214355355- if (get_1284_register(pp, 0, &ret))215215+ if (get_1284_register(pp, 0, &ret, GFP_KERNEL))356216 return 0;357217 return ret;358218}···362222 struct parport_uss720_private *priv = pp->private_data; 363223364224 d = (d & 0xf) | (priv->reg[1] & 0xf0);365365- if (set_1284_register(pp, 2, d))225225+ if (set_1284_register(pp, 2, d, GFP_KERNEL))366226 return;367227 priv->reg[1] = d;368228}···381241 mask &= 0x0f;382242 val &= 0x0f;383243 d = (priv->reg[1] & (~mask)) ^ val;384384- if (set_1284_register(pp, 2, d))244244+ if (set_1284_register(pp, 2, d, GFP_KERNEL))385245 return 0;386246 priv->reg[1] = d;387247 return d & 0xf;···391251{392252 unsigned char ret;393253394394- if (get_1284_register(pp, 1, &ret))254254+ if (get_1284_register(pp, 1, &ret, GFP_KERNEL))395255 return 0;396256 return ret & 0xf8;397257}···402262 unsigned char d;403263404264 d = priv->reg[1] & ~0x10;405405- if (set_1284_register(pp, 2, d))265265+ if (set_1284_register(pp, 2, d, GFP_KERNEL))406266 return;407267 priv->reg[1] = d;408268}···413273 unsigned char d;414274415275 d = priv->reg[1] | 0x10;416416- if (set_1284_register(pp, 2, d))276276+ if (set_1284_register(pp, 2, d, GFP_KERNEL))417277 return;418278 priv->reg[1] = d;419279}···424284 unsigned char d;425285426286 d = priv->reg[1] & ~0x20;427427- if (set_1284_register(pp, 2, d))287287+ if (set_1284_register(pp, 2, d, GFP_KERNEL))428288 return;429289 priv->reg[1] = d;430290}···435295 unsigned char d;436296437297 d = priv->reg[1] | 0x20;438438- if (set_1284_register(pp, 2, d))298298+ if (set_1284_register(pp, 2, d, GFP_KERNEL))439299 return;440300 priv->reg[1] = d;441301}···450310{451311 struct parport_uss720_private *priv = pp->private_data; 452312453453- if (get_1284_register(pp, 2, NULL))313313+#if 0314314+ if (get_1284_register(pp, 2, NULL, GFP_ATOMIC))454315 return;316316+#endif455317 s->u.pc.ctr = priv->reg[1];456318 s->u.pc.ecr = priv->reg[2];457319}458320459321static void parport_uss720_restore_state(struct parport *pp, struct parport_state *s)460322{461461- set_1284_register(pp, 2, s->u.pc.ctr);462462- set_1284_register(pp, 6, s->u.pc.ecr);463463- get_1284_register(pp, 2, NULL);323323+ struct parport_uss720_private *priv = pp->private_data;324324+325325+ set_1284_register(pp, 2, s->u.pc.ctr, GFP_ATOMIC);326326+ set_1284_register(pp, 6, s->u.pc.ecr, GFP_ATOMIC);327327+ get_1284_register(pp, 2, NULL, GFP_ATOMIC);328328+ priv->reg[1] = s->u.pc.ctr;329329+ priv->reg[2] = s->u.pc.ecr;464330}465331466332static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t length, int flags)···477331 if (change_mode(pp, ECR_EPP))478332 return 0;479333 for (; got < length; got++) {480480- if (get_1284_register(pp, 4, (char *)buf))334334+ if (get_1284_register(pp, 4, (char *)buf, GFP_KERNEL))481335 break;482336 buf++;483337 if (priv->reg[0] & 0x01) {···498352 if (change_mode(pp, ECR_EPP))499353 return 0;500354 for (; written < length; written++) {501501- if (set_1284_register(pp, 4, (char *)buf))355355+ if (set_1284_register(pp, 4, (char *)buf, GFP_KERNEL))502356 break;503357 ((char*)buf)++;504504- if (get_1284_register(pp, 1, NULL))358358+ if (get_1284_register(pp, 1, NULL, GFP_KERNEL))505359 break;506360 if (priv->reg[0] & 0x01) {507361 clear_epp_timeout(pp);···536390 if (change_mode(pp, ECR_EPP))537391 return 0;538392 for (; got < length; got++) {539539- if (get_1284_register(pp, 3, (char *)buf))393393+ if (get_1284_register(pp, 3, (char *)buf, GFP_KERNEL))540394 break;541395 buf++;542396 if (priv->reg[0] & 0x01) {···556410 if (change_mode(pp, ECR_EPP))557411 return 0;558412 for (; written < length; written++) {559559- if (set_1284_register(pp, 3, *(char *)buf))413413+ if (set_1284_register(pp, 3, *(char *)buf, GFP_KERNEL))560414 break;561415 buf++;562562- if (get_1284_register(pp, 1, NULL))416416+ if (get_1284_register(pp, 1, NULL, GFP_KERNEL))563417 break;564418 if (priv->reg[0] & 0x01) {565419 clear_epp_timeout(pp);···613467 if (change_mode(pp, ECR_ECP))614468 return 0;615469 for (; written < len; written++) {616616- if (set_1284_register(pp, 5, *(char *)buffer))470470+ if (set_1284_register(pp, 5, *(char *)buffer, GFP_KERNEL))617471 break;618472 buffer++;619473 }···682536static int uss720_probe(struct usb_interface *intf,683537 const struct usb_device_id *id)684538{685685- struct usb_device *usbdev = interface_to_usbdev(intf);539539+ struct usb_device *usbdev = usb_get_dev(interface_to_usbdev(intf));686540 struct usb_host_interface *interface;687541 struct usb_host_endpoint *endpoint;688542 struct parport_uss720_private *priv;689543 struct parport *pp;544544+ unsigned char reg;690545 int i;691546692692- printk(KERN_DEBUG "uss720: probe: vendor id 0x%x, device id 0x%x\n",693693- le16_to_cpu(usbdev->descriptor.idVendor),694694- le16_to_cpu(usbdev->descriptor.idProduct));547547+ dbg("probe: vendor id 0x%x, device id 0x%x\n",548548+ le16_to_cpu(usbdev->descriptor.idVendor),549549+ le16_to_cpu(usbdev->descriptor.idProduct));695550696551 /* our known interfaces have 3 alternate settings */697697- if (intf->num_altsetting != 3)552552+ if (intf->num_altsetting != 3) {553553+ usb_put_dev(usbdev);698554 return -ENODEV;699699-555555+ }700556 i = usb_set_interface(usbdev, intf->altsetting->desc.bInterfaceNumber, 2);701701- printk(KERN_DEBUG "uss720: set inteface result %d\n", i);557557+ dbg("set inteface result %d", i);702558703559 interface = intf->cur_altsetting;704560705561 /*706562 * Allocate parport interface 707563 */708708- printk(KERN_INFO "uss720: (C) 1999 by Thomas Sailer, <sailer@ife.ee.ethz.ch>\n");709709-710710- if (!(priv = kmalloc(sizeof(struct parport_uss720_private), GFP_KERNEL)))564564+ if (!(priv = kcalloc(sizeof(struct parport_uss720_private), 1, GFP_KERNEL))) {565565+ usb_put_dev(usbdev);711566 return -ENOMEM;567567+ }568568+ priv->pp = NULL;569569+ priv->usbdev = usbdev;570570+ kref_init(&priv->ref_count);571571+ spin_lock_init(&priv->asynclock);572572+ INIT_LIST_HEAD(&priv->asynclist);712573 if (!(pp = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &parport_uss720_ops))) {713713- printk(KERN_WARNING "usb-uss720: could not register parport\n");574574+ warn("could not register parport");714575 goto probe_abort;715576 }716577578578+ priv->pp = pp;717579 pp->private_data = priv;718718- priv->usbdev = usbdev;719580 pp->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP | PARPORT_MODE_ECP | PARPORT_MODE_COMPAT;720581721582 /* set the USS720 control register to manual mode, no ECP compression, enable all ints */722722- set_1284_register(pp, 7, 0x00);723723- set_1284_register(pp, 6, 0x30); /* PS/2 mode */724724- set_1284_register(pp, 2, 0x0c);583583+ set_1284_register(pp, 7, 0x00, GFP_KERNEL);584584+ set_1284_register(pp, 6, 0x30, GFP_KERNEL); /* PS/2 mode */585585+ set_1284_register(pp, 2, 0x0c, GFP_KERNEL);725586 /* debugging */726726- get_1284_register(pp, 0, NULL);727727- printk("uss720: reg: %02x %02x %02x %02x %02x %02x %02x\n",728728- priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]);587587+ get_1284_register(pp, 0, ®, GFP_KERNEL);588588+ dbg("reg: %02x %02x %02x %02x %02x %02x %02x",589589+ priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]);729590730591 endpoint = &interface->endpoint[2];731731- printk(KERN_DEBUG "uss720: epaddr %d interval %d\n", endpoint->desc.bEndpointAddress, endpoint->desc.bInterval);732732-#if 0733733- priv->irqpipe = usb_rcvctrlpipe(usbdev, endpoint->bEndpointAddress);734734- i = usb_request_irq(usbdev, priv->irqpipe,735735- uss720_irq, endpoint->bInterval,736736- pp, &priv->irqhandle);737737- if (i) {738738- printk (KERN_WARNING "usb-uss720: usb_request_irq failed (0x%x)\n", i);739739- goto probe_abort_port;740740- }741741-#endif592592+ dbg("epaddr %d interval %d", endpoint->desc.bEndpointAddress, endpoint->desc.bInterval);742593 parport_announce_port(pp);743594744744- usb_set_intfdata (intf, pp);595595+ usb_set_intfdata(intf, pp);745596 return 0;746597747747-#if 0748748-probe_abort_port:749749- parport_put_port(pp);750750-#endif751598probe_abort:752752- kfree(priv);599599+ kill_all_async_requests_priv(priv);600600+ kref_put(&priv->ref_count, destroy_priv);753601 return -ENODEV;754602}755603756604static void uss720_disconnect(struct usb_interface *intf)757605{758758- struct parport *pp = usb_get_intfdata (intf);606606+ struct parport *pp = usb_get_intfdata(intf);759607 struct parport_uss720_private *priv;608608+ struct usb_device *usbdev;760609761761- usb_set_intfdata (intf, NULL);610610+ dbg("disconnect");611611+ usb_set_intfdata(intf, NULL);762612 if (pp) {763613 priv = pp->private_data;764764- parport_remove_port(pp);765765-#if 0766766- usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe);767767-#endif614614+ usbdev = priv->usbdev;768615 priv->usbdev = NULL;616616+ priv->pp = NULL;617617+ dbg("parport_remove_port");618618+ parport_remove_port(pp);769619 parport_put_port(pp);770770- kfree(priv);620620+ kill_all_async_requests_priv(priv);621621+ kref_put(&priv->ref_count, destroy_priv);771622 }623623+ dbg("disconnect done");772624}773625774626/* table of cables that work through this driver */···791647792648/* --------------------------------------------------------------------- */793649794794-MODULE_AUTHOR( DRIVER_AUTHOR );795795-MODULE_DESCRIPTION( DRIVER_DESC );650650+MODULE_AUTHOR(DRIVER_AUTHOR);651651+MODULE_DESCRIPTION(DRIVER_DESC);796652MODULE_LICENSE("GPL");797653798654static int __init uss720_init(void)···803659 goto out;804660805661 info(DRIVER_VERSION ":" DRIVER_DESC);662662+ info("NOTE: this is a special purpose driver to allow nonstandard");663663+ info("protocols (eg. bitbang) over USS720 usb to parallel cables");664664+ info("If you just want to connect to a printer, use usblp instead");806665out:807666 return retval;808667}
+1-1
drivers/usb/mon/mon_text.c
···7979 return '-';80808181 if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)8282- return 'D';8282+ return mon_dmapeek(ep->setup, urb->setup_dma, SETUP_MAX);8383 if (urb->setup_packet == NULL)8484 return 'Z'; /* '0' would be not as pretty. */8585
···914914 unsigned interfaces;915915916916 /* Assume it is not the original SIO device for now. */917917- priv->baud_base = 48000000 / 16;917917+ priv->baud_base = 48000000 / 2;918918 priv->write_offset = 0;919919920920 version = le16_to_cpu(udev->descriptor.bcdDevice);
···227227 ***********************************************************************/228228229229/* Command timeout and abort */230230-/* This is always called with scsi_lock(host) held */231230static int command_abort(struct scsi_cmnd *srb)232231{233232 struct us_data *us = host_to_us(srb->device->host);234233235234 US_DEBUGP("%s called\n", __FUNCTION__);236235236236+ /* us->srb together with the TIMED_OUT, RESETTING, and ABORTING237237+ * bits are protected by the host lock. */238238+ scsi_lock(us_to_host(us));239239+237240 /* Is this command still active? */238241 if (us->srb != srb) {242242+ scsi_unlock(us_to_host(us));239243 US_DEBUGP ("-- nothing to abort\n");240244 return FAILED;241245 }242246243247 /* Set the TIMED_OUT bit. Also set the ABORTING bit, but only if244248 * a device reset isn't already in progress (to avoid interfering245245- * with the reset). To prevent races with auto-reset, we must246246- * stop any ongoing USB transfers while still holding the host247247- * lock. */249249+ * with the reset). Note that we must retain the host lock while250250+ * calling usb_stor_stop_transport(); otherwise it might interfere251251+ * with an auto-reset that begins as soon as we release the lock. */248252 set_bit(US_FLIDX_TIMED_OUT, &us->flags);249253 if (!test_bit(US_FLIDX_RESETTING, &us->flags)) {250254 set_bit(US_FLIDX_ABORTING, &us->flags);251255 usb_stor_stop_transport(us);252256 }257257+ scsi_unlock(us_to_host(us));253258254259 /* Wait for the aborted command to finish */255260 wait_for_completion(&us->notify);256256-257257- /* Reacquire the lock and allow USB transfers to resume */258258- clear_bit(US_FLIDX_ABORTING, &us->flags);259259- clear_bit(US_FLIDX_TIMED_OUT, &us->flags);260261 return SUCCESS;261262}262263263264/* This invokes the transport reset mechanism to reset the state of the264265 * device */265265-/* This is always called with scsi_lock(host) held */266266static int device_reset(struct scsi_cmnd *srb)267267{268268 struct us_data *us = host_to_us(srb->device->host);···279279}280280281281/* Simulate a SCSI bus reset by resetting the device's USB port. */282282-/* This is always called with scsi_lock(host) held */283282static int bus_reset(struct scsi_cmnd *srb)284283{285284 struct us_data *us = host_to_us(srb->device->host);···290291 result = usb_stor_port_reset(us);291292 up(&(us->dev_semaphore));292293293293- /* lock the host for the return */294294 return result < 0 ? FAILED : SUCCESS;295295}296296
+35
drivers/usb/storage/unusual_devs.h
···8686 US_SC_DEVICE, US_PR_DEVICE, NULL,8787 US_FL_IGNORE_RESIDUE ),88888989+/* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net>9090+ * and Olaf Hering <olh@suse.de> (different bcd's, same vendor/product)9191+ * for USB floppies that need the SINGLE_LUN enforcement.9292+ */9393+UNUSUAL_DEV( 0x0409, 0x0040, 0x0000, 0x9999,9494+ "NEC",9595+ "NEC USB UF000x",9696+ US_SC_DEVICE, US_PR_DEVICE, NULL,9797+ US_FL_SINGLE_LUN ),9898+8999/* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>90100 * Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message91101 * always fails and confuses drive.···10696 US_SC_DEVICE, US_PR_DEVICE, NULL,10797 US_FL_FIX_INQUIRY ),108989999+/* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */100100+UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210,101101+ "SMSC",102102+ "FDC GOLD-2.30",103103+ US_SC_DEVICE, US_PR_DEVICE, NULL,104104+ US_FL_SINGLE_LUN ),105105+109106#ifdef CONFIG_USB_STORAGE_DPCM110107UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100,111108 "Microtech",112109 "CameraMate (DPCM_USB)",113110 US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ),114111#endif112112+113113+/*114114+ * Pete Zaitcev <zaitcev@yahoo.com>, from Patrick C. F. Ernzer, bz#162559.115115+ * The key does not actually break, but it returns zero sense which116116+ * makes our SCSI stack to print confusing messages.117117+ */118118+UNUSUAL_DEV( 0x0457, 0x0150, 0x0100, 0x0100,119119+ "USBest Technology", /* sold by Transcend */120120+ "USB Mass Storage Device",121121+ US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),122122+123123+/* Patch submitted by Daniel Drake <dsd@gentoo.org>124124+ * Device reports nonsense bInterfaceProtocol 6 when connected over USB2 */125125+UNUSUAL_DEV( 0x0451, 0x5416, 0x0100, 0x0100,126126+ "Neuros Audio",127127+ "USB 2.0 HD 2.5",128128+ US_SC_DEVICE, US_PR_BULK, NULL,129129+ US_FL_NEED_OVERRIDE ),115130116131/* Patch submitted by Philipp Friedrich <philipp@void.at> */117132UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100,
+8-3
drivers/usb/storage/usb.c
···392392 /* If an abort request was received we need to signal that393393 * the abort has finished. The proper test for this is394394 * the TIMED_OUT flag, not srb->result == DID_ABORT, because395395- * a timeout/abort request might be received after all the396396- * USB processing was complete. */397397- if (test_bit(US_FLIDX_TIMED_OUT, &us->flags))395395+ * the timeout might have occurred after the command had396396+ * already completed with a different result code. */397397+ if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {398398 complete(&(us->notify));399399+400400+ /* Allow USB transfers to resume */401401+ clear_bit(US_FLIDX_ABORTING, &us->flags);402402+ clear_bit(US_FLIDX_TIMED_OUT, &us->flags);403403+ }399404400405 /* finished working on this command */401406 us->srb = NULL;
+1-1
drivers/video/console/Kconfig
···137137138138config FONT_8x16139139 bool "VGA 8x16 font" if FONTS140140- depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y140140+ depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y || USB_SISUSBVGA_CON141141 default y if !SPARC32 && !SPARC64 && !FONTS142142 help143143 This is the "high resolution" font for the VGA frame buffer (the one
+4
drivers/video/console/Makefile
···33333434obj-$(CONFIG_FB_STI) += sticore.o font.o35353636+ifeq ($(CONFIG_USB_SISUSBVGA_CON),y)3737+obj-$(CONFIG_USB_SISUSBVGA) += font.o3838+endif3939+3640# Targets that kbuild needs to know about3741targets := promcon_tbl.c3842