aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/aoe/aoe.h12
-rw-r--r--drivers/char/watchdog/Kconfig9
-rw-r--r--drivers/char/watchdog/Makefile1
-rw-r--r--drivers/char/watchdog/mpcore_wdt.c434
-rw-r--r--drivers/hwmon/Kconfig17
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/hdaps.c739
-rw-r--r--drivers/hwmon/sis5595.c5
-rw-r--r--drivers/hwmon/smsc47m1.c4
-rw-r--r--drivers/hwmon/via686a.c5
-rw-r--r--drivers/hwmon/w83627hf.c14
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c5
-rw-r--r--drivers/mmc/wbsd.c441
-rw-r--r--drivers/mmc/wbsd.h23
-rw-r--r--drivers/mtd/maps/uclinux.c13
-rw-r--r--drivers/net/Kconfig13
-rw-r--r--drivers/net/fec.c478
-rw-r--r--drivers/net/fec.h7
-rw-r--r--drivers/serial/mcfserial.c13
-rw-r--r--drivers/usb/class/audio.c12
-rw-r--r--drivers/usb/core/hcd.c3
-rw-r--r--drivers/usb/core/hub.c11
-rw-r--r--drivers/usb/gadget/inode.c1
-rw-r--r--drivers/usb/host/ehci-hcd.c28
-rw-r--r--drivers/usb/host/ehci-hub.c27
-rw-r--r--drivers/usb/host/ehci.h1
-rw-r--r--drivers/usb/host/ohci-dbg.c9
-rw-r--r--drivers/usb/host/ohci-hcd.c14
-rw-r--r--drivers/usb/host/ohci-hub.c22
-rw-r--r--drivers/usb/host/ohci-pxa27x.c48
-rw-r--r--drivers/usb/host/ohci.h1
-rw-r--r--drivers/usb/host/uhci-hcd.c62
-rw-r--r--drivers/usb/host/uhci-hcd.h11
-rw-r--r--drivers/usb/host/uhci-hub.c11
-rw-r--r--drivers/usb/host/uhci-q.c2
-rw-r--r--drivers/usb/input/Kconfig20
-rw-r--r--drivers/usb/input/Makefile1
-rw-r--r--drivers/usb/input/appletouch.c469
-rw-r--r--drivers/usb/input/hid-core.c2
-rw-r--r--drivers/usb/misc/sisusbvga/Kconfig42
-rw-r--r--drivers/usb/misc/sisusbvga/Makefile4
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c463
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.h73
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_con.c1658
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_init.c1047
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_init.h830
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_struct.h169
-rw-r--r--drivers/usb/misc/uss720.c393
-rw-r--r--drivers/usb/mon/mon_text.c2
-rw-r--r--drivers/usb/serial/cp2101.c5
-rw-r--r--drivers/usb/serial/cypress_m8.c3
-rw-r--r--drivers/usb/serial/ftdi_sio.c2
-rw-r--r--drivers/usb/serial/pl2303.c4
-rw-r--r--drivers/usb/serial/pl2303.h4
-rw-r--r--drivers/usb/storage/scsiglue.c20
-rw-r--r--drivers/usb/storage/unusual_devs.h35
-rw-r--r--drivers/usb/storage/usb.c11
-rw-r--r--drivers/video/console/Kconfig2
-rw-r--r--drivers/video/console/Makefile4
-rw-r--r--drivers/video/i810/i810_main.c74
-rw-r--r--drivers/w1/w1_ds2433.c6
61 files changed, 6962 insertions, 878 deletions
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
index 721ba8086043..0e9e586e9ba3 100644
--- a/drivers/block/aoe/aoe.h
+++ b/drivers/block/aoe/aoe.h
@@ -1,5 +1,5 @@
1/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ 1/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */
2#define VERSION "10" 2#define VERSION "12"
3#define AOE_MAJOR 152 3#define AOE_MAJOR 152
4#define DEVICE_NAME "aoe" 4#define DEVICE_NAME "aoe"
5 5
@@ -7,12 +7,12 @@
7 * default is 16, which is 15 partitions plus the whole disk 7 * default is 16, which is 15 partitions plus the whole disk
8 */ 8 */
9#ifndef AOE_PARTITIONS 9#ifndef AOE_PARTITIONS
10#define AOE_PARTITIONS 16 10#define AOE_PARTITIONS (16)
11#endif 11#endif
12 12
13#define SYSMINOR(aoemajor, aoeminor) ((aoemajor) * 10 + (aoeminor)) 13#define SYSMINOR(aoemajor, aoeminor) ((aoemajor) * NPERSHELF + (aoeminor))
14#define AOEMAJOR(sysminor) ((sysminor) / 10) 14#define AOEMAJOR(sysminor) ((sysminor) / NPERSHELF)
15#define AOEMINOR(sysminor) ((sysminor) % 10) 15#define AOEMINOR(sysminor) ((sysminor) % NPERSHELF)
16#define WHITESPACE " \t\v\f\n" 16#define WHITESPACE " \t\v\f\n"
17 17
18enum { 18enum {
@@ -83,7 +83,7 @@ enum {
83 83
84enum { 84enum {
85 MAXATADATA = 1024, 85 MAXATADATA = 1024,
86 NPERSHELF = 10, 86 NPERSHELF = 16, /* number of slots per shelf address */
87 FREETAG = -1, 87 FREETAG = -1,
88 MIN_BUFS = 8, 88 MIN_BUFS = 8,
89}; 89};
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index c3898afce3ae..fa789ea36bbe 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -139,6 +139,15 @@ config SA1100_WATCHDOG
139 To compile this driver as a module, choose M here: the 139 To compile this driver as a module, choose M here: the
140 module will be called sa1100_wdt. 140 module will be called sa1100_wdt.
141 141
142config MPCORE_WATCHDOG
143 tristate "MPcore watchdog"
144 depends on WATCHDOG && ARM_MPCORE_PLATFORM && LOCAL_TIMERS
145 help
146 Watchdog timer embedded into the MPcore system.
147
148 To compile this driver as a module, choose M here: the
149 module will be called mpcore_wdt.
150
142# X86 (i386 + ia64 + x86_64) Architecture 151# X86 (i386 + ia64 + x86_64) Architecture
143 152
144config ACQUIRE_WDT 153config ACQUIRE_WDT
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index cfeac6f10137..bc6f5fe88c8c 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
29obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o 29obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
30obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o 30obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
31obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o 31obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
32obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
32 33
33# X86 (i386 + ia64 + x86_64) Architecture 34# X86 (i386 + ia64 + x86_64) Architecture
34obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o 35obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
diff --git a/drivers/char/watchdog/mpcore_wdt.c b/drivers/char/watchdog/mpcore_wdt.c
new file mode 100644
index 000000000000..c694eee1fb24
--- /dev/null
+++ b/drivers/char/watchdog/mpcore_wdt.c
@@ -0,0 +1,434 @@
1/*
2 * Watchdog driver for the mpcore watchdog timer
3 *
4 * (c) Copyright 2004 ARM Limited
5 *
6 * Based on the SoftDog driver:
7 * (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
8 * http://www.redhat.com
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 *
15 * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
16 * warranty for any of this software. This material is provided
17 * "AS-IS" and at no charge.
18 *
19 * (c) Copyright 1995 Alan Cox <alan@lxorguk.ukuu.org.uk>
20 *
21 */
22#include <linux/module.h>
23#include <linux/moduleparam.h>
24#include <linux/config.h>
25#include <linux/types.h>
26#include <linux/miscdevice.h>
27#include <linux/watchdog.h>
28#include <linux/fs.h>
29#include <linux/reboot.h>
30#include <linux/init.h>
31#include <linux/interrupt.h>
32#include <linux/device.h>
33#include <asm/uaccess.h>
34
35struct mpcore_wdt {
36 unsigned long timer_alive;
37 struct device *dev;
38 void __iomem *base;
39 int irq;
40 unsigned int perturb;
41 char expect_close;
42};
43
44static struct platform_device *mpcore_wdt_dev;
45
46extern unsigned int mpcore_timer_rate;
47
48#define TIMER_MARGIN 60
49static int mpcore_margin = TIMER_MARGIN;
50module_param(mpcore_margin, int, 0);
51MODULE_PARM_DESC(mpcore_margin, "MPcore timer margin in seconds. (0<mpcore_margin<65536, default=" __MODULE_STRING(TIMER_MARGIN) ")");
52
53static int nowayout = WATCHDOG_NOWAYOUT;
54module_param(nowayout, int, 0);
55MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
56
57#define ONLY_TESTING 0
58static int mpcore_noboot = ONLY_TESTING;
59module_param(mpcore_noboot, int, 0);
60MODULE_PARM_DESC(mpcore_noboot, "MPcore watchdog action, set to 1 to ignore reboots, 0 to reboot (default=" __MODULE_STRING(ONLY_TESTING) ")");
61
62/*
63 * This is the interrupt handler. Note that we only use this
64 * in testing mode, so don't actually do a reboot here.
65 */
66static irqreturn_t mpcore_wdt_fire(int irq, void *arg, struct pt_regs *regs)
67{
68 struct mpcore_wdt *wdt = arg;
69
70 /* Check it really was our interrupt */
71 if (readl(wdt->base + TWD_WDOG_INTSTAT)) {
72 dev_printk(KERN_CRIT, wdt->dev, "Triggered - Reboot ignored.\n");
73
74 /* Clear the interrupt on the watchdog */
75 writel(1, wdt->base + TWD_WDOG_INTSTAT);
76
77 return IRQ_HANDLED;
78 }
79
80 return IRQ_NONE;
81}
82
83/*
84 * mpcore_wdt_keepalive - reload the timer
85 *
86 * Note that the spec says a DIFFERENT value must be written to the reload
87 * register each time. The "perturb" variable deals with this by adding 1
88 * to the count every other time the function is called.
89 */
90static void mpcore_wdt_keepalive(struct mpcore_wdt *wdt)
91{
92 unsigned int count;
93
94 /* Assume prescale is set to 256 */
95 count = (mpcore_timer_rate / 256) * mpcore_margin;
96
97 /* Reload the counter */
98 writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD);
99
100 wdt->perturb = wdt->perturb ? 0 : 1;
101}
102
103static void mpcore_wdt_stop(struct mpcore_wdt *wdt)
104{
105 writel(0x12345678, wdt->base + TWD_WDOG_DISABLE);
106 writel(0x87654321, wdt->base + TWD_WDOG_DISABLE);
107 writel(0x0, wdt->base + TWD_WDOG_CONTROL);
108}
109
110static void mpcore_wdt_start(struct mpcore_wdt *wdt)
111{
112 dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n");
113
114 /* This loads the count register but does NOT start the count yet */
115 mpcore_wdt_keepalive(wdt);
116
117 if (mpcore_noboot) {
118 /* Enable watchdog - prescale=256, watchdog mode=0, enable=1 */
119 writel(0x0000FF01, wdt->base + TWD_WDOG_CONTROL);
120 } else {
121 /* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */
122 writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL);
123 }
124}
125
126static int mpcore_wdt_set_heartbeat(int t)
127{
128 if (t < 0x0001 || t > 0xFFFF)
129 return -EINVAL;
130
131 mpcore_margin = t;
132 return 0;
133}
134
135/*
136 * /dev/watchdog handling
137 */
138static int mpcore_wdt_open(struct inode *inode, struct file *file)
139{
140 struct mpcore_wdt *wdt = dev_get_drvdata(&mpcore_wdt_dev->dev);
141
142 if (test_and_set_bit(0, &wdt->timer_alive))
143 return -EBUSY;
144
145 if (nowayout)
146 __module_get(THIS_MODULE);
147
148 file->private_data = wdt;
149
150 /*
151 * Activate timer
152 */
153 mpcore_wdt_start(wdt);
154
155 return nonseekable_open(inode, file);
156}
157
158static int mpcore_wdt_release(struct inode *inode, struct file *file)
159{
160 struct mpcore_wdt *wdt = file->private_data;
161
162 /*
163 * Shut off the timer.
164 * Lock it in if it's a module and we set nowayout
165 */
166 if (wdt->expect_close == 42) {
167 mpcore_wdt_stop(wdt);
168 } else {
169 dev_printk(KERN_CRIT, wdt->dev, "unexpected close, not stopping watchdog!\n");
170 mpcore_wdt_keepalive(wdt);
171 }
172 clear_bit(0, &wdt->timer_alive);
173 wdt->expect_close = 0;
174 return 0;
175}
176
177static ssize_t mpcore_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
178{
179 struct mpcore_wdt *wdt = file->private_data;
180
181 /* Can't seek (pwrite) on this device */
182 if (ppos != &file->f_pos)
183 return -ESPIPE;
184
185 /*
186 * Refresh the timer.
187 */
188 if (len) {
189 if (!nowayout) {
190 size_t i;
191
192 /* In case it was set long ago */
193 wdt->expect_close = 0;
194
195 for (i = 0; i != len; i++) {
196 char c;
197
198 if (get_user(c, data + i))
199 return -EFAULT;
200 if (c == 'V')
201 wdt->expect_close = 42;
202 }
203 }
204 mpcore_wdt_keepalive(wdt);
205 }
206 return len;
207}
208
209static struct watchdog_info ident = {
210 .options = WDIOF_SETTIMEOUT |
211 WDIOF_KEEPALIVEPING |
212 WDIOF_MAGICCLOSE,
213 .identity = "MPcore Watchdog",
214};
215
216static int mpcore_wdt_ioctl(struct inode *inode, struct file *file,
217 unsigned int cmd, unsigned long arg)
218{
219 struct mpcore_wdt *wdt = file->private_data;
220 int ret;
221 union {
222 struct watchdog_info ident;
223 int i;
224 } uarg;
225
226 if (_IOC_DIR(cmd) && _IOC_SIZE(cmd) > sizeof(uarg))
227 return -ENOIOCTLCMD;
228
229 if (_IOC_DIR(cmd) & _IOC_WRITE) {
230 ret = copy_from_user(&uarg, (void __user *)arg, _IOC_SIZE(cmd));
231 if (ret)
232 return -EFAULT;
233 }
234
235 switch (cmd) {
236 case WDIOC_GETSUPPORT:
237 uarg.ident = ident;
238 ret = 0;
239 break;
240
241 case WDIOC_SETOPTIONS:
242 ret = -EINVAL;
243 if (uarg.i & WDIOS_DISABLECARD) {
244 mpcore_wdt_stop(wdt);
245 ret = 0;
246 }
247 if (uarg.i & WDIOS_ENABLECARD) {
248 mpcore_wdt_start(wdt);
249 ret = 0;
250 }
251 break;
252
253 case WDIOC_GETSTATUS:
254 case WDIOC_GETBOOTSTATUS:
255 uarg.i = 0;
256 ret = 0;
257 break;
258
259 case WDIOC_KEEPALIVE:
260 mpcore_wdt_keepalive(wdt);
261 ret = 0;
262 break;
263
264 case WDIOC_SETTIMEOUT:
265 ret = mpcore_wdt_set_heartbeat(uarg.i);
266 if (ret)
267 break;
268
269 mpcore_wdt_keepalive(wdt);
270 /* Fall */
271 case WDIOC_GETTIMEOUT:
272 uarg.i = mpcore_margin;
273 ret = 0;
274 break;
275
276 default:
277 return -ENOIOCTLCMD;
278 }
279
280 if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
281 ret = copy_to_user((void __user *)arg, &uarg, _IOC_SIZE(cmd));
282 if (ret)
283 ret = -EFAULT;
284 }
285 return ret;
286}
287
288/*
289 * System shutdown handler. Turn off the watchdog if we're
290 * restarting or halting the system.
291 */
292static void mpcore_wdt_shutdown(struct device *_dev)
293{
294 struct mpcore_wdt *wdt = dev_get_drvdata(_dev);
295
296 if (system_state == SYSTEM_RESTART || system_state == SYSTEM_HALT)
297 mpcore_wdt_stop(wdt);
298}
299
300/*
301 * Kernel Interfaces
302 */
303static struct file_operations mpcore_wdt_fops = {
304 .owner = THIS_MODULE,
305 .llseek = no_llseek,
306 .write = mpcore_wdt_write,
307 .ioctl = mpcore_wdt_ioctl,
308 .open = mpcore_wdt_open,
309 .release = mpcore_wdt_release,
310};
311
312static struct miscdevice mpcore_wdt_miscdev = {
313 .minor = WATCHDOG_MINOR,
314 .name = "watchdog",
315 .fops = &mpcore_wdt_fops,
316};
317
318static int __devinit mpcore_wdt_probe(struct device *_dev)
319{
320 struct platform_device *dev = to_platform_device(_dev);
321 struct mpcore_wdt *wdt;
322 struct resource *res;
323 int ret;
324
325 /* We only accept one device, and it must have an id of -1 */
326 if (dev->id != -1)
327 return -ENODEV;
328
329 res = platform_get_resource(dev, IORESOURCE_MEM, 0);
330 if (!res) {
331 ret = -ENODEV;
332 goto err_out;
333 }
334
335 wdt = kmalloc(sizeof(struct mpcore_wdt), GFP_KERNEL);
336 if (!wdt) {
337 ret = -ENOMEM;
338 goto err_out;
339 }
340 memset(wdt, 0, sizeof(struct mpcore_wdt));
341
342 wdt->dev = &dev->dev;
343 wdt->irq = platform_get_irq(dev, 0);
344 wdt->base = ioremap(res->start, res->end - res->start + 1);
345 if (!wdt->base) {
346 ret = -ENOMEM;
347 goto err_free;
348 }
349
350 mpcore_wdt_miscdev.dev = &dev->dev;
351 ret = misc_register(&mpcore_wdt_miscdev);
352 if (ret) {
353 dev_printk(KERN_ERR, _dev, "cannot register miscdev on minor=%d (err=%d)\n",
354 WATCHDOG_MINOR, ret);
355 goto err_misc;
356 }
357
358 ret = request_irq(wdt->irq, mpcore_wdt_fire, SA_INTERRUPT, "mpcore_wdt", wdt);
359 if (ret) {
360 dev_printk(KERN_ERR, _dev, "cannot register IRQ%d for watchdog\n", wdt->irq);
361 goto err_irq;
362 }
363
364 mpcore_wdt_stop(wdt);
365 dev_set_drvdata(&dev->dev, wdt);
366 mpcore_wdt_dev = dev;
367
368 return 0;
369
370 err_irq:
371 misc_deregister(&mpcore_wdt_miscdev);
372 err_misc:
373 iounmap(wdt->base);
374 err_free:
375 kfree(wdt);
376 err_out:
377 return ret;
378}
379
380static int __devexit mpcore_wdt_remove(struct device *dev)
381{
382 struct mpcore_wdt *wdt = dev_get_drvdata(dev);
383
384 dev_set_drvdata(dev, NULL);
385
386 misc_deregister(&mpcore_wdt_miscdev);
387
388 mpcore_wdt_dev = NULL;
389
390 free_irq(wdt->irq, wdt);
391 iounmap(wdt->base);
392 kfree(wdt);
393 return 0;
394}
395
396static struct device_driver mpcore_wdt_driver = {
397 .name = "mpcore_wdt",
398 .bus = &platform_bus_type,
399 .probe = mpcore_wdt_probe,
400 .remove = __devexit_p(mpcore_wdt_remove),
401 .shutdown = mpcore_wdt_shutdown,
402};
403
404static char banner[] __initdata = KERN_INFO "MPcore Watchdog Timer: 0.1. mpcore_noboot=%d mpcore_margin=%d sec (nowayout= %d)\n";
405
406static int __init mpcore_wdt_init(void)
407{
408 /*
409 * Check that the margin value is within it's range;
410 * if not reset to the default
411 */
412 if (mpcore_wdt_set_heartbeat(mpcore_margin)) {
413 mpcore_wdt_set_heartbeat(TIMER_MARGIN);
414 printk(KERN_INFO "mpcore_margin value must be 0<mpcore_margin<65536, using %d\n",
415 TIMER_MARGIN);
416 }
417
418 printk(banner, mpcore_noboot, mpcore_margin, nowayout);
419
420 return driver_register(&mpcore_wdt_driver);
421}
422
423static void __exit mpcore_wdt_exit(void)
424{
425 driver_unregister(&mpcore_wdt_driver);
426}
427
428module_init(mpcore_wdt_init);
429module_exit(mpcore_wdt_exit);
430
431MODULE_AUTHOR("ARM Limited");
432MODULE_DESCRIPTION("MPcore Watchdog Device Driver");
433MODULE_LICENSE("GPL");
434MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 138dc50270e3..7e72e922b41c 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -411,6 +411,23 @@ config SENSORS_W83627EHF
411 This driver can also be built as a module. If so, the module 411 This driver can also be built as a module. If so, the module
412 will be called w83627ehf. 412 will be called w83627ehf.
413 413
414config SENSORS_HDAPS
415 tristate "IBM Hard Drive Active Protection System (hdaps)"
416 depends on HWMON && INPUT && X86
417 default n
418 help
419 This driver provides support for the IBM Hard Drive Active Protection
420 System (hdaps), which provides an accelerometer and other misc. data.
421 Supported laptops include the IBM ThinkPad T41, T42, T43, and R51.
422 The accelerometer data is readable via sysfs.
423
424 This driver also provides an input class device, allowing the
425 laptop to act as a pinball machine-esque mouse. This is off by
426 default but enabled via sysfs or the module parameter "mousedev".
427
428 Say Y here if you have an applicable laptop and want to experience
429 the awesome power of hdaps.
430
414config HWMON_DEBUG_CHIP 431config HWMON_DEBUG_CHIP
415 bool "Hardware Monitoring Chip debugging messages" 432 bool "Hardware Monitoring Chip debugging messages"
416 depends on HWMON 433 depends on HWMON
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 381f1bf04cc5..f7d6a2f61ee7 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_SENSORS_FSCHER) += fscher.o
22obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o 22obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o
23obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o 23obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
24obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o 24obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
25obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
25obj-$(CONFIG_SENSORS_IT87) += it87.o 26obj-$(CONFIG_SENSORS_IT87) += it87.o
26obj-$(CONFIG_SENSORS_LM63) += lm63.o 27obj-$(CONFIG_SENSORS_LM63) += lm63.o
27obj-$(CONFIG_SENSORS_LM75) += lm75.o 28obj-$(CONFIG_SENSORS_LM75) += lm75.o
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
new file mode 100644
index 000000000000..eaebfc14c933
--- /dev/null
+++ b/drivers/hwmon/hdaps.c
@@ -0,0 +1,739 @@
1/*
2 * drivers/hwmon/hdaps.c - driver for IBM's Hard Drive Active Protection System
3 *
4 * Copyright (C) 2005 Robert Love <rml@novell.com>
5 * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com>
6 *
7 * The HardDisk Active Protection System (hdaps) is present in the IBM ThinkPad
8 * T41, T42, T43, R51, and X40, at least. It provides a basic two-axis
9 * accelerometer and other data, such as the device's temperature.
10 *
11 * Based on the document by Mark A. Smith available at
12 * http://www.almaden.ibm.com/cs/people/marksmith/tpaps.html and a lot of trial
13 * and error.
14 *
15 * This program is free software; you can redistribute it and/or modify it
16 * under the terms of the GNU General Public License v2 as published by the
17 * Free Software Foundation.
18 *
19 * This program is distributed in the hope that it will be useful, but WITHOUT
20 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
22 * more details.
23 *
24 * You should have received a copy of the GNU General Public License along with
25 * this program; if not, write to the Free Software Foundation, Inc.,
26 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
27 */
28
29#include <linux/delay.h>
30#include <linux/device.h>
31#include <linux/input.h>
32#include <linux/kernel.h>
33#include <linux/module.h>
34#include <linux/timer.h>
35#include <linux/dmi.h>
36#include <asm/io.h>
37
38#define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */
39#define HDAPS_NR_PORTS 0x30 /* 0x1600 - 0x162f */
40
41#define STATE_FRESH 0x50 /* accelerometer data is fresh */
42
43#define REFRESH_ASYNC 0x00 /* do asynchronous refresh */
44#define REFRESH_SYNC 0x01 /* do synchronous refresh */
45
46#define HDAPS_PORT_STATE 0x1611 /* device state */
47#define HDAPS_PORT_YPOS 0x1612 /* y-axis position */
48#define HDAPS_PORT_XPOS 0x1614 /* x-axis position */
49#define HDAPS_PORT_TEMP1 0x1616 /* device temperature, in celcius */
50#define HDAPS_PORT_YVAR 0x1617 /* y-axis variance (what is this?) */
51#define HDAPS_PORT_XVAR 0x1619 /* x-axis variance (what is this?) */
52#define HDAPS_PORT_TEMP2 0x161b /* device temperature (again?) */
53#define HDAPS_PORT_UNKNOWN 0x161c /* what is this? */
54#define HDAPS_PORT_KMACT 0x161d /* keyboard or mouse activity */
55
56#define HDAPS_READ_MASK 0xff /* some reads have the low 8 bits set */
57
58#define KEYBD_MASK 0x20 /* set if keyboard activity */
59#define MOUSE_MASK 0x40 /* set if mouse activity */
60#define KEYBD_ISSET(n) (!! (n & KEYBD_MASK)) /* keyboard used? */
61#define MOUSE_ISSET(n) (!! (n & MOUSE_MASK)) /* mouse used? */
62
63#define INIT_TIMEOUT_MSECS 4000 /* wait up to 4s for device init ... */
64#define INIT_WAIT_MSECS 200 /* ... in 200ms increments */
65
66static struct platform_device *pdev;
67static struct input_dev hdaps_idev;
68static struct timer_list hdaps_timer;
69static unsigned int hdaps_mousedev_threshold = 4;
70static unsigned long hdaps_poll_ms = 50;
71static unsigned int hdaps_mousedev;
72static unsigned int hdaps_invert;
73static u8 km_activity;
74static int rest_x;
75static int rest_y;
76
77static DECLARE_MUTEX(hdaps_sem);
78
79/*
80 * __get_latch - Get the value from a given port. Callers must hold hdaps_sem.
81 */
82static inline u8 __get_latch(u16 port)
83{
84 return inb(port) & HDAPS_READ_MASK;
85}
86
87/*
88 * __check_latch - Check a port latch for a given value. Callers must hold
89 * hdaps_sem. Returns zero if the port contains the given value.
90 */
91static inline unsigned int __check_latch(u16 port, u8 val)
92{
93 if (__get_latch(port) == val)
94 return 0;
95 return -EINVAL;
96}
97
98/*
99 * __wait_latch - Wait up to 100us for a port latch to get a certain value,
100 * returning zero if the value is obtained. Callers must hold hdaps_sem.
101 */
102static unsigned int __wait_latch(u16 port, u8 val)
103{
104 unsigned int i;
105
106 for (i = 0; i < 20; i++) {
107 if (!__check_latch(port, val))
108 return 0;
109 udelay(5);
110 }
111
112 return -EINVAL;
113}
114
115/*
116 * __device_refresh - Request a refresh from the accelerometer.
117 *
118 * If sync is REFRESH_SYNC, we perform a synchronous refresh and will wait.
119 * Returns zero if successful and nonzero on error.
120 *
121 * If sync is REFRESH_ASYNC, we merely kick off a new refresh if the device is
122 * not up-to-date. Always returns zero.
123 *
124 * Callers must hold hdaps_sem.
125 */
126static int __device_refresh(unsigned int sync)
127{
128 u8 state;
129
130 udelay(100);
131
132 state = inb(0x1604);
133 if (state == STATE_FRESH)
134 return 0;
135
136 outb(0x11, 0x1610);
137 outb(0x01, 0x161f);
138 if (sync == REFRESH_ASYNC)
139 return 0;
140
141 return __wait_latch(0x1604, STATE_FRESH);
142}
143
144/*
145 * __device_complete - Indicate to the accelerometer that we are done reading
146 * data, and then initiate an async refresh. Callers must hold hdaps_sem.
147 */
148static inline void __device_complete(void)
149{
150 inb(0x161f);
151 inb(0x1604);
152 __device_refresh(REFRESH_ASYNC);
153}
154
155static int __hdaps_readb_one(unsigned int port, u8 *val)
156{
157 /* do a sync refresh -- we need to be sure that we read fresh data */
158 if (__device_refresh(REFRESH_SYNC))
159 return -EIO;
160
161 *val = inb(port);
162 __device_complete();
163
164 return 0;
165}
166
167/*
168 * hdaps_readb_one - reads a byte from a single I/O port, placing the value in
169 * the given pointer. Returns zero on success or a negative error on failure.
170 * Can sleep.
171 */
172static int hdaps_readb_one(unsigned int port, u8 *val)
173{
174 int ret;
175
176 down(&hdaps_sem);
177 ret = __hdaps_readb_one(port, val);
178 up(&hdaps_sem);
179
180 return ret;
181}
182
183static int __hdaps_read_pair(unsigned int port1, unsigned int port2,
184 int *x, int *y)
185{
186 /* do a sync refresh -- we need to be sure that we read fresh data */
187 if (__device_refresh(REFRESH_SYNC))
188 return -EIO;
189
190 *y = inw(port2);
191 *x = inw(port1);
192 km_activity = inb(HDAPS_PORT_KMACT);
193 __device_complete();
194
195 /* if hdaps_invert is set, negate the two values */
196 if (hdaps_invert) {
197 *x = -*x;
198 *y = -*y;
199 }
200
201 return 0;
202}
203
204/*
205 * hdaps_read_pair - reads the values from a pair of ports, placing the values
206 * in the given pointers. Returns zero on success. Can sleep.
207 */
208static int hdaps_read_pair(unsigned int port1, unsigned int port2,
209 int *val1, int *val2)
210{
211 int ret;
212
213 down(&hdaps_sem);
214 ret = __hdaps_read_pair(port1, port2, val1, val2);
215 up(&hdaps_sem);
216
217 return ret;
218}
219
220/* initialize the accelerometer */
221static int hdaps_device_init(void)
222{
223 unsigned int total_msecs = INIT_TIMEOUT_MSECS;
224 int ret = -ENXIO;
225
226 down(&hdaps_sem);
227
228 outb(0x13, 0x1610);
229 outb(0x01, 0x161f);
230 if (__wait_latch(0x161f, 0x00))
231 goto out;
232
233 /*
234 * The 0x03 value appears to only work on some thinkpads, such as the
235 * T42p. Others return 0x01.
236 *
237 * The 0x02 value occurs when the chip has been previously initialized.
238 */
239 if (__check_latch(0x1611, 0x03) &&
240 __check_latch(0x1611, 0x02) &&
241 __check_latch(0x1611, 0x01))
242 goto out;
243
244 printk(KERN_DEBUG "hdaps: initial latch check good (0x%02x).\n",
245 __get_latch(0x1611));
246
247 outb(0x17, 0x1610);
248 outb(0x81, 0x1611);
249 outb(0x01, 0x161f);
250 if (__wait_latch(0x161f, 0x00))
251 goto out;
252 if (__wait_latch(0x1611, 0x00))
253 goto out;
254 if (__wait_latch(0x1612, 0x60))
255 goto out;
256 if (__wait_latch(0x1613, 0x00))
257 goto out;
258 outb(0x14, 0x1610);
259 outb(0x01, 0x1611);
260 outb(0x01, 0x161f);
261 if (__wait_latch(0x161f, 0x00))
262 goto out;
263 outb(0x10, 0x1610);
264 outb(0xc8, 0x1611);
265 outb(0x00, 0x1612);
266 outb(0x02, 0x1613);
267 outb(0x01, 0x161f);
268 if (__wait_latch(0x161f, 0x00))
269 goto out;
270 if (__device_refresh(REFRESH_SYNC))
271 goto out;
272 if (__wait_latch(0x1611, 0x00))
273 goto out;
274
275 /* we have done our dance, now let's wait for the applause */
276 while (total_msecs > 0) {
277 u8 ignored;
278
279 /* a read of the device helps push it into action */
280 __hdaps_readb_one(HDAPS_PORT_UNKNOWN, &ignored);
281 if (!__wait_latch(0x1611, 0x02)) {
282 ret = 0;
283 break;
284 }
285
286 msleep(INIT_WAIT_MSECS);
287 total_msecs -= INIT_WAIT_MSECS;
288 }
289
290out:
291 up(&hdaps_sem);
292 return ret;
293}
294
295
296/* Input class stuff */
297
298/*
299 * hdaps_calibrate - Zero out our "resting" values. Callers must hold hdaps_sem.
300 */
301static void hdaps_calibrate(void)
302{
303 int x, y;
304
305 if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y))
306 return;
307
308 rest_x = x;
309 rest_y = y;
310}
311
312static void hdaps_mousedev_poll(unsigned long unused)
313{
314 int x, y;
315
316 /* Cannot sleep. Try nonblockingly. If we fail, try again later. */
317 if (down_trylock(&hdaps_sem)) {
318 mod_timer(&hdaps_timer,jiffies+msecs_to_jiffies(hdaps_poll_ms));
319 return;
320 }
321
322 if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y))
323 goto out;
324
325 x -= rest_x;
326 y -= rest_y;
327 if (abs(x) > hdaps_mousedev_threshold)
328 input_report_rel(&hdaps_idev, REL_X, x);
329 if (abs(y) > hdaps_mousedev_threshold)
330 input_report_rel(&hdaps_idev, REL_Y, y);
331 input_sync(&hdaps_idev);
332
333 mod_timer(&hdaps_timer, jiffies + msecs_to_jiffies(hdaps_poll_ms));
334
335out:
336 up(&hdaps_sem);
337}
338
339/*
340 * hdaps_mousedev_enable - enable the input class device. Can sleep.
341 */
342static void hdaps_mousedev_enable(void)
343{
344 down(&hdaps_sem);
345
346 /* calibrate the device before enabling */
347 hdaps_calibrate();
348
349 /* initialize the input class */
350 init_input_dev(&hdaps_idev);
351 hdaps_idev.dev = &pdev->dev;
352 hdaps_idev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
353 hdaps_idev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
354 hdaps_idev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT);
355 input_register_device(&hdaps_idev);
356
357 /* start up our timer */
358 init_timer(&hdaps_timer);
359 hdaps_timer.function = hdaps_mousedev_poll;
360 hdaps_timer.expires = jiffies + msecs_to_jiffies(hdaps_poll_ms);
361 add_timer(&hdaps_timer);
362
363 hdaps_mousedev = 1;
364
365 up(&hdaps_sem);
366
367 printk(KERN_INFO "hdaps: input device enabled.\n");
368}
369
370/*
371 * hdaps_mousedev_disable - disable the input class device. Caller must hold
372 * hdaps_sem.
373 */
374static void hdaps_mousedev_disable(void)
375{
376 down(&hdaps_sem);
377 if (hdaps_mousedev) {
378 hdaps_mousedev = 0;
379 del_timer_sync(&hdaps_timer);
380 input_unregister_device(&hdaps_idev);
381 }
382 up(&hdaps_sem);
383}
384
385
386/* Device model stuff */
387
388static int hdaps_probe(struct device *dev)
389{
390 int ret;
391
392 ret = hdaps_device_init();
393 if (ret)
394 return ret;
395
396 printk(KERN_INFO "hdaps: device successfully initialized.\n");
397 return 0;
398}
399
400static int hdaps_resume(struct device *dev, u32 level)
401{
402 if (level == RESUME_ENABLE)
403 return hdaps_device_init();
404 return 0;
405}
406
407static struct device_driver hdaps_driver = {
408 .name = "hdaps",
409 .bus = &platform_bus_type,
410 .owner = THIS_MODULE,
411 .probe = hdaps_probe,
412 .resume = hdaps_resume
413};
414
415
416/* Sysfs Files */
417
418static ssize_t hdaps_position_show(struct device *dev,
419 struct device_attribute *attr, char *buf)
420{
421 int ret, x, y;
422
423 ret = hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y);
424 if (ret)
425 return ret;
426
427 return sprintf(buf, "(%d,%d)\n", x, y);
428}
429
430static ssize_t hdaps_variance_show(struct device *dev,
431 struct device_attribute *attr, char *buf)
432{
433 int ret, x, y;
434
435 ret = hdaps_read_pair(HDAPS_PORT_XVAR, HDAPS_PORT_YVAR, &x, &y);
436 if (ret)
437 return ret;
438
439 return sprintf(buf, "(%d,%d)\n", x, y);
440}
441
442static ssize_t hdaps_temp1_show(struct device *dev,
443 struct device_attribute *attr, char *buf)
444{
445 u8 temp;
446 int ret;
447
448 ret = hdaps_readb_one(HDAPS_PORT_TEMP1, &temp);
449 if (ret < 0)
450 return ret;
451
452 return sprintf(buf, "%u\n", temp);
453}
454
455static ssize_t hdaps_temp2_show(struct device *dev,
456 struct device_attribute *attr, char *buf)
457{
458 u8 temp;
459 int ret;
460
461 ret = hdaps_readb_one(HDAPS_PORT_TEMP2, &temp);
462 if (ret < 0)
463 return ret;
464
465 return sprintf(buf, "%u\n", temp);
466}
467
468static ssize_t hdaps_keyboard_activity_show(struct device *dev,
469 struct device_attribute *attr,
470 char *buf)
471{
472 return sprintf(buf, "%u\n", KEYBD_ISSET(km_activity));
473}
474
475static ssize_t hdaps_mouse_activity_show(struct device *dev,
476 struct device_attribute *attr,
477 char *buf)
478{
479 return sprintf(buf, "%u\n", MOUSE_ISSET(km_activity));
480}
481
482static ssize_t hdaps_calibrate_show(struct device *dev,
483 struct device_attribute *attr, char *buf)
484{
485 return sprintf(buf, "(%d,%d)\n", rest_x, rest_y);
486}
487
488static ssize_t hdaps_calibrate_store(struct device *dev,
489 struct device_attribute *attr,
490 const char *buf, size_t count)
491{
492 down(&hdaps_sem);
493 hdaps_calibrate();
494 up(&hdaps_sem);
495
496 return count;
497}
498
499static ssize_t hdaps_invert_show(struct device *dev,
500 struct device_attribute *attr, char *buf)
501{
502 return sprintf(buf, "%u\n", hdaps_invert);
503}
504
505static ssize_t hdaps_invert_store(struct device *dev,
506 struct device_attribute *attr,
507 const char *buf, size_t count)
508{
509 int invert;
510
511 if (sscanf(buf, "%d", &invert) != 1 || (invert != 1 && invert != 0))
512 return -EINVAL;
513
514 hdaps_invert = invert;
515 hdaps_calibrate();
516
517 return count;
518}
519
520static ssize_t hdaps_mousedev_show(struct device *dev,
521 struct device_attribute *attr, char *buf)
522{
523 return sprintf(buf, "%d\n", hdaps_mousedev);
524}
525
526static ssize_t hdaps_mousedev_store(struct device *dev,
527 struct device_attribute *attr,
528 const char *buf, size_t count)
529{
530 int enable;
531
532 if (sscanf(buf, "%d", &enable) != 1)
533 return -EINVAL;
534
535 if (enable == 1)
536 hdaps_mousedev_enable();
537 else if (enable == 0)
538 hdaps_mousedev_disable();
539 else
540 return -EINVAL;
541
542 return count;
543}
544
545static ssize_t hdaps_poll_show(struct device *dev,
546 struct device_attribute *attr, char *buf)
547{
548 return sprintf(buf, "%lu\n", hdaps_poll_ms);
549}
550
551static ssize_t hdaps_poll_store(struct device *dev,
552 struct device_attribute *attr,
553 const char *buf, size_t count)
554{
555 unsigned int poll;
556
557 if (sscanf(buf, "%u", &poll) != 1 || poll == 0)
558 return -EINVAL;
559 hdaps_poll_ms = poll;
560
561 return count;
562}
563
564static ssize_t hdaps_threshold_show(struct device *dev,
565 struct device_attribute *attr, char *buf)
566{
567 return sprintf(buf, "%u\n", hdaps_mousedev_threshold);
568}
569
570static ssize_t hdaps_threshold_store(struct device *dev,
571 struct device_attribute *attr,
572 const char *buf, size_t count)
573{
574 unsigned int threshold;
575
576 if (sscanf(buf, "%u", &threshold) != 1 || threshold == 0)
577 return -EINVAL;
578 hdaps_mousedev_threshold = threshold;
579
580 return count;
581}
582
583static DEVICE_ATTR(position, 0444, hdaps_position_show, NULL);
584static DEVICE_ATTR(variance, 0444, hdaps_variance_show, NULL);
585static DEVICE_ATTR(temp1, 0444, hdaps_temp1_show, NULL);
586static DEVICE_ATTR(temp2, 0444, hdaps_temp2_show, NULL);
587static DEVICE_ATTR(keyboard_activity, 0444, hdaps_keyboard_activity_show, NULL);
588static DEVICE_ATTR(mouse_activity, 0444, hdaps_mouse_activity_show, NULL);
589static DEVICE_ATTR(calibrate, 0644, hdaps_calibrate_show,hdaps_calibrate_store);
590static DEVICE_ATTR(invert, 0644, hdaps_invert_show, hdaps_invert_store);
591static DEVICE_ATTR(mousedev, 0644, hdaps_mousedev_show, hdaps_mousedev_store);
592static DEVICE_ATTR(mousedev_poll_ms, 0644, hdaps_poll_show, hdaps_poll_store);
593static DEVICE_ATTR(mousedev_threshold, 0644, hdaps_threshold_show,
594 hdaps_threshold_store);
595
596static struct attribute *hdaps_attributes[] = {
597 &dev_attr_position.attr,
598 &dev_attr_variance.attr,
599 &dev_attr_temp1.attr,
600 &dev_attr_temp2.attr,
601 &dev_attr_keyboard_activity.attr,
602 &dev_attr_mouse_activity.attr,
603 &dev_attr_calibrate.attr,
604 &dev_attr_mousedev.attr,
605 &dev_attr_mousedev_threshold.attr,
606 &dev_attr_mousedev_poll_ms.attr,
607 &dev_attr_invert.attr,
608 NULL,
609};
610
611static struct attribute_group hdaps_attribute_group = {
612 .attrs = hdaps_attributes,
613};
614
615
616/* Module stuff */
617
618/*
619 * XXX: We should be able to return nonzero and halt the detection process.
620 * But there is a bug in dmi_check_system() where a nonzero return from the
621 * first match will result in a return of failure from dmi_check_system().
622 * I fixed this; the patch is in 2.6-mm. Once in Linus's tree we can make
623 * hdaps_dmi_match_invert() return hdaps_dmi_match(), which in turn returns 1.
624 */
625static int hdaps_dmi_match(struct dmi_system_id *id)
626{
627 printk(KERN_INFO "hdaps: %s detected.\n", id->ident);
628 return 0;
629}
630
631static int hdaps_dmi_match_invert(struct dmi_system_id *id)
632{
633 hdaps_invert = 1;
634 printk(KERN_INFO "hdaps: inverting axis readings.\n");
635 return 0;
636}
637
638#define HDAPS_DMI_MATCH_NORMAL(model) { \
639 .ident = "IBM " model, \
640 .callback = hdaps_dmi_match, \
641 .matches = { \
642 DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), \
643 DMI_MATCH(DMI_PRODUCT_VERSION, model) \
644 } \
645}
646
647#define HDAPS_DMI_MATCH_INVERT(model) { \
648 .ident = "IBM " model, \
649 .callback = hdaps_dmi_match_invert, \
650 .matches = { \
651 DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), \
652 DMI_MATCH(DMI_PRODUCT_VERSION, model) \
653 } \
654}
655
656static int __init hdaps_init(void)
657{
658 int ret;
659
660 /* Note that DMI_MATCH(...,"ThinkPad T42") will match "ThinkPad T42p" */
661 struct dmi_system_id hdaps_whitelist[] = {
662 HDAPS_DMI_MATCH_INVERT("ThinkPad R50p"),
663 HDAPS_DMI_MATCH_NORMAL("ThinkPad R50"),
664 HDAPS_DMI_MATCH_NORMAL("ThinkPad R51"),
665 HDAPS_DMI_MATCH_INVERT("ThinkPad T41p"),
666 HDAPS_DMI_MATCH_NORMAL("ThinkPad T41"),
667 HDAPS_DMI_MATCH_INVERT("ThinkPad T42p"),
668 HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"),
669 HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"),
670 HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"),
671 { .ident = NULL }
672 };
673
674 if (!dmi_check_system(hdaps_whitelist)) {
675 printk(KERN_WARNING "hdaps: supported laptop not found!\n");
676 ret = -ENXIO;
677 goto out;
678 }
679
680 if (!request_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS, "hdaps")) {
681 ret = -ENXIO;
682 goto out;
683 }
684
685 ret = driver_register(&hdaps_driver);
686 if (ret)
687 goto out_region;
688
689 pdev = platform_device_register_simple("hdaps", -1, NULL, 0);
690 if (IS_ERR(pdev)) {
691 ret = PTR_ERR(pdev);
692 goto out_driver;
693 }
694
695 ret = sysfs_create_group(&pdev->dev.kobj, &hdaps_attribute_group);
696 if (ret)
697 goto out_device;
698
699 if (hdaps_mousedev)
700 hdaps_mousedev_enable();
701
702 printk(KERN_INFO "hdaps: driver successfully loaded.\n");
703 return 0;
704
705out_device:
706 platform_device_unregister(pdev);
707out_driver:
708 driver_unregister(&hdaps_driver);
709out_region:
710 release_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS);
711out:
712 printk(KERN_WARNING "hdaps: driver init failed (ret=%d)!\n", ret);
713 return ret;
714}
715
716static void __exit hdaps_exit(void)
717{
718 hdaps_mousedev_disable();
719
720 sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
721 platform_device_unregister(pdev);
722 driver_unregister(&hdaps_driver);
723 release_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS);
724
725 printk(KERN_INFO "hdaps: driver unloaded.\n");
726}
727
728module_init(hdaps_init);
729module_exit(hdaps_exit);
730
731module_param_named(mousedev, hdaps_mousedev, bool, 0);
732MODULE_PARM_DESC(mousedev, "enable the input class device");
733
734module_param_named(invert, hdaps_invert, bool, 0);
735MODULE_PARM_DESC(invert, "invert data along each axis");
736
737MODULE_AUTHOR("Robert Love");
738MODULE_DESCRIPTION("IBM Hard Drive Active Protection System (HDAPS) driver");
739MODULE_LICENSE("GPL v2");
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index 8610bce08244..21aa9a41f62c 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -758,11 +758,6 @@ static int __devinit sis5595_pci_probe(struct pci_dev *dev,
758 return -ENODEV; 758 return -ENODEV;
759 } 759 }
760 760
761 if (!address) {
762 dev_err(&dev->dev,"No SiS 5595 sensors found.\n");
763 return -ENODEV;
764 }
765
766 s_bridge = pci_dev_get(dev); 761 s_bridge = pci_dev_get(dev);
767 if (i2c_isa_add_driver(&sis5595_driver)) { 762 if (i2c_isa_add_driver(&sis5595_driver)) {
768 pci_dev_put(s_bridge); 763 pci_dev_put(s_bridge);
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index 7e699a8ede26..c9cc683eba4a 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -2,8 +2,8 @@
2 smsc47m1.c - Part of lm_sensors, Linux kernel modules 2 smsc47m1.c - Part of lm_sensors, Linux kernel modules
3 for hardware monitoring 3 for hardware monitoring
4 4
5 Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x and LPC47M14x 5 Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x, LPC47M14x,
6 Super-I/O chips. 6 LPC47M15x and LPC47M192 Super-I/O chips.
7 7
8 Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com> 8 Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
9 Copyright (C) 2004 Jean Delvare <khali@linux-fr.org> 9 Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
index eb84997627c8..05ddc88e7dd2 100644
--- a/drivers/hwmon/via686a.c
+++ b/drivers/hwmon/via686a.c
@@ -812,11 +812,6 @@ static int __devinit via686a_pci_probe(struct pci_dev *dev,
812 return -ENODEV; 812 return -ENODEV;
813 } 813 }
814 814
815 if (!address) {
816 dev_err(&dev->dev, "No Via 686A sensors found.\n");
817 return -ENODEV;
818 }
819
820 s_bridge = pci_dev_get(dev); 815 s_bridge = pci_dev_get(dev);
821 if (i2c_isa_add_driver(&via686a_driver)) { 816 if (i2c_isa_add_driver(&via686a_driver)) {
822 pci_dev_put(s_bridge); 817 pci_dev_put(s_bridge);
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index 02bd5c0239a2..3479dc5208e2 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -64,6 +64,10 @@ static unsigned short address;
64/* Insmod parameters */ 64/* Insmod parameters */
65enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf }; 65enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf };
66 66
67static int reset;
68module_param(reset, bool, 0);
69MODULE_PARM_DESC(reset, "Set to one to reset chip on load");
70
67static int init = 1; 71static int init = 1;
68module_param(init, bool, 0); 72module_param(init, bool, 0);
69MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); 73MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
@@ -1279,7 +1283,15 @@ static void w83627hf_init_client(struct i2c_client *client)
1279 int type = data->type; 1283 int type = data->type;
1280 u8 tmp; 1284 u8 tmp;
1281 1285
1282 if(init) { 1286 if (reset) {
1287 /* Resetting the chip has been the default for a long time,
1288 but repeatedly caused problems (fans going to full
1289 speed...) so it is now optional. It might even go away if
1290 nobody reports it as being useful, as I see very little
1291 reason why this would be needed at all. */
1292 dev_info(&client->dev, "If reset=1 solved a problem you were "
1293 "having, please report!\n");
1294
1283 /* save this register */ 1295 /* save this register */
1284 i = w83627hf_read_value(client, W83781D_REG_BEEP_CONFIG); 1296 i = w83627hf_read_value(client, W83781D_REG_BEEP_CONFIG);
1285 /* Reset all except Watchdog values and last conversion values 1297 /* Reset all except Watchdog values and last conversion values
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index e0b7a913431e..fe9c0f42a2b7 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -98,11 +98,6 @@ struct nforce2_smbus {
98#define NVIDIA_SMB_PRTCL_PEC 0x80 98#define NVIDIA_SMB_PRTCL_PEC 0x80
99 99
100 100
101/* Other settings */
102#define MAX_TIMEOUT 256
103
104
105
106static s32 nforce2_access(struct i2c_adapter *adap, u16 addr, 101static s32 nforce2_access(struct i2c_adapter *adap, u16 addr,
107 unsigned short flags, char read_write, 102 unsigned short flags, char read_write,
108 u8 command, int size, union i2c_smbus_data *data); 103 u8 command, int size, union i2c_smbus_data *data);
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index e11e55dc8924..3cbca7cbea80 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -93,7 +93,7 @@ static int dma = 2;
93static inline void wbsd_unlock_config(struct wbsd_host* host) 93static inline void wbsd_unlock_config(struct wbsd_host* host)
94{ 94{
95 BUG_ON(host->config == 0); 95 BUG_ON(host->config == 0);
96 96
97 outb(host->unlock_code, host->config); 97 outb(host->unlock_code, host->config);
98 outb(host->unlock_code, host->config); 98 outb(host->unlock_code, host->config);
99} 99}
@@ -101,14 +101,14 @@ static inline void wbsd_unlock_config(struct wbsd_host* host)
101static inline void wbsd_lock_config(struct wbsd_host* host) 101static inline void wbsd_lock_config(struct wbsd_host* host)
102{ 102{
103 BUG_ON(host->config == 0); 103 BUG_ON(host->config == 0);
104 104
105 outb(LOCK_CODE, host->config); 105 outb(LOCK_CODE, host->config);
106} 106}
107 107
108static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value) 108static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value)
109{ 109{
110 BUG_ON(host->config == 0); 110 BUG_ON(host->config == 0);
111 111
112 outb(reg, host->config); 112 outb(reg, host->config);
113 outb(value, host->config + 1); 113 outb(value, host->config + 1);
114} 114}
@@ -116,7 +116,7 @@ static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value)
116static inline u8 wbsd_read_config(struct wbsd_host* host, u8 reg) 116static inline u8 wbsd_read_config(struct wbsd_host* host, u8 reg)
117{ 117{
118 BUG_ON(host->config == 0); 118 BUG_ON(host->config == 0);
119 119
120 outb(reg, host->config); 120 outb(reg, host->config);
121 return inb(host->config + 1); 121 return inb(host->config + 1);
122} 122}
@@ -140,21 +140,21 @@ static inline u8 wbsd_read_index(struct wbsd_host* host, u8 index)
140static void wbsd_init_device(struct wbsd_host* host) 140static void wbsd_init_device(struct wbsd_host* host)
141{ 141{
142 u8 setup, ier; 142 u8 setup, ier;
143 143
144 /* 144 /*
145 * Reset chip (SD/MMC part) and fifo. 145 * Reset chip (SD/MMC part) and fifo.
146 */ 146 */
147 setup = wbsd_read_index(host, WBSD_IDX_SETUP); 147 setup = wbsd_read_index(host, WBSD_IDX_SETUP);
148 setup |= WBSD_FIFO_RESET | WBSD_SOFT_RESET; 148 setup |= WBSD_FIFO_RESET | WBSD_SOFT_RESET;
149 wbsd_write_index(host, WBSD_IDX_SETUP, setup); 149 wbsd_write_index(host, WBSD_IDX_SETUP, setup);
150 150
151 /* 151 /*
152 * Set DAT3 to input 152 * Set DAT3 to input
153 */ 153 */
154 setup &= ~WBSD_DAT3_H; 154 setup &= ~WBSD_DAT3_H;
155 wbsd_write_index(host, WBSD_IDX_SETUP, setup); 155 wbsd_write_index(host, WBSD_IDX_SETUP, setup);
156 host->flags &= ~WBSD_FIGNORE_DETECT; 156 host->flags &= ~WBSD_FIGNORE_DETECT;
157 157
158 /* 158 /*
159 * Read back default clock. 159 * Read back default clock.
160 */ 160 */
@@ -164,12 +164,12 @@ static void wbsd_init_device(struct wbsd_host* host)
164 * Power down port. 164 * Power down port.
165 */ 165 */
166 outb(WBSD_POWER_N, host->base + WBSD_CSR); 166 outb(WBSD_POWER_N, host->base + WBSD_CSR);
167 167
168 /* 168 /*
169 * Set maximum timeout. 169 * Set maximum timeout.
170 */ 170 */
171 wbsd_write_index(host, WBSD_IDX_TAAC, 0x7F); 171 wbsd_write_index(host, WBSD_IDX_TAAC, 0x7F);
172 172
173 /* 173 /*
174 * Test for card presence 174 * Test for card presence
175 */ 175 */
@@ -177,7 +177,7 @@ static void wbsd_init_device(struct wbsd_host* host)
177 host->flags |= WBSD_FCARD_PRESENT; 177 host->flags |= WBSD_FCARD_PRESENT;
178 else 178 else
179 host->flags &= ~WBSD_FCARD_PRESENT; 179 host->flags &= ~WBSD_FCARD_PRESENT;
180 180
181 /* 181 /*
182 * Enable interesting interrupts. 182 * Enable interesting interrupts.
183 */ 183 */
@@ -200,9 +200,9 @@ static void wbsd_init_device(struct wbsd_host* host)
200static void wbsd_reset(struct wbsd_host* host) 200static void wbsd_reset(struct wbsd_host* host)
201{ 201{
202 u8 setup; 202 u8 setup;
203 203
204 printk(KERN_ERR DRIVER_NAME ": Resetting chip\n"); 204 printk(KERN_ERR DRIVER_NAME ": Resetting chip\n");
205 205
206 /* 206 /*
207 * Soft reset of chip (SD/MMC part). 207 * Soft reset of chip (SD/MMC part).
208 */ 208 */
@@ -214,9 +214,9 @@ static void wbsd_reset(struct wbsd_host* host)
214static void wbsd_request_end(struct wbsd_host* host, struct mmc_request* mrq) 214static void wbsd_request_end(struct wbsd_host* host, struct mmc_request* mrq)
215{ 215{
216 unsigned long dmaflags; 216 unsigned long dmaflags;
217 217
218 DBGF("Ending request, cmd (%x)\n", mrq->cmd->opcode); 218 DBGF("Ending request, cmd (%x)\n", mrq->cmd->opcode);
219 219
220 if (host->dma >= 0) 220 if (host->dma >= 0)
221 { 221 {
222 /* 222 /*
@@ -232,7 +232,7 @@ static void wbsd_request_end(struct wbsd_host* host, struct mmc_request* mrq)
232 */ 232 */
233 wbsd_write_index(host, WBSD_IDX_DMA, 0); 233 wbsd_write_index(host, WBSD_IDX_DMA, 0);
234 } 234 }
235 235
236 host->mrq = NULL; 236 host->mrq = NULL;
237 237
238 /* 238 /*
@@ -275,7 +275,7 @@ static inline int wbsd_next_sg(struct wbsd_host* host)
275 host->offset = 0; 275 host->offset = 0;
276 host->remain = host->cur_sg->length; 276 host->remain = host->cur_sg->length;
277 } 277 }
278 278
279 return host->num_sg; 279 return host->num_sg;
280} 280}
281 281
@@ -297,12 +297,12 @@ static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data)
297 struct scatterlist* sg; 297 struct scatterlist* sg;
298 char* dmabuf = host->dma_buffer; 298 char* dmabuf = host->dma_buffer;
299 char* sgbuf; 299 char* sgbuf;
300 300
301 size = host->size; 301 size = host->size;
302 302
303 sg = data->sg; 303 sg = data->sg;
304 len = data->sg_len; 304 len = data->sg_len;
305 305
306 /* 306 /*
307 * Just loop through all entries. Size might not 307 * Just loop through all entries. Size might not
308 * be the entire list though so make sure that 308 * be the entire list though so make sure that
@@ -317,23 +317,23 @@ static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data)
317 memcpy(dmabuf, sgbuf, sg[i].length); 317 memcpy(dmabuf, sgbuf, sg[i].length);
318 kunmap_atomic(sgbuf, KM_BIO_SRC_IRQ); 318 kunmap_atomic(sgbuf, KM_BIO_SRC_IRQ);
319 dmabuf += sg[i].length; 319 dmabuf += sg[i].length;
320 320
321 if (size < sg[i].length) 321 if (size < sg[i].length)
322 size = 0; 322 size = 0;
323 else 323 else
324 size -= sg[i].length; 324 size -= sg[i].length;
325 325
326 if (size == 0) 326 if (size == 0)
327 break; 327 break;
328 } 328 }
329 329
330 /* 330 /*
331 * Check that we didn't get a request to transfer 331 * Check that we didn't get a request to transfer
332 * more data than can fit into the SG list. 332 * more data than can fit into the SG list.
333 */ 333 */
334 334
335 BUG_ON(size != 0); 335 BUG_ON(size != 0);
336 336
337 host->size -= size; 337 host->size -= size;
338} 338}
339 339
@@ -343,12 +343,12 @@ static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data)
343 struct scatterlist* sg; 343 struct scatterlist* sg;
344 char* dmabuf = host->dma_buffer; 344 char* dmabuf = host->dma_buffer;
345 char* sgbuf; 345 char* sgbuf;
346 346
347 size = host->size; 347 size = host->size;
348 348
349 sg = data->sg; 349 sg = data->sg;
350 len = data->sg_len; 350 len = data->sg_len;
351 351
352 /* 352 /*
353 * Just loop through all entries. Size might not 353 * Just loop through all entries. Size might not
354 * be the entire list though so make sure that 354 * be the entire list though so make sure that
@@ -363,30 +363,30 @@ static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data)
363 memcpy(sgbuf, dmabuf, sg[i].length); 363 memcpy(sgbuf, dmabuf, sg[i].length);
364 kunmap_atomic(sgbuf, KM_BIO_SRC_IRQ); 364 kunmap_atomic(sgbuf, KM_BIO_SRC_IRQ);
365 dmabuf += sg[i].length; 365 dmabuf += sg[i].length;
366 366
367 if (size < sg[i].length) 367 if (size < sg[i].length)
368 size = 0; 368 size = 0;
369 else 369 else
370 size -= sg[i].length; 370 size -= sg[i].length;
371 371
372 if (size == 0) 372 if (size == 0)
373 break; 373 break;
374 } 374 }
375 375
376 /* 376 /*
377 * Check that we didn't get a request to transfer 377 * Check that we didn't get a request to transfer
378 * more data than can fit into the SG list. 378 * more data than can fit into the SG list.
379 */ 379 */
380 380
381 BUG_ON(size != 0); 381 BUG_ON(size != 0);
382 382
383 host->size -= size; 383 host->size -= size;
384} 384}
385 385
386/* 386/*
387 * Command handling 387 * Command handling
388 */ 388 */
389 389
390static inline void wbsd_get_short_reply(struct wbsd_host* host, 390static inline void wbsd_get_short_reply(struct wbsd_host* host,
391 struct mmc_command* cmd) 391 struct mmc_command* cmd)
392{ 392{
@@ -398,7 +398,7 @@ static inline void wbsd_get_short_reply(struct wbsd_host* host,
398 cmd->error = MMC_ERR_INVALID; 398 cmd->error = MMC_ERR_INVALID;
399 return; 399 return;
400 } 400 }
401 401
402 cmd->resp[0] = 402 cmd->resp[0] =
403 wbsd_read_index(host, WBSD_IDX_RESP12) << 24; 403 wbsd_read_index(host, WBSD_IDX_RESP12) << 24;
404 cmd->resp[0] |= 404 cmd->resp[0] |=
@@ -415,7 +415,7 @@ static inline void wbsd_get_long_reply(struct wbsd_host* host,
415 struct mmc_command* cmd) 415 struct mmc_command* cmd)
416{ 416{
417 int i; 417 int i;
418 418
419 /* 419 /*
420 * Correct response type? 420 * Correct response type?
421 */ 421 */
@@ -424,7 +424,7 @@ static inline void wbsd_get_long_reply(struct wbsd_host* host,
424 cmd->error = MMC_ERR_INVALID; 424 cmd->error = MMC_ERR_INVALID;
425 return; 425 return;
426 } 426 }
427 427
428 for (i = 0;i < 4;i++) 428 for (i = 0;i < 4;i++)
429 { 429 {
430 cmd->resp[i] = 430 cmd->resp[i] =
@@ -442,7 +442,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
442{ 442{
443 int i; 443 int i;
444 u8 status, isr; 444 u8 status, isr;
445 445
446 DBGF("Sending cmd (%x)\n", cmd->opcode); 446 DBGF("Sending cmd (%x)\n", cmd->opcode);
447 447
448 /* 448 /*
@@ -451,16 +451,16 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
451 * transfer. 451 * transfer.
452 */ 452 */
453 host->isr = 0; 453 host->isr = 0;
454 454
455 /* 455 /*
456 * Send the command (CRC calculated by host). 456 * Send the command (CRC calculated by host).
457 */ 457 */
458 outb(cmd->opcode, host->base + WBSD_CMDR); 458 outb(cmd->opcode, host->base + WBSD_CMDR);
459 for (i = 3;i >= 0;i--) 459 for (i = 3;i >= 0;i--)
460 outb((cmd->arg >> (i * 8)) & 0xff, host->base + WBSD_CMDR); 460 outb((cmd->arg >> (i * 8)) & 0xff, host->base + WBSD_CMDR);
461 461
462 cmd->error = MMC_ERR_NONE; 462 cmd->error = MMC_ERR_NONE;
463 463
464 /* 464 /*
465 * Wait for the request to complete. 465 * Wait for the request to complete.
466 */ 466 */
@@ -477,7 +477,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
477 * Read back status. 477 * Read back status.
478 */ 478 */
479 isr = host->isr; 479 isr = host->isr;
480 480
481 /* Card removed? */ 481 /* Card removed? */
482 if (isr & WBSD_INT_CARD) 482 if (isr & WBSD_INT_CARD)
483 cmd->error = MMC_ERR_TIMEOUT; 483 cmd->error = MMC_ERR_TIMEOUT;
@@ -509,13 +509,13 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
509 struct mmc_data* data = host->mrq->cmd->data; 509 struct mmc_data* data = host->mrq->cmd->data;
510 char* buffer; 510 char* buffer;
511 int i, fsr, fifo; 511 int i, fsr, fifo;
512 512
513 /* 513 /*
514 * Handle excessive data. 514 * Handle excessive data.
515 */ 515 */
516 if (data->bytes_xfered == host->size) 516 if (data->bytes_xfered == host->size)
517 return; 517 return;
518 518
519 buffer = wbsd_kmap_sg(host) + host->offset; 519 buffer = wbsd_kmap_sg(host) + host->offset;
520 520
521 /* 521 /*
@@ -527,14 +527,14 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
527 /* 527 /*
528 * The size field in the FSR is broken so we have to 528 * The size field in the FSR is broken so we have to
529 * do some guessing. 529 * do some guessing.
530 */ 530 */
531 if (fsr & WBSD_FIFO_FULL) 531 if (fsr & WBSD_FIFO_FULL)
532 fifo = 16; 532 fifo = 16;
533 else if (fsr & WBSD_FIFO_FUTHRE) 533 else if (fsr & WBSD_FIFO_FUTHRE)
534 fifo = 8; 534 fifo = 8;
535 else 535 else
536 fifo = 1; 536 fifo = 1;
537 537
538 for (i = 0;i < fifo;i++) 538 for (i = 0;i < fifo;i++)
539 { 539 {
540 *buffer = inb(host->base + WBSD_DFR); 540 *buffer = inb(host->base + WBSD_DFR);
@@ -543,23 +543,23 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
543 host->remain--; 543 host->remain--;
544 544
545 data->bytes_xfered++; 545 data->bytes_xfered++;
546 546
547 /* 547 /*
548 * Transfer done? 548 * Transfer done?
549 */ 549 */
550 if (data->bytes_xfered == host->size) 550 if (data->bytes_xfered == host->size)
551 { 551 {
552 wbsd_kunmap_sg(host); 552 wbsd_kunmap_sg(host);
553 return; 553 return;
554 } 554 }
555 555
556 /* 556 /*
557 * End of scatter list entry? 557 * End of scatter list entry?
558 */ 558 */
559 if (host->remain == 0) 559 if (host->remain == 0)
560 { 560 {
561 wbsd_kunmap_sg(host); 561 wbsd_kunmap_sg(host);
562 562
563 /* 563 /*
564 * Get next entry. Check if last. 564 * Get next entry. Check if last.
565 */ 565 */
@@ -572,17 +572,17 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
572 * into the scatter list. 572 * into the scatter list.
573 */ 573 */
574 BUG_ON(1); 574 BUG_ON(1);
575 575
576 host->size = data->bytes_xfered; 576 host->size = data->bytes_xfered;
577 577
578 return; 578 return;
579 } 579 }
580 580
581 buffer = wbsd_kmap_sg(host); 581 buffer = wbsd_kmap_sg(host);
582 } 582 }
583 } 583 }
584 } 584 }
585 585
586 wbsd_kunmap_sg(host); 586 wbsd_kunmap_sg(host);
587 587
588 /* 588 /*
@@ -599,7 +599,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
599 struct mmc_data* data = host->mrq->cmd->data; 599 struct mmc_data* data = host->mrq->cmd->data;
600 char* buffer; 600 char* buffer;
601 int i, fsr, fifo; 601 int i, fsr, fifo;
602 602
603 /* 603 /*
604 * Check that we aren't being called after the 604 * Check that we aren't being called after the
605 * entire buffer has been transfered. 605 * entire buffer has been transfered.
@@ -618,7 +618,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
618 /* 618 /*
619 * The size field in the FSR is broken so we have to 619 * The size field in the FSR is broken so we have to
620 * do some guessing. 620 * do some guessing.
621 */ 621 */
622 if (fsr & WBSD_FIFO_EMPTY) 622 if (fsr & WBSD_FIFO_EMPTY)
623 fifo = 0; 623 fifo = 0;
624 else if (fsr & WBSD_FIFO_EMTHRE) 624 else if (fsr & WBSD_FIFO_EMTHRE)
@@ -632,9 +632,9 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
632 buffer++; 632 buffer++;
633 host->offset++; 633 host->offset++;
634 host->remain--; 634 host->remain--;
635 635
636 data->bytes_xfered++; 636 data->bytes_xfered++;
637 637
638 /* 638 /*
639 * Transfer done? 639 * Transfer done?
640 */ 640 */
@@ -650,7 +650,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
650 if (host->remain == 0) 650 if (host->remain == 0)
651 { 651 {
652 wbsd_kunmap_sg(host); 652 wbsd_kunmap_sg(host);
653 653
654 /* 654 /*
655 * Get next entry. Check if last. 655 * Get next entry. Check if last.
656 */ 656 */
@@ -663,19 +663,19 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
663 * into the scatter list. 663 * into the scatter list.
664 */ 664 */
665 BUG_ON(1); 665 BUG_ON(1);
666 666
667 host->size = data->bytes_xfered; 667 host->size = data->bytes_xfered;
668 668
669 return; 669 return;
670 } 670 }
671 671
672 buffer = wbsd_kmap_sg(host); 672 buffer = wbsd_kmap_sg(host);
673 } 673 }
674 } 674 }
675 } 675 }
676 676
677 wbsd_kunmap_sg(host); 677 wbsd_kunmap_sg(host);
678 678
679 /* 679 /*
680 * The controller stops sending interrupts for 680 * The controller stops sending interrupts for
681 * 'FIFO empty' under certain conditions. So we 681 * 'FIFO empty' under certain conditions. So we
@@ -694,7 +694,7 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
694 1 << data->blksz_bits, data->blocks, data->flags); 694 1 << data->blksz_bits, data->blocks, data->flags);
695 DBGF("tsac %d ms nsac %d clk\n", 695 DBGF("tsac %d ms nsac %d clk\n",
696 data->timeout_ns / 1000000, data->timeout_clks); 696 data->timeout_ns / 1000000, data->timeout_clks);
697 697
698 /* 698 /*
699 * Calculate size. 699 * Calculate size.
700 */ 700 */
@@ -708,12 +708,12 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
708 wbsd_write_index(host, WBSD_IDX_TAAC, 127); 708 wbsd_write_index(host, WBSD_IDX_TAAC, 127);
709 else 709 else
710 wbsd_write_index(host, WBSD_IDX_TAAC, data->timeout_ns/1000000); 710 wbsd_write_index(host, WBSD_IDX_TAAC, data->timeout_ns/1000000);
711 711
712 if (data->timeout_clks > 255) 712 if (data->timeout_clks > 255)
713 wbsd_write_index(host, WBSD_IDX_NSAC, 255); 713 wbsd_write_index(host, WBSD_IDX_NSAC, 255);
714 else 714 else
715 wbsd_write_index(host, WBSD_IDX_NSAC, data->timeout_clks); 715 wbsd_write_index(host, WBSD_IDX_NSAC, data->timeout_clks);
716 716
717 /* 717 /*
718 * Inform the chip of how large blocks will be 718 * Inform the chip of how large blocks will be
719 * sent. It needs this to determine when to 719 * sent. It needs this to determine when to
@@ -732,7 +732,7 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
732 else if (host->bus_width == MMC_BUS_WIDTH_4) 732 else if (host->bus_width == MMC_BUS_WIDTH_4)
733 { 733 {
734 blksize = (1 << data->blksz_bits) + 2 * 4; 734 blksize = (1 << data->blksz_bits) + 2 * 4;
735 735
736 wbsd_write_index(host, WBSD_IDX_PBSMSB, ((blksize >> 4) & 0xF0) 736 wbsd_write_index(host, WBSD_IDX_PBSMSB, ((blksize >> 4) & 0xF0)
737 | WBSD_DATA_WIDTH); 737 | WBSD_DATA_WIDTH);
738 wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF); 738 wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
@@ -751,12 +751,12 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
751 setup = wbsd_read_index(host, WBSD_IDX_SETUP); 751 setup = wbsd_read_index(host, WBSD_IDX_SETUP);
752 setup |= WBSD_FIFO_RESET; 752 setup |= WBSD_FIFO_RESET;
753 wbsd_write_index(host, WBSD_IDX_SETUP, setup); 753 wbsd_write_index(host, WBSD_IDX_SETUP, setup);
754 754
755 /* 755 /*
756 * DMA transfer? 756 * DMA transfer?
757 */ 757 */
758 if (host->dma >= 0) 758 if (host->dma >= 0)
759 { 759 {
760 /* 760 /*
761 * The buffer for DMA is only 64 kB. 761 * The buffer for DMA is only 64 kB.
762 */ 762 */
@@ -766,17 +766,17 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
766 data->error = MMC_ERR_INVALID; 766 data->error = MMC_ERR_INVALID;
767 return; 767 return;
768 } 768 }
769 769
770 /* 770 /*
771 * Transfer data from the SG list to 771 * Transfer data from the SG list to
772 * the DMA buffer. 772 * the DMA buffer.
773 */ 773 */
774 if (data->flags & MMC_DATA_WRITE) 774 if (data->flags & MMC_DATA_WRITE)
775 wbsd_sg_to_dma(host, data); 775 wbsd_sg_to_dma(host, data);
776 776
777 /* 777 /*
778 * Initialise the ISA DMA controller. 778 * Initialise the ISA DMA controller.
779 */ 779 */
780 dmaflags = claim_dma_lock(); 780 dmaflags = claim_dma_lock();
781 disable_dma(host->dma); 781 disable_dma(host->dma);
782 clear_dma_ff(host->dma); 782 clear_dma_ff(host->dma);
@@ -802,17 +802,17 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
802 * output to a minimum. 802 * output to a minimum.
803 */ 803 */
804 host->firsterr = 1; 804 host->firsterr = 1;
805 805
806 /* 806 /*
807 * Initialise the SG list. 807 * Initialise the SG list.
808 */ 808 */
809 wbsd_init_sg(host, data); 809 wbsd_init_sg(host, data);
810 810
811 /* 811 /*
812 * Turn off DMA. 812 * Turn off DMA.
813 */ 813 */
814 wbsd_write_index(host, WBSD_IDX_DMA, 0); 814 wbsd_write_index(host, WBSD_IDX_DMA, 0);
815 815
816 /* 816 /*
817 * Set up FIFO threshold levels (and fill 817 * Set up FIFO threshold levels (and fill
818 * buffer if doing a write). 818 * buffer if doing a write).
@@ -828,8 +828,8 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
828 WBSD_FIFOEN_EMPTY | 8); 828 WBSD_FIFOEN_EMPTY | 8);
829 wbsd_fill_fifo(host); 829 wbsd_fill_fifo(host);
830 } 830 }
831 } 831 }
832 832
833 data->error = MMC_ERR_NONE; 833 data->error = MMC_ERR_NONE;
834} 834}
835 835
@@ -838,7 +838,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
838 unsigned long dmaflags; 838 unsigned long dmaflags;
839 int count; 839 int count;
840 u8 status; 840 u8 status;
841 841
842 WARN_ON(host->mrq == NULL); 842 WARN_ON(host->mrq == NULL);
843 843
844 /* 844 /*
@@ -855,7 +855,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
855 { 855 {
856 status = wbsd_read_index(host, WBSD_IDX_STATUS); 856 status = wbsd_read_index(host, WBSD_IDX_STATUS);
857 } while (status & (WBSD_BLOCK_READ | WBSD_BLOCK_WRITE)); 857 } while (status & (WBSD_BLOCK_READ | WBSD_BLOCK_WRITE));
858 858
859 /* 859 /*
860 * DMA transfer? 860 * DMA transfer?
861 */ 861 */
@@ -865,7 +865,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
865 * Disable DMA on the host. 865 * Disable DMA on the host.
866 */ 866 */
867 wbsd_write_index(host, WBSD_IDX_DMA, 0); 867 wbsd_write_index(host, WBSD_IDX_DMA, 0);
868 868
869 /* 869 /*
870 * Turn of ISA DMA controller. 870 * Turn of ISA DMA controller.
871 */ 871 */
@@ -874,7 +874,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
874 clear_dma_ff(host->dma); 874 clear_dma_ff(host->dma);
875 count = get_dma_residue(host->dma); 875 count = get_dma_residue(host->dma);
876 release_dma_lock(dmaflags); 876 release_dma_lock(dmaflags);
877 877
878 /* 878 /*
879 * Any leftover data? 879 * Any leftover data?
880 */ 880 */
@@ -882,7 +882,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
882 { 882 {
883 printk(KERN_ERR DRIVER_NAME ": Incomplete DMA " 883 printk(KERN_ERR DRIVER_NAME ": Incomplete DMA "
884 "transfer. %d bytes left.\n", count); 884 "transfer. %d bytes left.\n", count);
885 885
886 data->error = MMC_ERR_FAILED; 886 data->error = MMC_ERR_FAILED;
887 } 887 }
888 else 888 else
@@ -893,13 +893,13 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
893 */ 893 */
894 if (data->flags & MMC_DATA_READ) 894 if (data->flags & MMC_DATA_READ)
895 wbsd_dma_to_sg(host, data); 895 wbsd_dma_to_sg(host, data);
896 896
897 data->bytes_xfered = host->size; 897 data->bytes_xfered = host->size;
898 } 898 }
899 } 899 }
900 900
901 DBGF("Ending data transfer (%d bytes)\n", data->bytes_xfered); 901 DBGF("Ending data transfer (%d bytes)\n", data->bytes_xfered);
902 902
903 wbsd_request_end(host, host->mrq); 903 wbsd_request_end(host, host->mrq);
904} 904}
905 905
@@ -924,7 +924,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
924 cmd = mrq->cmd; 924 cmd = mrq->cmd;
925 925
926 host->mrq = mrq; 926 host->mrq = mrq;
927 927
928 /* 928 /*
929 * If there is no card in the slot then 929 * If there is no card in the slot then
930 * timeout immediatly. 930 * timeout immediatly.
@@ -941,18 +941,18 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
941 if (cmd->data) 941 if (cmd->data)
942 { 942 {
943 wbsd_prepare_data(host, cmd->data); 943 wbsd_prepare_data(host, cmd->data);
944 944
945 if (cmd->data->error != MMC_ERR_NONE) 945 if (cmd->data->error != MMC_ERR_NONE)
946 goto done; 946 goto done;
947 } 947 }
948 948
949 wbsd_send_command(host, cmd); 949 wbsd_send_command(host, cmd);
950 950
951 /* 951 /*
952 * If this is a data transfer the request 952 * If this is a data transfer the request
953 * will be finished after the data has 953 * will be finished after the data has
954 * transfered. 954 * transfered.
955 */ 955 */
956 if (cmd->data && (cmd->error == MMC_ERR_NONE)) 956 if (cmd->data && (cmd->error == MMC_ERR_NONE))
957 { 957 {
958 /* 958 /*
@@ -965,7 +965,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
965 965
966 return; 966 return;
967 } 967 }
968 968
969done: 969done:
970 wbsd_request_end(host, mrq); 970 wbsd_request_end(host, mrq);
971 971
@@ -976,7 +976,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
976{ 976{
977 struct wbsd_host* host = mmc_priv(mmc); 977 struct wbsd_host* host = mmc_priv(mmc);
978 u8 clk, setup, pwr; 978 u8 clk, setup, pwr;
979 979
980 DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n", 980 DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
981 ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select, 981 ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select,
982 ios->vdd, ios->bus_width); 982 ios->vdd, ios->bus_width);
@@ -989,7 +989,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
989 */ 989 */
990 if (ios->power_mode == MMC_POWER_OFF) 990 if (ios->power_mode == MMC_POWER_OFF)
991 wbsd_init_device(host); 991 wbsd_init_device(host);
992 992
993 if (ios->clock >= 24000000) 993 if (ios->clock >= 24000000)
994 clk = WBSD_CLK_24M; 994 clk = WBSD_CLK_24M;
995 else if (ios->clock >= 16000000) 995 else if (ios->clock >= 16000000)
@@ -1042,7 +1042,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
1042 mod_timer(&host->ignore_timer, jiffies + HZ/100); 1042 mod_timer(&host->ignore_timer, jiffies + HZ/100);
1043 } 1043 }
1044 wbsd_write_index(host, WBSD_IDX_SETUP, setup); 1044 wbsd_write_index(host, WBSD_IDX_SETUP, setup);
1045 1045
1046 /* 1046 /*
1047 * Store bus width for later. Will be used when 1047 * Store bus width for later. Will be used when
1048 * setting up the data transfer. 1048 * setting up the data transfer.
@@ -1128,7 +1128,7 @@ static inline struct mmc_data* wbsd_get_data(struct wbsd_host* host)
1128 WARN_ON(!host->mrq->cmd->data); 1128 WARN_ON(!host->mrq->cmd->data);
1129 if (!host->mrq->cmd->data) 1129 if (!host->mrq->cmd->data)
1130 return NULL; 1130 return NULL;
1131 1131
1132 return host->mrq->cmd->data; 1132 return host->mrq->cmd->data;
1133} 1133}
1134 1134
@@ -1136,72 +1136,67 @@ static void wbsd_tasklet_card(unsigned long param)
1136{ 1136{
1137 struct wbsd_host* host = (struct wbsd_host*)param; 1137 struct wbsd_host* host = (struct wbsd_host*)param;
1138 u8 csr; 1138 u8 csr;
1139 1139 int delay = -1;
1140
1140 spin_lock(&host->lock); 1141 spin_lock(&host->lock);
1141 1142
1142 if (host->flags & WBSD_FIGNORE_DETECT) 1143 if (host->flags & WBSD_FIGNORE_DETECT)
1143 { 1144 {
1144 spin_unlock(&host->lock); 1145 spin_unlock(&host->lock);
1145 return; 1146 return;
1146 } 1147 }
1147 1148
1148 csr = inb(host->base + WBSD_CSR); 1149 csr = inb(host->base + WBSD_CSR);
1149 WARN_ON(csr == 0xff); 1150 WARN_ON(csr == 0xff);
1150 1151
1151 if (csr & WBSD_CARDPRESENT) 1152 if (csr & WBSD_CARDPRESENT)
1152 { 1153 {
1153 if (!(host->flags & WBSD_FCARD_PRESENT)) 1154 if (!(host->flags & WBSD_FCARD_PRESENT))
1154 { 1155 {
1155 DBG("Card inserted\n"); 1156 DBG("Card inserted\n");
1156 host->flags |= WBSD_FCARD_PRESENT; 1157 host->flags |= WBSD_FCARD_PRESENT;
1157
1158 spin_unlock(&host->lock);
1159 1158
1160 /* 1159 delay = 500;
1161 * Delay card detection to allow electrical connections
1162 * to stabilise.
1163 */
1164 mmc_detect_change(host->mmc, msecs_to_jiffies(500));
1165 } 1160 }
1166 else
1167 spin_unlock(&host->lock);
1168 } 1161 }
1169 else if (host->flags & WBSD_FCARD_PRESENT) 1162 else if (host->flags & WBSD_FCARD_PRESENT)
1170 { 1163 {
1171 DBG("Card removed\n"); 1164 DBG("Card removed\n");
1172 host->flags &= ~WBSD_FCARD_PRESENT; 1165 host->flags &= ~WBSD_FCARD_PRESENT;
1173 1166
1174 if (host->mrq) 1167 if (host->mrq)
1175 { 1168 {
1176 printk(KERN_ERR DRIVER_NAME 1169 printk(KERN_ERR DRIVER_NAME
1177 ": Card removed during transfer!\n"); 1170 ": Card removed during transfer!\n");
1178 wbsd_reset(host); 1171 wbsd_reset(host);
1179 1172
1180 host->mrq->cmd->error = MMC_ERR_FAILED; 1173 host->mrq->cmd->error = MMC_ERR_FAILED;
1181 tasklet_schedule(&host->finish_tasklet); 1174 tasklet_schedule(&host->finish_tasklet);
1182 } 1175 }
1183
1184 /*
1185 * Unlock first since we might get a call back.
1186 */
1187 spin_unlock(&host->lock);
1188 1176
1189 mmc_detect_change(host->mmc, 0); 1177 delay = 0;
1190 } 1178 }
1191 else 1179
1192 spin_unlock(&host->lock); 1180 /*
1181 * Unlock first since we might get a call back.
1182 */
1183
1184 spin_unlock(&host->lock);
1185
1186 if (delay != -1)
1187 mmc_detect_change(host->mmc, msecs_to_jiffies(delay));
1193} 1188}
1194 1189
1195static void wbsd_tasklet_fifo(unsigned long param) 1190static void wbsd_tasklet_fifo(unsigned long param)
1196{ 1191{
1197 struct wbsd_host* host = (struct wbsd_host*)param; 1192 struct wbsd_host* host = (struct wbsd_host*)param;
1198 struct mmc_data* data; 1193 struct mmc_data* data;
1199 1194
1200 spin_lock(&host->lock); 1195 spin_lock(&host->lock);
1201 1196
1202 if (!host->mrq) 1197 if (!host->mrq)
1203 goto end; 1198 goto end;
1204 1199
1205 data = wbsd_get_data(host); 1200 data = wbsd_get_data(host);
1206 if (!data) 1201 if (!data)
1207 goto end; 1202 goto end;
@@ -1220,7 +1215,7 @@ static void wbsd_tasklet_fifo(unsigned long param)
1220 tasklet_schedule(&host->finish_tasklet); 1215 tasklet_schedule(&host->finish_tasklet);
1221 } 1216 }
1222 1217
1223end: 1218end:
1224 spin_unlock(&host->lock); 1219 spin_unlock(&host->lock);
1225} 1220}
1226 1221
@@ -1228,23 +1223,23 @@ static void wbsd_tasklet_crc(unsigned long param)
1228{ 1223{
1229 struct wbsd_host* host = (struct wbsd_host*)param; 1224 struct wbsd_host* host = (struct wbsd_host*)param;
1230 struct mmc_data* data; 1225 struct mmc_data* data;
1231 1226
1232 spin_lock(&host->lock); 1227 spin_lock(&host->lock);
1233 1228
1234 if (!host->mrq) 1229 if (!host->mrq)
1235 goto end; 1230 goto end;
1236 1231
1237 data = wbsd_get_data(host); 1232 data = wbsd_get_data(host);
1238 if (!data) 1233 if (!data)
1239 goto end; 1234 goto end;
1240 1235
1241 DBGF("CRC error\n"); 1236 DBGF("CRC error\n");
1242 1237
1243 data->error = MMC_ERR_BADCRC; 1238 data->error = MMC_ERR_BADCRC;
1244 1239
1245 tasklet_schedule(&host->finish_tasklet); 1240 tasklet_schedule(&host->finish_tasklet);
1246 1241
1247end: 1242end:
1248 spin_unlock(&host->lock); 1243 spin_unlock(&host->lock);
1249} 1244}
1250 1245
@@ -1252,23 +1247,23 @@ static void wbsd_tasklet_timeout(unsigned long param)
1252{ 1247{
1253 struct wbsd_host* host = (struct wbsd_host*)param; 1248 struct wbsd_host* host = (struct wbsd_host*)param;
1254 struct mmc_data* data; 1249 struct mmc_data* data;
1255 1250
1256 spin_lock(&host->lock); 1251 spin_lock(&host->lock);
1257 1252
1258 if (!host->mrq) 1253 if (!host->mrq)
1259 goto end; 1254 goto end;
1260 1255
1261 data = wbsd_get_data(host); 1256 data = wbsd_get_data(host);
1262 if (!data) 1257 if (!data)
1263 goto end; 1258 goto end;
1264 1259
1265 DBGF("Timeout\n"); 1260 DBGF("Timeout\n");
1266 1261
1267 data->error = MMC_ERR_TIMEOUT; 1262 data->error = MMC_ERR_TIMEOUT;
1268 1263
1269 tasklet_schedule(&host->finish_tasklet); 1264 tasklet_schedule(&host->finish_tasklet);
1270 1265
1271end: 1266end:
1272 spin_unlock(&host->lock); 1267 spin_unlock(&host->lock);
1273} 1268}
1274 1269
@@ -1276,20 +1271,20 @@ static void wbsd_tasklet_finish(unsigned long param)
1276{ 1271{
1277 struct wbsd_host* host = (struct wbsd_host*)param; 1272 struct wbsd_host* host = (struct wbsd_host*)param;
1278 struct mmc_data* data; 1273 struct mmc_data* data;
1279 1274
1280 spin_lock(&host->lock); 1275 spin_lock(&host->lock);
1281 1276
1282 WARN_ON(!host->mrq); 1277 WARN_ON(!host->mrq);
1283 if (!host->mrq) 1278 if (!host->mrq)
1284 goto end; 1279 goto end;
1285 1280
1286 data = wbsd_get_data(host); 1281 data = wbsd_get_data(host);
1287 if (!data) 1282 if (!data)
1288 goto end; 1283 goto end;
1289 1284
1290 wbsd_finish_data(host, data); 1285 wbsd_finish_data(host, data);
1291 1286
1292end: 1287end:
1293 spin_unlock(&host->lock); 1288 spin_unlock(&host->lock);
1294} 1289}
1295 1290
@@ -1297,7 +1292,7 @@ static void wbsd_tasklet_block(unsigned long param)
1297{ 1292{
1298 struct wbsd_host* host = (struct wbsd_host*)param; 1293 struct wbsd_host* host = (struct wbsd_host*)param;
1299 struct mmc_data* data; 1294 struct mmc_data* data;
1300 1295
1301 spin_lock(&host->lock); 1296 spin_lock(&host->lock);
1302 1297
1303 if ((wbsd_read_index(host, WBSD_IDX_CRCSTATUS) & WBSD_CRC_MASK) != 1298 if ((wbsd_read_index(host, WBSD_IDX_CRCSTATUS) & WBSD_CRC_MASK) !=
@@ -1306,15 +1301,15 @@ static void wbsd_tasklet_block(unsigned long param)
1306 data = wbsd_get_data(host); 1301 data = wbsd_get_data(host);
1307 if (!data) 1302 if (!data)
1308 goto end; 1303 goto end;
1309 1304
1310 DBGF("CRC error\n"); 1305 DBGF("CRC error\n");
1311 1306
1312 data->error = MMC_ERR_BADCRC; 1307 data->error = MMC_ERR_BADCRC;
1313 1308
1314 tasklet_schedule(&host->finish_tasklet); 1309 tasklet_schedule(&host->finish_tasklet);
1315 } 1310 }
1316 1311
1317end: 1312end:
1318 spin_unlock(&host->lock); 1313 spin_unlock(&host->lock);
1319} 1314}
1320 1315
@@ -1326,7 +1321,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
1326{ 1321{
1327 struct wbsd_host* host = dev_id; 1322 struct wbsd_host* host = dev_id;
1328 int isr; 1323 int isr;
1329 1324
1330 isr = inb(host->base + WBSD_ISR); 1325 isr = inb(host->base + WBSD_ISR);
1331 1326
1332 /* 1327 /*
@@ -1334,7 +1329,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
1334 */ 1329 */
1335 if (isr == 0xff || isr == 0x00) 1330 if (isr == 0xff || isr == 0x00)
1336 return IRQ_NONE; 1331 return IRQ_NONE;
1337 1332
1338 host->isr |= isr; 1333 host->isr |= isr;
1339 1334
1340 /* 1335 /*
@@ -1352,7 +1347,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
1352 tasklet_hi_schedule(&host->block_tasklet); 1347 tasklet_hi_schedule(&host->block_tasklet);
1353 if (isr & WBSD_INT_TC) 1348 if (isr & WBSD_INT_TC)
1354 tasklet_schedule(&host->finish_tasklet); 1349 tasklet_schedule(&host->finish_tasklet);
1355 1350
1356 return IRQ_HANDLED; 1351 return IRQ_HANDLED;
1357} 1352}
1358 1353
@@ -1370,14 +1365,14 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
1370{ 1365{
1371 struct mmc_host* mmc; 1366 struct mmc_host* mmc;
1372 struct wbsd_host* host; 1367 struct wbsd_host* host;
1373 1368
1374 /* 1369 /*
1375 * Allocate MMC structure. 1370 * Allocate MMC structure.
1376 */ 1371 */
1377 mmc = mmc_alloc_host(sizeof(struct wbsd_host), dev); 1372 mmc = mmc_alloc_host(sizeof(struct wbsd_host), dev);
1378 if (!mmc) 1373 if (!mmc)
1379 return -ENOMEM; 1374 return -ENOMEM;
1380 1375
1381 host = mmc_priv(mmc); 1376 host = mmc_priv(mmc);
1382 host->mmc = mmc; 1377 host->mmc = mmc;
1383 1378
@@ -1391,37 +1386,37 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
1391 mmc->f_max = 24000000; 1386 mmc->f_max = 24000000;
1392 mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34; 1387 mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
1393 mmc->caps = MMC_CAP_4_BIT_DATA; 1388 mmc->caps = MMC_CAP_4_BIT_DATA;
1394 1389
1395 spin_lock_init(&host->lock); 1390 spin_lock_init(&host->lock);
1396 1391
1397 /* 1392 /*
1398 * Set up timers 1393 * Set up timers
1399 */ 1394 */
1400 init_timer(&host->ignore_timer); 1395 init_timer(&host->ignore_timer);
1401 host->ignore_timer.data = (unsigned long)host; 1396 host->ignore_timer.data = (unsigned long)host;
1402 host->ignore_timer.function = wbsd_reset_ignore; 1397 host->ignore_timer.function = wbsd_reset_ignore;
1403 1398
1404 /* 1399 /*
1405 * Maximum number of segments. Worst case is one sector per segment 1400 * Maximum number of segments. Worst case is one sector per segment
1406 * so this will be 64kB/512. 1401 * so this will be 64kB/512.
1407 */ 1402 */
1408 mmc->max_hw_segs = 128; 1403 mmc->max_hw_segs = 128;
1409 mmc->max_phys_segs = 128; 1404 mmc->max_phys_segs = 128;
1410 1405
1411 /* 1406 /*
1412 * Maximum number of sectors in one transfer. Also limited by 64kB 1407 * Maximum number of sectors in one transfer. Also limited by 64kB
1413 * buffer. 1408 * buffer.
1414 */ 1409 */
1415 mmc->max_sectors = 128; 1410 mmc->max_sectors = 128;
1416 1411
1417 /* 1412 /*
1418 * Maximum segment size. Could be one segment with the maximum number 1413 * Maximum segment size. Could be one segment with the maximum number
1419 * of segments. 1414 * of segments.
1420 */ 1415 */
1421 mmc->max_seg_size = mmc->max_sectors * 512; 1416 mmc->max_seg_size = mmc->max_sectors * 512;
1422 1417
1423 dev_set_drvdata(dev, mmc); 1418 dev_set_drvdata(dev, mmc);
1424 1419
1425 return 0; 1420 return 0;
1426} 1421}
1427 1422
@@ -1429,18 +1424,18 @@ static void __devexit wbsd_free_mmc(struct device* dev)
1429{ 1424{
1430 struct mmc_host* mmc; 1425 struct mmc_host* mmc;
1431 struct wbsd_host* host; 1426 struct wbsd_host* host;
1432 1427
1433 mmc = dev_get_drvdata(dev); 1428 mmc = dev_get_drvdata(dev);
1434 if (!mmc) 1429 if (!mmc)
1435 return; 1430 return;
1436 1431
1437 host = mmc_priv(mmc); 1432 host = mmc_priv(mmc);
1438 BUG_ON(host == NULL); 1433 BUG_ON(host == NULL);
1439 1434
1440 del_timer_sync(&host->ignore_timer); 1435 del_timer_sync(&host->ignore_timer);
1441 1436
1442 mmc_free_host(mmc); 1437 mmc_free_host(mmc);
1443 1438
1444 dev_set_drvdata(dev, NULL); 1439 dev_set_drvdata(dev, NULL);
1445} 1440}
1446 1441
@@ -1452,7 +1447,7 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
1452{ 1447{
1453 int i, j, k; 1448 int i, j, k;
1454 int id; 1449 int id;
1455 1450
1456 /* 1451 /*
1457 * Iterate through all ports, all codes to 1452 * Iterate through all ports, all codes to
1458 * find hardware that is in our known list. 1453 * find hardware that is in our known list.
@@ -1461,32 +1456,32 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
1461 { 1456 {
1462 if (!request_region(config_ports[i], 2, DRIVER_NAME)) 1457 if (!request_region(config_ports[i], 2, DRIVER_NAME))
1463 continue; 1458 continue;
1464 1459
1465 for (j = 0;j < sizeof(unlock_codes)/sizeof(int);j++) 1460 for (j = 0;j < sizeof(unlock_codes)/sizeof(int);j++)
1466 { 1461 {
1467 id = 0xFFFF; 1462 id = 0xFFFF;
1468 1463
1469 outb(unlock_codes[j], config_ports[i]); 1464 outb(unlock_codes[j], config_ports[i]);
1470 outb(unlock_codes[j], config_ports[i]); 1465 outb(unlock_codes[j], config_ports[i]);
1471 1466
1472 outb(WBSD_CONF_ID_HI, config_ports[i]); 1467 outb(WBSD_CONF_ID_HI, config_ports[i]);
1473 id = inb(config_ports[i] + 1) << 8; 1468 id = inb(config_ports[i] + 1) << 8;
1474 1469
1475 outb(WBSD_CONF_ID_LO, config_ports[i]); 1470 outb(WBSD_CONF_ID_LO, config_ports[i]);
1476 id |= inb(config_ports[i] + 1); 1471 id |= inb(config_ports[i] + 1);
1477 1472
1478 for (k = 0;k < sizeof(valid_ids)/sizeof(int);k++) 1473 for (k = 0;k < sizeof(valid_ids)/sizeof(int);k++)
1479 { 1474 {
1480 if (id == valid_ids[k]) 1475 if (id == valid_ids[k])
1481 { 1476 {
1482 host->chip_id = id; 1477 host->chip_id = id;
1483 host->config = config_ports[i]; 1478 host->config = config_ports[i];
1484 host->unlock_code = unlock_codes[i]; 1479 host->unlock_code = unlock_codes[i];
1485 1480
1486 return 0; 1481 return 0;
1487 } 1482 }
1488 } 1483 }
1489 1484
1490 if (id != 0xFFFF) 1485 if (id != 0xFFFF)
1491 { 1486 {
1492 DBG("Unknown hardware (id %x) found at %x\n", 1487 DBG("Unknown hardware (id %x) found at %x\n",
@@ -1495,10 +1490,10 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
1495 1490
1496 outb(LOCK_CODE, config_ports[i]); 1491 outb(LOCK_CODE, config_ports[i]);
1497 } 1492 }
1498 1493
1499 release_region(config_ports[i], 2); 1494 release_region(config_ports[i], 2);
1500 } 1495 }
1501 1496
1502 return -ENODEV; 1497 return -ENODEV;
1503} 1498}
1504 1499
@@ -1510,12 +1505,12 @@ static int __devinit wbsd_request_region(struct wbsd_host* host, int base)
1510{ 1505{
1511 if (io & 0x7) 1506 if (io & 0x7)
1512 return -EINVAL; 1507 return -EINVAL;
1513 1508
1514 if (!request_region(base, 8, DRIVER_NAME)) 1509 if (!request_region(base, 8, DRIVER_NAME))
1515 return -EIO; 1510 return -EIO;
1516 1511
1517 host->base = io; 1512 host->base = io;
1518 1513
1519 return 0; 1514 return 0;
1520} 1515}
1521 1516
@@ -1523,12 +1518,12 @@ static void __devexit wbsd_release_regions(struct wbsd_host* host)
1523{ 1518{
1524 if (host->base) 1519 if (host->base)
1525 release_region(host->base, 8); 1520 release_region(host->base, 8);
1526 1521
1527 host->base = 0; 1522 host->base = 0;
1528 1523
1529 if (host->config) 1524 if (host->config)
1530 release_region(host->config, 2); 1525 release_region(host->config, 2);
1531 1526
1532 host->config = 0; 1527 host->config = 0;
1533} 1528}
1534 1529
@@ -1540,10 +1535,10 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma)
1540{ 1535{
1541 if (dma < 0) 1536 if (dma < 0)
1542 return; 1537 return;
1543 1538
1544 if (request_dma(dma, DRIVER_NAME)) 1539 if (request_dma(dma, DRIVER_NAME))
1545 goto err; 1540 goto err;
1546 1541
1547 /* 1542 /*
1548 * We need to allocate a special buffer in 1543 * We need to allocate a special buffer in
1549 * order for ISA to be able to DMA to it. 1544 * order for ISA to be able to DMA to it.
@@ -1558,7 +1553,7 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma)
1558 */ 1553 */
1559 host->dma_addr = dma_map_single(host->mmc->dev, host->dma_buffer, 1554 host->dma_addr = dma_map_single(host->mmc->dev, host->dma_buffer,
1560 WBSD_DMA_SIZE, DMA_BIDIRECTIONAL); 1555 WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
1561 1556
1562 /* 1557 /*
1563 * ISA DMA must be aligned on a 64k basis. 1558 * ISA DMA must be aligned on a 64k basis.
1564 */ 1559 */
@@ -1571,19 +1566,19 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma)
1571 goto kfree; 1566 goto kfree;
1572 1567
1573 host->dma = dma; 1568 host->dma = dma;
1574 1569
1575 return; 1570 return;
1576 1571
1577kfree: 1572kfree:
1578 /* 1573 /*
1579 * If we've gotten here then there is some kind of alignment bug 1574 * If we've gotten here then there is some kind of alignment bug
1580 */ 1575 */
1581 BUG_ON(1); 1576 BUG_ON(1);
1582 1577
1583 dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE, 1578 dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE,
1584 DMA_BIDIRECTIONAL); 1579 DMA_BIDIRECTIONAL);
1585 host->dma_addr = (dma_addr_t)NULL; 1580 host->dma_addr = (dma_addr_t)NULL;
1586 1581
1587 kfree(host->dma_buffer); 1582 kfree(host->dma_buffer);
1588 host->dma_buffer = NULL; 1583 host->dma_buffer = NULL;
1589 1584
@@ -1604,7 +1599,7 @@ static void __devexit wbsd_release_dma(struct wbsd_host* host)
1604 kfree(host->dma_buffer); 1599 kfree(host->dma_buffer);
1605 if (host->dma >= 0) 1600 if (host->dma >= 0)
1606 free_dma(host->dma); 1601 free_dma(host->dma);
1607 1602
1608 host->dma = -1; 1603 host->dma = -1;
1609 host->dma_buffer = NULL; 1604 host->dma_buffer = NULL;
1610 host->dma_addr = (dma_addr_t)NULL; 1605 host->dma_addr = (dma_addr_t)NULL;
@@ -1617,7 +1612,7 @@ static void __devexit wbsd_release_dma(struct wbsd_host* host)
1617static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq) 1612static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
1618{ 1613{
1619 int ret; 1614 int ret;
1620 1615
1621 /* 1616 /*
1622 * Allocate interrupt. 1617 * Allocate interrupt.
1623 */ 1618 */
@@ -1625,7 +1620,7 @@ static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
1625 ret = request_irq(irq, wbsd_irq, SA_SHIRQ, DRIVER_NAME, host); 1620 ret = request_irq(irq, wbsd_irq, SA_SHIRQ, DRIVER_NAME, host);
1626 if (ret) 1621 if (ret)
1627 return ret; 1622 return ret;
1628 1623
1629 host->irq = irq; 1624 host->irq = irq;
1630 1625
1631 /* 1626 /*
@@ -1637,7 +1632,7 @@ static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
1637 tasklet_init(&host->timeout_tasklet, wbsd_tasklet_timeout, (unsigned long)host); 1632 tasklet_init(&host->timeout_tasklet, wbsd_tasklet_timeout, (unsigned long)host);
1638 tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish, (unsigned long)host); 1633 tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish, (unsigned long)host);
1639 tasklet_init(&host->block_tasklet, wbsd_tasklet_block, (unsigned long)host); 1634 tasklet_init(&host->block_tasklet, wbsd_tasklet_block, (unsigned long)host);
1640 1635
1641 return 0; 1636 return 0;
1642} 1637}
1643 1638
@@ -1647,9 +1642,9 @@ static void __devexit wbsd_release_irq(struct wbsd_host* host)
1647 return; 1642 return;
1648 1643
1649 free_irq(host->irq, host); 1644 free_irq(host->irq, host);
1650 1645
1651 host->irq = 0; 1646 host->irq = 0;
1652 1647
1653 tasklet_kill(&host->card_tasklet); 1648 tasklet_kill(&host->card_tasklet);
1654 tasklet_kill(&host->fifo_tasklet); 1649 tasklet_kill(&host->fifo_tasklet);
1655 tasklet_kill(&host->crc_tasklet); 1650 tasklet_kill(&host->crc_tasklet);
@@ -1666,7 +1661,7 @@ static int __devinit wbsd_request_resources(struct wbsd_host* host,
1666 int base, int irq, int dma) 1661 int base, int irq, int dma)
1667{ 1662{
1668 int ret; 1663 int ret;
1669 1664
1670 /* 1665 /*
1671 * Allocate I/O ports. 1666 * Allocate I/O ports.
1672 */ 1667 */
@@ -1685,7 +1680,7 @@ static int __devinit wbsd_request_resources(struct wbsd_host* host,
1685 * Allocate DMA. 1680 * Allocate DMA.
1686 */ 1681 */
1687 wbsd_request_dma(host, dma); 1682 wbsd_request_dma(host, dma);
1688 1683
1689 return 0; 1684 return 0;
1690} 1685}
1691 1686
@@ -1708,7 +1703,7 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host)
1708{ 1703{
1709 /* 1704 /*
1710 * Reset the chip. 1705 * Reset the chip.
1711 */ 1706 */
1712 wbsd_write_config(host, WBSD_CONF_SWRST, 1); 1707 wbsd_write_config(host, WBSD_CONF_SWRST, 1);
1713 wbsd_write_config(host, WBSD_CONF_SWRST, 0); 1708 wbsd_write_config(host, WBSD_CONF_SWRST, 0);
1714 1709
@@ -1716,23 +1711,23 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host)
1716 * Select SD/MMC function. 1711 * Select SD/MMC function.
1717 */ 1712 */
1718 wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD); 1713 wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
1719 1714
1720 /* 1715 /*
1721 * Set up card detection. 1716 * Set up card detection.
1722 */ 1717 */
1723 wbsd_write_config(host, WBSD_CONF_PINS, WBSD_PINS_DETECT_GP11); 1718 wbsd_write_config(host, WBSD_CONF_PINS, WBSD_PINS_DETECT_GP11);
1724 1719
1725 /* 1720 /*
1726 * Configure chip 1721 * Configure chip
1727 */ 1722 */
1728 wbsd_write_config(host, WBSD_CONF_PORT_HI, host->base >> 8); 1723 wbsd_write_config(host, WBSD_CONF_PORT_HI, host->base >> 8);
1729 wbsd_write_config(host, WBSD_CONF_PORT_LO, host->base & 0xff); 1724 wbsd_write_config(host, WBSD_CONF_PORT_LO, host->base & 0xff);
1730 1725
1731 wbsd_write_config(host, WBSD_CONF_IRQ, host->irq); 1726 wbsd_write_config(host, WBSD_CONF_IRQ, host->irq);
1732 1727
1733 if (host->dma >= 0) 1728 if (host->dma >= 0)
1734 wbsd_write_config(host, WBSD_CONF_DRQ, host->dma); 1729 wbsd_write_config(host, WBSD_CONF_DRQ, host->dma);
1735 1730
1736 /* 1731 /*
1737 * Enable and power up chip. 1732 * Enable and power up chip.
1738 */ 1733 */
@@ -1743,26 +1738,26 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host)
1743/* 1738/*
1744 * Check that configured resources are correct. 1739 * Check that configured resources are correct.
1745 */ 1740 */
1746 1741
1747static int __devinit wbsd_chip_validate(struct wbsd_host* host) 1742static int __devinit wbsd_chip_validate(struct wbsd_host* host)
1748{ 1743{
1749 int base, irq, dma; 1744 int base, irq, dma;
1750 1745
1751 /* 1746 /*
1752 * Select SD/MMC function. 1747 * Select SD/MMC function.
1753 */ 1748 */
1754 wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD); 1749 wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
1755 1750
1756 /* 1751 /*
1757 * Read configuration. 1752 * Read configuration.
1758 */ 1753 */
1759 base = wbsd_read_config(host, WBSD_CONF_PORT_HI) << 8; 1754 base = wbsd_read_config(host, WBSD_CONF_PORT_HI) << 8;
1760 base |= wbsd_read_config(host, WBSD_CONF_PORT_LO); 1755 base |= wbsd_read_config(host, WBSD_CONF_PORT_LO);
1761 1756
1762 irq = wbsd_read_config(host, WBSD_CONF_IRQ); 1757 irq = wbsd_read_config(host, WBSD_CONF_IRQ);
1763 1758
1764 dma = wbsd_read_config(host, WBSD_CONF_DRQ); 1759 dma = wbsd_read_config(host, WBSD_CONF_DRQ);
1765 1760
1766 /* 1761 /*
1767 * Validate against given configuration. 1762 * Validate against given configuration.
1768 */ 1763 */
@@ -1772,7 +1767,7 @@ static int __devinit wbsd_chip_validate(struct wbsd_host* host)
1772 return 0; 1767 return 0;
1773 if ((dma != host->dma) && (host->dma != -1)) 1768 if ((dma != host->dma) && (host->dma != -1))
1774 return 0; 1769 return 0;
1775 1770
1776 return 1; 1771 return 1;
1777} 1772}
1778 1773
@@ -1788,14 +1783,14 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
1788 struct wbsd_host* host = NULL; 1783 struct wbsd_host* host = NULL;
1789 struct mmc_host* mmc = NULL; 1784 struct mmc_host* mmc = NULL;
1790 int ret; 1785 int ret;
1791 1786
1792 ret = wbsd_alloc_mmc(dev); 1787 ret = wbsd_alloc_mmc(dev);
1793 if (ret) 1788 if (ret)
1794 return ret; 1789 return ret;
1795 1790
1796 mmc = dev_get_drvdata(dev); 1791 mmc = dev_get_drvdata(dev);
1797 host = mmc_priv(mmc); 1792 host = mmc_priv(mmc);
1798 1793
1799 /* 1794 /*
1800 * Scan for hardware. 1795 * Scan for hardware.
1801 */ 1796 */
@@ -1814,7 +1809,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
1814 return ret; 1809 return ret;
1815 } 1810 }
1816 } 1811 }
1817 1812
1818 /* 1813 /*
1819 * Request resources. 1814 * Request resources.
1820 */ 1815 */
@@ -1825,7 +1820,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
1825 wbsd_free_mmc(dev); 1820 wbsd_free_mmc(dev);
1826 return ret; 1821 return ret;
1827 } 1822 }
1828 1823
1829 /* 1824 /*
1830 * See if chip needs to be configured. 1825 * See if chip needs to be configured.
1831 */ 1826 */
@@ -1842,7 +1837,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
1842 } 1837 }
1843 else 1838 else
1844 wbsd_chip_config(host); 1839 wbsd_chip_config(host);
1845 1840
1846 /* 1841 /*
1847 * Power Management stuff. No idea how this works. 1842 * Power Management stuff. No idea how this works.
1848 * Not tested. 1843 * Not tested.
@@ -1860,7 +1855,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
1860 * Reset the chip into a known state. 1855 * Reset the chip into a known state.
1861 */ 1856 */
1862 wbsd_init_device(host); 1857 wbsd_init_device(host);
1863 1858
1864 mmc_add_host(mmc); 1859 mmc_add_host(mmc);
1865 1860
1866 printk(KERN_INFO "%s: W83L51xD", mmc_hostname(mmc)); 1861 printk(KERN_INFO "%s: W83L51xD", mmc_hostname(mmc));
@@ -1882,12 +1877,12 @@ static void __devexit wbsd_shutdown(struct device* dev, int pnp)
1882{ 1877{
1883 struct mmc_host* mmc = dev_get_drvdata(dev); 1878 struct mmc_host* mmc = dev_get_drvdata(dev);
1884 struct wbsd_host* host; 1879 struct wbsd_host* host;
1885 1880
1886 if (!mmc) 1881 if (!mmc)
1887 return; 1882 return;
1888 1883
1889 host = mmc_priv(mmc); 1884 host = mmc_priv(mmc);
1890 1885
1891 mmc_remove_host(mmc); 1886 mmc_remove_host(mmc);
1892 1887
1893 if (!pnp) 1888 if (!pnp)
@@ -1900,9 +1895,9 @@ static void __devexit wbsd_shutdown(struct device* dev, int pnp)
1900 wbsd_write_config(host, WBSD_CONF_ENABLE, 0); 1895 wbsd_write_config(host, WBSD_CONF_ENABLE, 0);
1901 wbsd_lock_config(host); 1896 wbsd_lock_config(host);
1902 } 1897 }
1903 1898
1904 wbsd_release_resources(host); 1899 wbsd_release_resources(host);
1905 1900
1906 wbsd_free_mmc(dev); 1901 wbsd_free_mmc(dev);
1907} 1902}
1908 1903
@@ -1932,7 +1927,7 @@ static int __devinit
1932wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id) 1927wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id)
1933{ 1928{
1934 int io, irq, dma; 1929 int io, irq, dma;
1935 1930
1936 /* 1931 /*
1937 * Get resources from PnP layer. 1932 * Get resources from PnP layer.
1938 */ 1933 */
@@ -1942,9 +1937,9 @@ wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id)
1942 dma = pnp_dma(pnpdev, 0); 1937 dma = pnp_dma(pnpdev, 0);
1943 else 1938 else
1944 dma = -1; 1939 dma = -1;
1945 1940
1946 DBGF("PnP resources: port %3x irq %d dma %d\n", io, irq, dma); 1941 DBGF("PnP resources: port %3x irq %d dma %d\n", io, irq, dma);
1947 1942
1948 return wbsd_init(&pnpdev->dev, io, irq, dma, 1); 1943 return wbsd_init(&pnpdev->dev, io, irq, dma, 1);
1949} 1944}
1950 1945
@@ -1985,7 +1980,7 @@ static struct device_driver wbsd_driver = {
1985 .bus = &platform_bus_type, 1980 .bus = &platform_bus_type,
1986 .probe = wbsd_probe, 1981 .probe = wbsd_probe,
1987 .remove = wbsd_remove, 1982 .remove = wbsd_remove,
1988 1983
1989 .suspend = wbsd_suspend, 1984 .suspend = wbsd_suspend,
1990 .resume = wbsd_resume, 1985 .resume = wbsd_resume,
1991}; 1986};
@@ -2008,7 +2003,7 @@ static struct pnp_driver wbsd_pnp_driver = {
2008static int __init wbsd_drv_init(void) 2003static int __init wbsd_drv_init(void)
2009{ 2004{
2010 int result; 2005 int result;
2011 2006
2012 printk(KERN_INFO DRIVER_NAME 2007 printk(KERN_INFO DRIVER_NAME
2013 ": Winbond W83L51xD SD/MMC card interface driver, " 2008 ": Winbond W83L51xD SD/MMC card interface driver, "
2014 DRIVER_VERSION "\n"); 2009 DRIVER_VERSION "\n");
@@ -2023,8 +2018,8 @@ static int __init wbsd_drv_init(void)
2023 return result; 2018 return result;
2024 } 2019 }
2025 2020
2026#endif /* CONFIG_PNP */ 2021#endif /* CONFIG_PNP */
2027 2022
2028 if (nopnp) 2023 if (nopnp)
2029 { 2024 {
2030 result = driver_register(&wbsd_driver); 2025 result = driver_register(&wbsd_driver);
@@ -2046,13 +2041,13 @@ static void __exit wbsd_drv_exit(void)
2046 2041
2047 if (!nopnp) 2042 if (!nopnp)
2048 pnp_unregister_driver(&wbsd_pnp_driver); 2043 pnp_unregister_driver(&wbsd_pnp_driver);
2049 2044
2050#endif /* CONFIG_PNP */ 2045#endif /* CONFIG_PNP */
2051 2046
2052 if (nopnp) 2047 if (nopnp)
2053 { 2048 {
2054 platform_device_unregister(wbsd_device); 2049 platform_device_unregister(wbsd_device);
2055 2050
2056 driver_unregister(&wbsd_driver); 2051 driver_unregister(&wbsd_driver);
2057 } 2052 }
2058 2053
diff --git a/drivers/mmc/wbsd.h b/drivers/mmc/wbsd.h
index 9005b5241b3c..249baa701cb0 100644
--- a/drivers/mmc/wbsd.h
+++ b/drivers/mmc/wbsd.h
@@ -139,51 +139,50 @@
139struct wbsd_host 139struct wbsd_host
140{ 140{
141 struct mmc_host* mmc; /* MMC structure */ 141 struct mmc_host* mmc; /* MMC structure */
142 142
143 spinlock_t lock; /* Mutex */ 143 spinlock_t lock; /* Mutex */
144 144
145 int flags; /* Driver states */ 145 int flags; /* Driver states */
146 146
147#define WBSD_FCARD_PRESENT (1<<0) /* Card is present */ 147#define WBSD_FCARD_PRESENT (1<<0) /* Card is present */
148#define WBSD_FIGNORE_DETECT (1<<1) /* Ignore card detection */ 148#define WBSD_FIGNORE_DETECT (1<<1) /* Ignore card detection */
149 149
150 struct mmc_request* mrq; /* Current request */ 150 struct mmc_request* mrq; /* Current request */
151 151
152 u8 isr; /* Accumulated ISR */ 152 u8 isr; /* Accumulated ISR */
153 153
154 struct scatterlist* cur_sg; /* Current SG entry */ 154 struct scatterlist* cur_sg; /* Current SG entry */
155 unsigned int num_sg; /* Number of entries left */ 155 unsigned int num_sg; /* Number of entries left */
156 void* mapped_sg; /* vaddr of mapped sg */ 156 void* mapped_sg; /* vaddr of mapped sg */
157 157
158 unsigned int offset; /* Offset into current entry */ 158 unsigned int offset; /* Offset into current entry */
159 unsigned int remain; /* Data left in curren entry */ 159 unsigned int remain; /* Data left in curren entry */
160 160
161 int size; /* Total size of transfer */ 161 int size; /* Total size of transfer */
162 162
163 char* dma_buffer; /* ISA DMA buffer */ 163 char* dma_buffer; /* ISA DMA buffer */
164 dma_addr_t dma_addr; /* Physical address for same */ 164 dma_addr_t dma_addr; /* Physical address for same */
165 165
166 int firsterr; /* See fifo functions */ 166 int firsterr; /* See fifo functions */
167 167
168 u8 clk; /* Current clock speed */ 168 u8 clk; /* Current clock speed */
169 unsigned char bus_width; /* Current bus width */ 169 unsigned char bus_width; /* Current bus width */
170 170
171 int config; /* Config port */ 171 int config; /* Config port */
172 u8 unlock_code; /* Code to unlock config */ 172 u8 unlock_code; /* Code to unlock config */
173 173
174 int chip_id; /* ID of controller */ 174 int chip_id; /* ID of controller */
175 175
176 int base; /* I/O port base */ 176 int base; /* I/O port base */
177 int irq; /* Interrupt */ 177 int irq; /* Interrupt */
178 int dma; /* DMA channel */ 178 int dma; /* DMA channel */
179 179
180 struct tasklet_struct card_tasklet; /* Tasklet structures */ 180 struct tasklet_struct card_tasklet; /* Tasklet structures */
181 struct tasklet_struct fifo_tasklet; 181 struct tasklet_struct fifo_tasklet;
182 struct tasklet_struct crc_tasklet; 182 struct tasklet_struct crc_tasklet;
183 struct tasklet_struct timeout_tasklet; 183 struct tasklet_struct timeout_tasklet;
184 struct tasklet_struct finish_tasklet; 184 struct tasklet_struct finish_tasklet;
185 struct tasklet_struct block_tasklet; 185 struct tasklet_struct block_tasklet;
186 186
187 struct timer_list detect_timer; /* Card detection timer */
188 struct timer_list ignore_timer; /* Ignore detection timer */ 187 struct timer_list ignore_timer; /* Ignore detection timer */
189}; 188};
diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c
index 811d92e5f5b1..cc372136e852 100644
--- a/drivers/mtd/maps/uclinux.c
+++ b/drivers/mtd/maps/uclinux.c
@@ -25,9 +25,6 @@
25 25
26/****************************************************************************/ 26/****************************************************************************/
27 27
28
29/****************************************************************************/
30
31struct map_info uclinux_ram_map = { 28struct map_info uclinux_ram_map = {
32 .name = "RAM", 29 .name = "RAM",
33}; 30};
@@ -60,14 +57,15 @@ int __init uclinux_mtd_init(void)
60 struct mtd_info *mtd; 57 struct mtd_info *mtd;
61 struct map_info *mapp; 58 struct map_info *mapp;
62 extern char _ebss; 59 extern char _ebss;
60 unsigned long addr = (unsigned long) &_ebss;
63 61
64 mapp = &uclinux_ram_map; 62 mapp = &uclinux_ram_map;
65 mapp->phys = (unsigned long) &_ebss; 63 mapp->phys = addr;
66 mapp->size = PAGE_ALIGN(*((unsigned long *)((&_ebss) + 8))); 64 mapp->size = PAGE_ALIGN(ntohl(*((unsigned long *)(addr + 8))));
67 mapp->bankwidth = 4; 65 mapp->bankwidth = 4;
68 66
69 printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n", 67 printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n",
70 (int) mapp->map_priv_2, (int) mapp->size); 68 (int) mapp->phys, (int) mapp->size);
71 69
72 mapp->virt = ioremap_nocache(mapp->phys, mapp->size); 70 mapp->virt = ioremap_nocache(mapp->phys, mapp->size);
73 71
@@ -95,7 +93,6 @@ int __init uclinux_mtd_init(void)
95 printk("uclinux[mtd]: set %s to be root filesystem\n", 93 printk("uclinux[mtd]: set %s to be root filesystem\n",
96 uclinux_romfs[0].name); 94 uclinux_romfs[0].name);
97 ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 0); 95 ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 0);
98 put_mtd_device(mtd);
99 96
100 return(0); 97 return(0);
101} 98}
@@ -109,7 +106,7 @@ void __exit uclinux_mtd_cleanup(void)
109 map_destroy(uclinux_ram_mtdinfo); 106 map_destroy(uclinux_ram_mtdinfo);
110 uclinux_ram_mtdinfo = NULL; 107 uclinux_ram_mtdinfo = NULL;
111 } 108 }
112 if (uclinux_ram_map.map_priv_1) { 109 if (uclinux_ram_map.virt) {
113 iounmap((void *) uclinux_ram_map.virt); 110 iounmap((void *) uclinux_ram_map.virt);
114 uclinux_ram_map.virt = 0; 111 uclinux_ram_map.virt = 0;
115 } 112 }
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 6bb9232514b4..54fff9c2e802 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1738,11 +1738,18 @@ config 68360_ENET
1738 the Motorola 68360 processor. 1738 the Motorola 68360 processor.
1739 1739
1740config FEC 1740config FEC
1741 bool "FEC ethernet controller (of ColdFire 5272)" 1741 bool "FEC ethernet controller (of ColdFire CPUs)"
1742 depends on M5272 || M5282 1742 depends on M523x || M527x || M5272 || M528x
1743 help 1743 help
1744 Say Y here if you want to use the built-in 10/100 Fast ethernet 1744 Say Y here if you want to use the built-in 10/100 Fast ethernet
1745 controller on the Motorola ColdFire 5272 processor. 1745 controller on some Motorola ColdFire processors.
1746
1747config FEC2
1748 bool "Second FEC ethernet controller (on some ColdFire CPUs)"
1749 depends on FEC
1750 help
1751 Say Y here if you want to use the second built-in 10/100 Fast
1752 ethernet controller on some Motorola ColdFire processors.
1746 1753
1747config NE_H8300 1754config NE_H8300
1748 tristate "NE2000 compatible support for H8/300" 1755 tristate "NE2000 compatible support for H8/300"
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 2c7008491378..85504fb900da 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -8,7 +8,7 @@
8 * describes connections using the internal parallel port I/O, which 8 * describes connections using the internal parallel port I/O, which
9 * is basically all of Port D. 9 * is basically all of Port D.
10 * 10 *
11 * Right now, I am very watseful with the buffers. I allocate memory 11 * Right now, I am very wasteful with the buffers. I allocate memory
12 * pages and then divide them into 2K frame buffers. This way I know I 12 * pages and then divide them into 2K frame buffers. This way I know I
13 * have buffers large enough to hold one frame within one buffer descriptor. 13 * have buffers large enough to hold one frame within one buffer descriptor.
14 * Once I get this working, I will use 64 or 128 byte CPM buffers, which 14 * Once I get this working, I will use 64 or 128 byte CPM buffers, which
@@ -19,7 +19,10 @@
19 * Copyright (c) 2000 Ericsson Radio Systems AB. 19 * Copyright (c) 2000 Ericsson Radio Systems AB.
20 * 20 *
21 * Support for FEC controller of ColdFire/5270/5271/5272/5274/5275/5280/5282. 21 * Support for FEC controller of ColdFire/5270/5271/5272/5274/5275/5280/5282.
22 * Copyrught (c) 2001-2004 Greg Ungerer (gerg@snapgear.com) 22 * Copyright (c) 2001-2004 Greg Ungerer (gerg@snapgear.com)
23 *
24 * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be)
25 * Copyright (c) 2004-2005 Macq Electronique SA.
23 */ 26 */
24 27
25#include <linux/config.h> 28#include <linux/config.h>
@@ -46,7 +49,8 @@
46#include <asm/io.h> 49#include <asm/io.h>
47#include <asm/pgtable.h> 50#include <asm/pgtable.h>
48 51
49#if defined(CONFIG_M527x) || defined(CONFIG_M5272) || defined(CONFIG_M528x) 52#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \
53 defined(CONFIG_M5272) || defined(CONFIG_M528x)
50#include <asm/coldfire.h> 54#include <asm/coldfire.h>
51#include <asm/mcfsim.h> 55#include <asm/mcfsim.h>
52#include "fec.h" 56#include "fec.h"
@@ -71,7 +75,7 @@ static unsigned int fec_hw[] = {
71#elif defined(CONFIG_M527x) 75#elif defined(CONFIG_M527x)
72 (MCF_MBAR + 0x1000), 76 (MCF_MBAR + 0x1000),
73 (MCF_MBAR + 0x1800), 77 (MCF_MBAR + 0x1800),
74#elif defined(CONFIG_M528x) 78#elif defined(CONFIG_M523x) || defined(CONFIG_M528x)
75 (MCF_MBAR + 0x1000), 79 (MCF_MBAR + 0x1000),
76#else 80#else
77 &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec), 81 &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec),
@@ -94,12 +98,14 @@ static unsigned char fec_mac_default[] = {
94#define FEC_FLASHMAC 0xffe04000 98#define FEC_FLASHMAC 0xffe04000
95#elif defined(CONFIG_CANCam) 99#elif defined(CONFIG_CANCam)
96#define FEC_FLASHMAC 0xf0020000 100#define FEC_FLASHMAC 0xf0020000
101#elif defined (CONFIG_M5272C3)
102#define FEC_FLASHMAC (0xffe04000 + 4)
103#elif defined(CONFIG_MOD5272)
104#define FEC_FLASHMAC 0xffc0406b
97#else 105#else
98#define FEC_FLASHMAC 0 106#define FEC_FLASHMAC 0
99#endif 107#endif
100 108
101unsigned char *fec_flashmac = (unsigned char *) FEC_FLASHMAC;
102
103/* Forward declarations of some structures to support different PHYs 109/* Forward declarations of some structures to support different PHYs
104*/ 110*/
105 111
@@ -158,7 +164,7 @@ typedef struct {
158 * size bits. Other FEC hardware does not, so we need to take that into 164 * size bits. Other FEC hardware does not, so we need to take that into
159 * account when setting it. 165 * account when setting it.
160 */ 166 */
161#if defined(CONFIG_M527x) || defined(CONFIG_M528x) 167#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
162#define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) 168#define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16)
163#else 169#else
164#define OPT_FRAME_SIZE 0 170#define OPT_FRAME_SIZE 0
@@ -196,7 +202,7 @@ struct fec_enet_private {
196 uint phy_id_done; 202 uint phy_id_done;
197 uint phy_status; 203 uint phy_status;
198 uint phy_speed; 204 uint phy_speed;
199 phy_info_t *phy; 205 phy_info_t const *phy;
200 struct work_struct phy_task; 206 struct work_struct phy_task;
201 207
202 uint sequence_done; 208 uint sequence_done;
@@ -209,7 +215,6 @@ struct fec_enet_private {
209 int link; 215 int link;
210 int old_link; 216 int old_link;
211 int full_duplex; 217 int full_duplex;
212 unsigned char mac_addr[ETH_ALEN];
213}; 218};
214 219
215static int fec_enet_open(struct net_device *dev); 220static int fec_enet_open(struct net_device *dev);
@@ -237,10 +242,10 @@ typedef struct mii_list {
237} mii_list_t; 242} mii_list_t;
238 243
239#define NMII 20 244#define NMII 20
240mii_list_t mii_cmds[NMII]; 245static mii_list_t mii_cmds[NMII];
241mii_list_t *mii_free; 246static mii_list_t *mii_free;
242mii_list_t *mii_head; 247static mii_list_t *mii_head;
243mii_list_t *mii_tail; 248static mii_list_t *mii_tail;
244 249
245static int mii_queue(struct net_device *dev, int request, 250static int mii_queue(struct net_device *dev, int request,
246 void (*func)(uint, struct net_device *)); 251 void (*func)(uint, struct net_device *));
@@ -425,7 +430,7 @@ fec_timeout(struct net_device *dev)
425 } 430 }
426 } 431 }
427#endif 432#endif
428 fec_restart(dev, 0); 433 fec_restart(dev, fep->full_duplex);
429 netif_wake_queue(dev); 434 netif_wake_queue(dev);
430} 435}
431 436
@@ -757,45 +762,52 @@ static void mii_parse_sr(uint mii_reg, struct net_device *dev)
757{ 762{
758 struct fec_enet_private *fep = netdev_priv(dev); 763 struct fec_enet_private *fep = netdev_priv(dev);
759 volatile uint *s = &(fep->phy_status); 764 volatile uint *s = &(fep->phy_status);
765 uint status;
760 766
761 *s &= ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC); 767 status = *s & ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC);
762 768
763 if (mii_reg & 0x0004) 769 if (mii_reg & 0x0004)
764 *s |= PHY_STAT_LINK; 770 status |= PHY_STAT_LINK;
765 if (mii_reg & 0x0010) 771 if (mii_reg & 0x0010)
766 *s |= PHY_STAT_FAULT; 772 status |= PHY_STAT_FAULT;
767 if (mii_reg & 0x0020) 773 if (mii_reg & 0x0020)
768 *s |= PHY_STAT_ANC; 774 status |= PHY_STAT_ANC;
775
776 *s = status;
769} 777}
770 778
771static void mii_parse_cr(uint mii_reg, struct net_device *dev) 779static void mii_parse_cr(uint mii_reg, struct net_device *dev)
772{ 780{
773 struct fec_enet_private *fep = netdev_priv(dev); 781 struct fec_enet_private *fep = netdev_priv(dev);
774 volatile uint *s = &(fep->phy_status); 782 volatile uint *s = &(fep->phy_status);
783 uint status;
775 784
776 *s &= ~(PHY_CONF_ANE | PHY_CONF_LOOP); 785 status = *s & ~(PHY_CONF_ANE | PHY_CONF_LOOP);
777 786
778 if (mii_reg & 0x1000) 787 if (mii_reg & 0x1000)
779 *s |= PHY_CONF_ANE; 788 status |= PHY_CONF_ANE;
780 if (mii_reg & 0x4000) 789 if (mii_reg & 0x4000)
781 *s |= PHY_CONF_LOOP; 790 status |= PHY_CONF_LOOP;
791 *s = status;
782} 792}
783 793
784static void mii_parse_anar(uint mii_reg, struct net_device *dev) 794static void mii_parse_anar(uint mii_reg, struct net_device *dev)
785{ 795{
786 struct fec_enet_private *fep = netdev_priv(dev); 796 struct fec_enet_private *fep = netdev_priv(dev);
787 volatile uint *s = &(fep->phy_status); 797 volatile uint *s = &(fep->phy_status);
798 uint status;
788 799
789 *s &= ~(PHY_CONF_SPMASK); 800 status = *s & ~(PHY_CONF_SPMASK);
790 801
791 if (mii_reg & 0x0020) 802 if (mii_reg & 0x0020)
792 *s |= PHY_CONF_10HDX; 803 status |= PHY_CONF_10HDX;
793 if (mii_reg & 0x0040) 804 if (mii_reg & 0x0040)
794 *s |= PHY_CONF_10FDX; 805 status |= PHY_CONF_10FDX;
795 if (mii_reg & 0x0080) 806 if (mii_reg & 0x0080)
796 *s |= PHY_CONF_100HDX; 807 status |= PHY_CONF_100HDX;
797 if (mii_reg & 0x00100) 808 if (mii_reg & 0x00100)
798 *s |= PHY_CONF_100FDX; 809 status |= PHY_CONF_100FDX;
810 *s = status;
799} 811}
800 812
801/* ------------------------------------------------------------------------- */ 813/* ------------------------------------------------------------------------- */
@@ -811,37 +823,34 @@ static void mii_parse_lxt970_csr(uint mii_reg, struct net_device *dev)
811{ 823{
812 struct fec_enet_private *fep = netdev_priv(dev); 824 struct fec_enet_private *fep = netdev_priv(dev);
813 volatile uint *s = &(fep->phy_status); 825 volatile uint *s = &(fep->phy_status);
826 uint status;
814 827
815 *s &= ~(PHY_STAT_SPMASK); 828 status = *s & ~(PHY_STAT_SPMASK);
816
817 if (mii_reg & 0x0800) { 829 if (mii_reg & 0x0800) {
818 if (mii_reg & 0x1000) 830 if (mii_reg & 0x1000)
819 *s |= PHY_STAT_100FDX; 831 status |= PHY_STAT_100FDX;
820 else 832 else
821 *s |= PHY_STAT_100HDX; 833 status |= PHY_STAT_100HDX;
822 } else { 834 } else {
823 if (mii_reg & 0x1000) 835 if (mii_reg & 0x1000)
824 *s |= PHY_STAT_10FDX; 836 status |= PHY_STAT_10FDX;
825 else 837 else
826 *s |= PHY_STAT_10HDX; 838 status |= PHY_STAT_10HDX;
827 } 839 }
840 *s = status;
828} 841}
829 842
830static phy_info_t phy_info_lxt970 = { 843static phy_cmd_t const phy_cmd_lxt970_config[] = {
831 0x07810000,
832 "LXT970",
833
834 (const phy_cmd_t []) { /* config */
835 { mk_mii_read(MII_REG_CR), mii_parse_cr }, 844 { mk_mii_read(MII_REG_CR), mii_parse_cr },
836 { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, 845 { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
837 { mk_mii_end, } 846 { mk_mii_end, }
838 }, 847 };
839 (const phy_cmd_t []) { /* startup - enable interrupts */ 848static phy_cmd_t const phy_cmd_lxt970_startup[] = { /* enable interrupts */
840 { mk_mii_write(MII_LXT970_IER, 0x0002), NULL }, 849 { mk_mii_write(MII_LXT970_IER, 0x0002), NULL },
841 { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ 850 { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
842 { mk_mii_end, } 851 { mk_mii_end, }
843 }, 852 };
844 (const phy_cmd_t []) { /* ack_int */ 853static phy_cmd_t const phy_cmd_lxt970_ack_int[] = {
845 /* read SR and ISR to acknowledge */ 854 /* read SR and ISR to acknowledge */
846 { mk_mii_read(MII_REG_SR), mii_parse_sr }, 855 { mk_mii_read(MII_REG_SR), mii_parse_sr },
847 { mk_mii_read(MII_LXT970_ISR), NULL }, 856 { mk_mii_read(MII_LXT970_ISR), NULL },
@@ -849,11 +858,18 @@ static phy_info_t phy_info_lxt970 = {
849 /* find out the current status */ 858 /* find out the current status */
850 { mk_mii_read(MII_LXT970_CSR), mii_parse_lxt970_csr }, 859 { mk_mii_read(MII_LXT970_CSR), mii_parse_lxt970_csr },
851 { mk_mii_end, } 860 { mk_mii_end, }
852 }, 861 };
853 (const phy_cmd_t []) { /* shutdown - disable interrupts */ 862static phy_cmd_t const phy_cmd_lxt970_shutdown[] = { /* disable interrupts */
854 { mk_mii_write(MII_LXT970_IER, 0x0000), NULL }, 863 { mk_mii_write(MII_LXT970_IER, 0x0000), NULL },
855 { mk_mii_end, } 864 { mk_mii_end, }
856 }, 865 };
866static phy_info_t const phy_info_lxt970 = {
867 .id = 0x07810000,
868 .name = "LXT970",
869 .config = phy_cmd_lxt970_config,
870 .startup = phy_cmd_lxt970_startup,
871 .ack_int = phy_cmd_lxt970_ack_int,
872 .shutdown = phy_cmd_lxt970_shutdown
857}; 873};
858 874
859/* ------------------------------------------------------------------------- */ 875/* ------------------------------------------------------------------------- */
@@ -878,45 +894,44 @@ static void mii_parse_lxt971_sr2(uint mii_reg, struct net_device *dev)
878{ 894{
879 struct fec_enet_private *fep = netdev_priv(dev); 895 struct fec_enet_private *fep = netdev_priv(dev);
880 volatile uint *s = &(fep->phy_status); 896 volatile uint *s = &(fep->phy_status);
897 uint status;
881 898
882 *s &= ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC); 899 status = *s & ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC);
883 900
884 if (mii_reg & 0x0400) { 901 if (mii_reg & 0x0400) {
885 fep->link = 1; 902 fep->link = 1;
886 *s |= PHY_STAT_LINK; 903 status |= PHY_STAT_LINK;
887 } else { 904 } else {
888 fep->link = 0; 905 fep->link = 0;
889 } 906 }
890 if (mii_reg & 0x0080) 907 if (mii_reg & 0x0080)
891 *s |= PHY_STAT_ANC; 908 status |= PHY_STAT_ANC;
892 if (mii_reg & 0x4000) { 909 if (mii_reg & 0x4000) {
893 if (mii_reg & 0x0200) 910 if (mii_reg & 0x0200)
894 *s |= PHY_STAT_100FDX; 911 status |= PHY_STAT_100FDX;
895 else 912 else
896 *s |= PHY_STAT_100HDX; 913 status |= PHY_STAT_100HDX;
897 } else { 914 } else {
898 if (mii_reg & 0x0200) 915 if (mii_reg & 0x0200)
899 *s |= PHY_STAT_10FDX; 916 status |= PHY_STAT_10FDX;
900 else 917 else
901 *s |= PHY_STAT_10HDX; 918 status |= PHY_STAT_10HDX;
902 } 919 }
903 if (mii_reg & 0x0008) 920 if (mii_reg & 0x0008)
904 *s |= PHY_STAT_FAULT; 921 status |= PHY_STAT_FAULT;
905}
906 922
907static phy_info_t phy_info_lxt971 = { 923 *s = status;
908 0x0001378e, 924}
909 "LXT971",
910 925
911 (const phy_cmd_t []) { /* config */ 926static phy_cmd_t const phy_cmd_lxt971_config[] = {
912 /* limit to 10MBit because my protorype board 927 /* limit to 10MBit because my prototype board
913 * doesn't work with 100. */ 928 * doesn't work with 100. */
914 { mk_mii_read(MII_REG_CR), mii_parse_cr }, 929 { mk_mii_read(MII_REG_CR), mii_parse_cr },
915 { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, 930 { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
916 { mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 }, 931 { mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 },
917 { mk_mii_end, } 932 { mk_mii_end, }
918 }, 933 };
919 (const phy_cmd_t []) { /* startup - enable interrupts */ 934static phy_cmd_t const phy_cmd_lxt971_startup[] = { /* enable interrupts */
920 { mk_mii_write(MII_LXT971_IER, 0x00f2), NULL }, 935 { mk_mii_write(MII_LXT971_IER, 0x00f2), NULL },
921 { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ 936 { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
922 { mk_mii_write(MII_LXT971_LCR, 0xd422), NULL }, /* LED config */ 937 { mk_mii_write(MII_LXT971_LCR, 0xd422), NULL }, /* LED config */
@@ -925,19 +940,26 @@ static phy_info_t phy_info_lxt971 = {
925 * read here to get a valid value in ack_int */ 940 * read here to get a valid value in ack_int */
926 { mk_mii_read(MII_REG_SR), mii_parse_sr }, 941 { mk_mii_read(MII_REG_SR), mii_parse_sr },
927 { mk_mii_end, } 942 { mk_mii_end, }
928 }, 943 };
929 (const phy_cmd_t []) { /* ack_int */ 944static phy_cmd_t const phy_cmd_lxt971_ack_int[] = {
945 /* acknowledge the int before reading status ! */
946 { mk_mii_read(MII_LXT971_ISR), NULL },
930 /* find out the current status */ 947 /* find out the current status */
931 { mk_mii_read(MII_REG_SR), mii_parse_sr }, 948 { mk_mii_read(MII_REG_SR), mii_parse_sr },
932 { mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 }, 949 { mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 },
933 /* we only need to read ISR to acknowledge */
934 { mk_mii_read(MII_LXT971_ISR), NULL },
935 { mk_mii_end, } 950 { mk_mii_end, }
936 }, 951 };
937 (const phy_cmd_t []) { /* shutdown - disable interrupts */ 952static phy_cmd_t const phy_cmd_lxt971_shutdown[] = { /* disable interrupts */
938 { mk_mii_write(MII_LXT971_IER, 0x0000), NULL }, 953 { mk_mii_write(MII_LXT971_IER, 0x0000), NULL },
939 { mk_mii_end, } 954 { mk_mii_end, }
940 }, 955 };
956static phy_info_t const phy_info_lxt971 = {
957 .id = 0x0001378e,
958 .name = "LXT971",
959 .config = phy_cmd_lxt971_config,
960 .startup = phy_cmd_lxt971_startup,
961 .ack_int = phy_cmd_lxt971_ack_int,
962 .shutdown = phy_cmd_lxt971_shutdown
941}; 963};
942 964
943/* ------------------------------------------------------------------------- */ 965/* ------------------------------------------------------------------------- */
@@ -956,22 +978,21 @@ static void mii_parse_qs6612_pcr(uint mii_reg, struct net_device *dev)
956{ 978{
957 struct fec_enet_private *fep = netdev_priv(dev); 979 struct fec_enet_private *fep = netdev_priv(dev);
958 volatile uint *s = &(fep->phy_status); 980 volatile uint *s = &(fep->phy_status);
981 uint status;
959 982
960 *s &= ~(PHY_STAT_SPMASK); 983 status = *s & ~(PHY_STAT_SPMASK);
961 984
962 switch((mii_reg >> 2) & 7) { 985 switch((mii_reg >> 2) & 7) {
963 case 1: *s |= PHY_STAT_10HDX; break; 986 case 1: status |= PHY_STAT_10HDX; break;
964 case 2: *s |= PHY_STAT_100HDX; break; 987 case 2: status |= PHY_STAT_100HDX; break;
965 case 5: *s |= PHY_STAT_10FDX; break; 988 case 5: status |= PHY_STAT_10FDX; break;
966 case 6: *s |= PHY_STAT_100FDX; break; 989 case 6: status |= PHY_STAT_100FDX; break;
967 }
968} 990}
969 991
970static phy_info_t phy_info_qs6612 = { 992 *s = status;
971 0x00181440, 993}
972 "QS6612", 994
973 995static phy_cmd_t const phy_cmd_qs6612_config[] = {
974 (const phy_cmd_t []) { /* config */
975 /* The PHY powers up isolated on the RPX, 996 /* The PHY powers up isolated on the RPX,
976 * so send a command to allow operation. 997 * so send a command to allow operation.
977 */ 998 */
@@ -981,13 +1002,13 @@ static phy_info_t phy_info_qs6612 = {
981 { mk_mii_read(MII_REG_CR), mii_parse_cr }, 1002 { mk_mii_read(MII_REG_CR), mii_parse_cr },
982 { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, 1003 { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
983 { mk_mii_end, } 1004 { mk_mii_end, }
984 }, 1005 };
985 (const phy_cmd_t []) { /* startup - enable interrupts */ 1006static phy_cmd_t const phy_cmd_qs6612_startup[] = { /* enable interrupts */
986 { mk_mii_write(MII_QS6612_IMR, 0x003a), NULL }, 1007 { mk_mii_write(MII_QS6612_IMR, 0x003a), NULL },
987 { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ 1008 { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
988 { mk_mii_end, } 1009 { mk_mii_end, }
989 }, 1010 };
990 (const phy_cmd_t []) { /* ack_int */ 1011static phy_cmd_t const phy_cmd_qs6612_ack_int[] = {
991 /* we need to read ISR, SR and ANER to acknowledge */ 1012 /* we need to read ISR, SR and ANER to acknowledge */
992 { mk_mii_read(MII_QS6612_ISR), NULL }, 1013 { mk_mii_read(MII_QS6612_ISR), NULL },
993 { mk_mii_read(MII_REG_SR), mii_parse_sr }, 1014 { mk_mii_read(MII_REG_SR), mii_parse_sr },
@@ -996,11 +1017,18 @@ static phy_info_t phy_info_qs6612 = {
996 /* read pcr to get info */ 1017 /* read pcr to get info */
997 { mk_mii_read(MII_QS6612_PCR), mii_parse_qs6612_pcr }, 1018 { mk_mii_read(MII_QS6612_PCR), mii_parse_qs6612_pcr },
998 { mk_mii_end, } 1019 { mk_mii_end, }
999 }, 1020 };
1000 (const phy_cmd_t []) { /* shutdown - disable interrupts */ 1021static phy_cmd_t const phy_cmd_qs6612_shutdown[] = { /* disable interrupts */
1001 { mk_mii_write(MII_QS6612_IMR, 0x0000), NULL }, 1022 { mk_mii_write(MII_QS6612_IMR, 0x0000), NULL },
1002 { mk_mii_end, } 1023 { mk_mii_end, }
1003 }, 1024 };
1025static phy_info_t const phy_info_qs6612 = {
1026 .id = 0x00181440,
1027 .name = "QS6612",
1028 .config = phy_cmd_qs6612_config,
1029 .startup = phy_cmd_qs6612_startup,
1030 .ack_int = phy_cmd_qs6612_ack_int,
1031 .shutdown = phy_cmd_qs6612_shutdown
1004}; 1032};
1005 1033
1006/* ------------------------------------------------------------------------- */ 1034/* ------------------------------------------------------------------------- */
@@ -1020,49 +1048,54 @@ static void mii_parse_am79c874_dr(uint mii_reg, struct net_device *dev)
1020{ 1048{
1021 struct fec_enet_private *fep = netdev_priv(dev); 1049 struct fec_enet_private *fep = netdev_priv(dev);
1022 volatile uint *s = &(fep->phy_status); 1050 volatile uint *s = &(fep->phy_status);
1051 uint status;
1023 1052
1024 *s &= ~(PHY_STAT_SPMASK | PHY_STAT_ANC); 1053 status = *s & ~(PHY_STAT_SPMASK | PHY_STAT_ANC);
1025 1054
1026 if (mii_reg & 0x0080) 1055 if (mii_reg & 0x0080)
1027 *s |= PHY_STAT_ANC; 1056 status |= PHY_STAT_ANC;
1028 if (mii_reg & 0x0400) 1057 if (mii_reg & 0x0400)
1029 *s |= ((mii_reg & 0x0800) ? PHY_STAT_100FDX : PHY_STAT_100HDX); 1058 status |= ((mii_reg & 0x0800) ? PHY_STAT_100FDX : PHY_STAT_100HDX);
1030 else 1059 else
1031 *s |= ((mii_reg & 0x0800) ? PHY_STAT_10FDX : PHY_STAT_10HDX); 1060 status |= ((mii_reg & 0x0800) ? PHY_STAT_10FDX : PHY_STAT_10HDX);
1061
1062 *s = status;
1032} 1063}
1033 1064
1034static phy_info_t phy_info_am79c874 = { 1065static phy_cmd_t const phy_cmd_am79c874_config[] = {
1035 0x00022561,
1036 "AM79C874",
1037
1038 (const phy_cmd_t []) { /* config */
1039 /* limit to 10MBit because my protorype board
1040 * doesn't work with 100. */
1041 { mk_mii_read(MII_REG_CR), mii_parse_cr }, 1066 { mk_mii_read(MII_REG_CR), mii_parse_cr },
1042 { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, 1067 { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
1043 { mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr }, 1068 { mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr },
1044 { mk_mii_end, } 1069 { mk_mii_end, }
1045 }, 1070 };
1046 (const phy_cmd_t []) { /* startup - enable interrupts */ 1071static phy_cmd_t const phy_cmd_am79c874_startup[] = { /* enable interrupts */
1047 { mk_mii_write(MII_AM79C874_ICSR, 0xff00), NULL }, 1072 { mk_mii_write(MII_AM79C874_ICSR, 0xff00), NULL },
1048 { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ 1073 { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
1049 { mk_mii_read(MII_REG_SR), mii_parse_sr }, 1074 { mk_mii_read(MII_REG_SR), mii_parse_sr },
1050 { mk_mii_end, } 1075 { mk_mii_end, }
1051 }, 1076 };
1052 (const phy_cmd_t []) { /* ack_int */ 1077static phy_cmd_t const phy_cmd_am79c874_ack_int[] = {
1053 /* find out the current status */ 1078 /* find out the current status */
1054 { mk_mii_read(MII_REG_SR), mii_parse_sr }, 1079 { mk_mii_read(MII_REG_SR), mii_parse_sr },
1055 { mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr }, 1080 { mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr },
1056 /* we only need to read ISR to acknowledge */ 1081 /* we only need to read ISR to acknowledge */
1057 { mk_mii_read(MII_AM79C874_ICSR), NULL }, 1082 { mk_mii_read(MII_AM79C874_ICSR), NULL },
1058 { mk_mii_end, } 1083 { mk_mii_end, }
1059 }, 1084 };
1060 (const phy_cmd_t []) { /* shutdown - disable interrupts */ 1085static phy_cmd_t const phy_cmd_am79c874_shutdown[] = { /* disable interrupts */
1061 { mk_mii_write(MII_AM79C874_ICSR, 0x0000), NULL }, 1086 { mk_mii_write(MII_AM79C874_ICSR, 0x0000), NULL },
1062 { mk_mii_end, } 1087 { mk_mii_end, }
1063 }, 1088 };
1089static phy_info_t const phy_info_am79c874 = {
1090 .id = 0x00022561,
1091 .name = "AM79C874",
1092 .config = phy_cmd_am79c874_config,
1093 .startup = phy_cmd_am79c874_startup,
1094 .ack_int = phy_cmd_am79c874_ack_int,
1095 .shutdown = phy_cmd_am79c874_shutdown
1064}; 1096};
1065 1097
1098
1066/* ------------------------------------------------------------------------- */ 1099/* ------------------------------------------------------------------------- */
1067/* Kendin KS8721BL phy */ 1100/* Kendin KS8721BL phy */
1068 1101
@@ -1072,37 +1105,40 @@ static phy_info_t phy_info_am79c874 = {
1072#define MII_KS8721BL_ICSR 22 1105#define MII_KS8721BL_ICSR 22
1073#define MII_KS8721BL_PHYCR 31 1106#define MII_KS8721BL_PHYCR 31
1074 1107
1075static phy_info_t phy_info_ks8721bl = { 1108static phy_cmd_t const phy_cmd_ks8721bl_config[] = {
1076 0x00022161,
1077 "KS8721BL",
1078
1079 (const phy_cmd_t []) { /* config */
1080 { mk_mii_read(MII_REG_CR), mii_parse_cr }, 1109 { mk_mii_read(MII_REG_CR), mii_parse_cr },
1081 { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, 1110 { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
1082 { mk_mii_end, } 1111 { mk_mii_end, }
1083 }, 1112 };
1084 (const phy_cmd_t []) { /* startup */ 1113static phy_cmd_t const phy_cmd_ks8721bl_startup[] = { /* enable interrupts */
1085 { mk_mii_write(MII_KS8721BL_ICSR, 0xff00), NULL }, 1114 { mk_mii_write(MII_KS8721BL_ICSR, 0xff00), NULL },
1086 { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ 1115 { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
1087 { mk_mii_read(MII_REG_SR), mii_parse_sr }, 1116 { mk_mii_read(MII_REG_SR), mii_parse_sr },
1088 { mk_mii_end, } 1117 { mk_mii_end, }
1089 }, 1118 };
1090 (const phy_cmd_t []) { /* ack_int */ 1119static phy_cmd_t const phy_cmd_ks8721bl_ack_int[] = {
1091 /* find out the current status */ 1120 /* find out the current status */
1092 { mk_mii_read(MII_REG_SR), mii_parse_sr }, 1121 { mk_mii_read(MII_REG_SR), mii_parse_sr },
1093 /* we only need to read ISR to acknowledge */ 1122 /* we only need to read ISR to acknowledge */
1094 { mk_mii_read(MII_KS8721BL_ICSR), NULL }, 1123 { mk_mii_read(MII_KS8721BL_ICSR), NULL },
1095 { mk_mii_end, } 1124 { mk_mii_end, }
1096 }, 1125 };
1097 (const phy_cmd_t []) { /* shutdown */ 1126static phy_cmd_t const phy_cmd_ks8721bl_shutdown[] = { /* disable interrupts */
1098 { mk_mii_write(MII_KS8721BL_ICSR, 0x0000), NULL }, 1127 { mk_mii_write(MII_KS8721BL_ICSR, 0x0000), NULL },
1099 { mk_mii_end, } 1128 { mk_mii_end, }
1100 }, 1129 };
1130static phy_info_t const phy_info_ks8721bl = {
1131 .id = 0x00022161,
1132 .name = "KS8721BL",
1133 .config = phy_cmd_ks8721bl_config,
1134 .startup = phy_cmd_ks8721bl_startup,
1135 .ack_int = phy_cmd_ks8721bl_ack_int,
1136 .shutdown = phy_cmd_ks8721bl_shutdown
1101}; 1137};
1102 1138
1103/* ------------------------------------------------------------------------- */ 1139/* ------------------------------------------------------------------------- */
1104 1140
1105static phy_info_t *phy_info[] = { 1141static phy_info_t const * const phy_info[] = {
1106 &phy_info_lxt970, 1142 &phy_info_lxt970,
1107 &phy_info_lxt971, 1143 &phy_info_lxt971,
1108 &phy_info_qs6612, 1144 &phy_info_qs6612,
@@ -1129,16 +1165,23 @@ mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs);
1129static void __inline__ fec_request_intrs(struct net_device *dev) 1165static void __inline__ fec_request_intrs(struct net_device *dev)
1130{ 1166{
1131 volatile unsigned long *icrp; 1167 volatile unsigned long *icrp;
1168 static const struct idesc {
1169 char *name;
1170 unsigned short irq;
1171 irqreturn_t (*handler)(int, void *, struct pt_regs *);
1172 } *idp, id[] = {
1173 { "fec(RX)", 86, fec_enet_interrupt },
1174 { "fec(TX)", 87, fec_enet_interrupt },
1175 { "fec(OTHER)", 88, fec_enet_interrupt },
1176 { "fec(MII)", 66, mii_link_interrupt },
1177 { NULL },
1178 };
1132 1179
1133 /* Setup interrupt handlers. */ 1180 /* Setup interrupt handlers. */
1134 if (request_irq(86, fec_enet_interrupt, 0, "fec(RX)", dev) != 0) 1181 for (idp = id; idp->name; idp++) {
1135 printk("FEC: Could not allocate FEC(RC) IRQ(86)!\n"); 1182 if (request_irq(idp->irq, idp->handler, 0, idp->name, dev) != 0)
1136 if (request_irq(87, fec_enet_interrupt, 0, "fec(TX)", dev) != 0) 1183 printk("FEC: Could not allocate %s IRQ(%d)!\n", idp->name, idp->irq);
1137 printk("FEC: Could not allocate FEC(RC) IRQ(87)!\n"); 1184 }
1138 if (request_irq(88, fec_enet_interrupt, 0, "fec(OTHER)", dev) != 0)
1139 printk("FEC: Could not allocate FEC(OTHER) IRQ(88)!\n");
1140 if (request_irq(66, mii_link_interrupt, 0, "fec(MII)", dev) != 0)
1141 printk("FEC: Could not allocate MII IRQ(66)!\n");
1142 1185
1143 /* Unmask interrupt at ColdFire 5272 SIM */ 1186 /* Unmask interrupt at ColdFire 5272 SIM */
1144 icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR3); 1187 icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR3);
@@ -1169,17 +1212,16 @@ static void __inline__ fec_get_mac(struct net_device *dev)
1169{ 1212{
1170 struct fec_enet_private *fep = netdev_priv(dev); 1213 struct fec_enet_private *fep = netdev_priv(dev);
1171 volatile fec_t *fecp; 1214 volatile fec_t *fecp;
1172 unsigned char *iap, tmpaddr[6]; 1215 unsigned char *iap, tmpaddr[ETH_ALEN];
1173 int i;
1174 1216
1175 fecp = fep->hwp; 1217 fecp = fep->hwp;
1176 1218
1177 if (fec_flashmac) { 1219 if (FEC_FLASHMAC) {
1178 /* 1220 /*
1179 * Get MAC address from FLASH. 1221 * Get MAC address from FLASH.
1180 * If it is all 1's or 0's, use the default. 1222 * If it is all 1's or 0's, use the default.
1181 */ 1223 */
1182 iap = fec_flashmac; 1224 iap = (unsigned char *)FEC_FLASHMAC;
1183 if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) && 1225 if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
1184 (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0)) 1226 (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
1185 iap = fec_mac_default; 1227 iap = fec_mac_default;
@@ -1192,14 +1234,11 @@ static void __inline__ fec_get_mac(struct net_device *dev)
1192 iap = &tmpaddr[0]; 1234 iap = &tmpaddr[0];
1193 } 1235 }
1194 1236
1195 for (i=0; i<ETH_ALEN; i++) 1237 memcpy(dev->dev_addr, iap, ETH_ALEN);
1196 dev->dev_addr[i] = fep->mac_addr[i] = *iap++;
1197 1238
1198 /* Adjust MAC if using default MAC address */ 1239 /* Adjust MAC if using default MAC address */
1199 if (iap == fec_mac_default) { 1240 if (iap == fec_mac_default)
1200 dev->dev_addr[ETH_ALEN-1] = fep->mac_addr[ETH_ALEN-1] = 1241 dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
1201 iap[ETH_ALEN-1] + fep->index;
1202 }
1203} 1242}
1204 1243
1205static void __inline__ fec_enable_phy_intr(void) 1244static void __inline__ fec_enable_phy_intr(void)
@@ -1234,48 +1273,44 @@ static void __inline__ fec_uncache(unsigned long addr)
1234 1273
1235/* ------------------------------------------------------------------------- */ 1274/* ------------------------------------------------------------------------- */
1236 1275
1237#elif defined(CONFIG_M527x) || defined(CONFIG_M528x) 1276#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
1238 1277
1239/* 1278/*
1240 * Code specific to Coldfire 5270/5271/5274/5275 and 5280/5282 setups. 1279 * Code specific to Coldfire 5230/5231/5232/5234/5235,
1280 * the 5270/5271/5274/5275 and 5280/5282 setups.
1241 */ 1281 */
1242static void __inline__ fec_request_intrs(struct net_device *dev) 1282static void __inline__ fec_request_intrs(struct net_device *dev)
1243{ 1283{
1244 struct fec_enet_private *fep; 1284 struct fec_enet_private *fep;
1245 int b; 1285 int b;
1286 static const struct idesc {
1287 char *name;
1288 unsigned short irq;
1289 } *idp, id[] = {
1290 { "fec(TXF)", 23 },
1291 { "fec(TXB)", 24 },
1292 { "fec(TXFIFO)", 25 },
1293 { "fec(TXCR)", 26 },
1294 { "fec(RXF)", 27 },
1295 { "fec(RXB)", 28 },
1296 { "fec(MII)", 29 },
1297 { "fec(LC)", 30 },
1298 { "fec(HBERR)", 31 },
1299 { "fec(GRA)", 32 },
1300 { "fec(EBERR)", 33 },
1301 { "fec(BABT)", 34 },
1302 { "fec(BABR)", 35 },
1303 { NULL },
1304 };
1246 1305
1247 fep = netdev_priv(dev); 1306 fep = netdev_priv(dev);
1248 b = (fep->index) ? 128 : 64; 1307 b = (fep->index) ? 128 : 64;
1249 1308
1250 /* Setup interrupt handlers. */ 1309 /* Setup interrupt handlers. */
1251 if (request_irq(b+23, fec_enet_interrupt, 0, "fec(TXF)", dev) != 0) 1310 for (idp = id; idp->name; idp++) {
1252 printk("FEC: Could not allocate FEC(TXF) IRQ(%d+23)!\n", b); 1311 if (request_irq(b+idp->irq, fec_enet_interrupt, 0, idp->name, dev) != 0)
1253 if (request_irq(b+24, fec_enet_interrupt, 0, "fec(TXB)", dev) != 0) 1312 printk("FEC: Could not allocate %s IRQ(%d)!\n", idp->name, b+idp->irq);
1254 printk("FEC: Could not allocate FEC(TXB) IRQ(%d+24)!\n", b); 1313 }
1255 if (request_irq(b+25, fec_enet_interrupt, 0, "fec(TXFIFO)", dev) != 0)
1256 printk("FEC: Could not allocate FEC(TXFIFO) IRQ(%d+25)!\n", b);
1257 if (request_irq(b+26, fec_enet_interrupt, 0, "fec(TXCR)", dev) != 0)
1258 printk("FEC: Could not allocate FEC(TXCR) IRQ(%d+26)!\n", b);
1259
1260 if (request_irq(b+27, fec_enet_interrupt, 0, "fec(RXF)", dev) != 0)
1261 printk("FEC: Could not allocate FEC(RXF) IRQ(%d+27)!\n", b);
1262 if (request_irq(b+28, fec_enet_interrupt, 0, "fec(RXB)", dev) != 0)
1263 printk("FEC: Could not allocate FEC(RXB) IRQ(%d+28)!\n", b);
1264
1265 if (request_irq(b+29, fec_enet_interrupt, 0, "fec(MII)", dev) != 0)
1266 printk("FEC: Could not allocate FEC(MII) IRQ(%d+29)!\n", b);
1267 if (request_irq(b+30, fec_enet_interrupt, 0, "fec(LC)", dev) != 0)
1268 printk("FEC: Could not allocate FEC(LC) IRQ(%d+30)!\n", b);
1269 if (request_irq(b+31, fec_enet_interrupt, 0, "fec(HBERR)", dev) != 0)
1270 printk("FEC: Could not allocate FEC(HBERR) IRQ(%d+31)!\n", b);
1271 if (request_irq(b+32, fec_enet_interrupt, 0, "fec(GRA)", dev) != 0)
1272 printk("FEC: Could not allocate FEC(GRA) IRQ(%d+32)!\n", b);
1273 if (request_irq(b+33, fec_enet_interrupt, 0, "fec(EBERR)", dev) != 0)
1274 printk("FEC: Could not allocate FEC(EBERR) IRQ(%d+33)!\n", b);
1275 if (request_irq(b+34, fec_enet_interrupt, 0, "fec(BABT)", dev) != 0)
1276 printk("FEC: Could not allocate FEC(BABT) IRQ(%d+34)!\n", b);
1277 if (request_irq(b+35, fec_enet_interrupt, 0, "fec(BABR)", dev) != 0)
1278 printk("FEC: Could not allocate FEC(BABR) IRQ(%d+35)!\n", b);
1279 1314
1280 /* Unmask interrupts at ColdFire 5280/5282 interrupt controller */ 1315 /* Unmask interrupts at ColdFire 5280/5282 interrupt controller */
1281 { 1316 {
@@ -1300,11 +1335,13 @@ static void __inline__ fec_request_intrs(struct net_device *dev)
1300#if defined(CONFIG_M528x) 1335#if defined(CONFIG_M528x)
1301 /* Set up gpio outputs for MII lines */ 1336 /* Set up gpio outputs for MII lines */
1302 { 1337 {
1303 volatile unsigned short *gpio_paspar; 1338 volatile u16 *gpio_paspar;
1339 volatile u8 *gpio_pehlpar;
1304 1340
1305 gpio_paspar = (volatile unsigned short *) (MCF_IPSBAR + 1341 gpio_paspar = (volatile u16 *) (MCF_IPSBAR + 0x100056);
1306 0x100056); 1342 gpio_pehlpar = (volatile u16 *) (MCF_IPSBAR + 0x100058);
1307 *gpio_paspar = 0x0f00; 1343 *gpio_paspar |= 0x0f00;
1344 *gpio_pehlpar = 0xc0;
1308 } 1345 }
1309#endif 1346#endif
1310} 1347}
@@ -1331,17 +1368,16 @@ static void __inline__ fec_get_mac(struct net_device *dev)
1331{ 1368{
1332 struct fec_enet_private *fep = netdev_priv(dev); 1369 struct fec_enet_private *fep = netdev_priv(dev);
1333 volatile fec_t *fecp; 1370 volatile fec_t *fecp;
1334 unsigned char *iap, tmpaddr[6]; 1371 unsigned char *iap, tmpaddr[ETH_ALEN];
1335 int i;
1336 1372
1337 fecp = fep->hwp; 1373 fecp = fep->hwp;
1338 1374
1339 if (fec_flashmac) { 1375 if (FEC_FLASHMAC) {
1340 /* 1376 /*
1341 * Get MAC address from FLASH. 1377 * Get MAC address from FLASH.
1342 * If it is all 1's or 0's, use the default. 1378 * If it is all 1's or 0's, use the default.
1343 */ 1379 */
1344 iap = fec_flashmac; 1380 iap = FEC_FLASHMAC;
1345 if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) && 1381 if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
1346 (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0)) 1382 (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
1347 iap = fec_mac_default; 1383 iap = fec_mac_default;
@@ -1354,14 +1390,11 @@ static void __inline__ fec_get_mac(struct net_device *dev)
1354 iap = &tmpaddr[0]; 1390 iap = &tmpaddr[0];
1355 } 1391 }
1356 1392
1357 for (i=0; i<ETH_ALEN; i++) 1393 memcpy(dev->dev_addr, iap, ETH_ALEN);
1358 dev->dev_addr[i] = fep->mac_addr[i] = *iap++;
1359 1394
1360 /* Adjust MAC if using default MAC address */ 1395 /* Adjust MAC if using default MAC address */
1361 if (iap == fec_mac_default) { 1396 if (iap == fec_mac_default)
1362 dev->dev_addr[ETH_ALEN-1] = fep->mac_addr[ETH_ALEN-1] = 1397 dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
1363 iap[ETH_ALEN-1] + fep->index;
1364 }
1365} 1398}
1366 1399
1367static void __inline__ fec_enable_phy_intr(void) 1400static void __inline__ fec_enable_phy_intr(void)
@@ -1392,7 +1425,7 @@ static void __inline__ fec_uncache(unsigned long addr)
1392#else 1425#else
1393 1426
1394/* 1427/*
1395 * Code sepcific to the MPC860T setup. 1428 * Code specific to the MPC860T setup.
1396 */ 1429 */
1397static void __inline__ fec_request_intrs(struct net_device *dev) 1430static void __inline__ fec_request_intrs(struct net_device *dev)
1398{ 1431{
@@ -1424,13 +1457,10 @@ static void __inline__ fec_request_intrs(struct net_device *dev)
1424 1457
1425static void __inline__ fec_get_mac(struct net_device *dev) 1458static void __inline__ fec_get_mac(struct net_device *dev)
1426{ 1459{
1427 struct fec_enet_private *fep = netdev_priv(dev);
1428 unsigned char *iap, tmpaddr[6];
1429 bd_t *bd; 1460 bd_t *bd;
1430 int i;
1431 1461
1432 iap = bd->bi_enetaddr;
1433 bd = (bd_t *)__res; 1462 bd = (bd_t *)__res;
1463 memcpy(dev->dev_addr, bd->bi_enetaddr, ETH_ALEN);
1434 1464
1435#ifdef CONFIG_RPXCLASSIC 1465#ifdef CONFIG_RPXCLASSIC
1436 /* The Embedded Planet boards have only one MAC address in 1466 /* The Embedded Planet boards have only one MAC address in
@@ -1439,14 +1469,8 @@ static void __inline__ fec_get_mac(struct net_device *dev)
1439 * the address bits above something that would have (up to 1469 * the address bits above something that would have (up to
1440 * now) been allocated. 1470 * now) been allocated.
1441 */ 1471 */
1442 for (i=0; i<6; i++) 1472 dev->dev_adrd[3] |= 0x80;
1443 tmpaddr[i] = *iap++;
1444 tmpaddr[3] |= 0x80;
1445 iap = tmpaddr;
1446#endif 1473#endif
1447
1448 for (i=0; i<6; i++)
1449 dev->dev_addr[i] = fep->mac_addr[i] = *iap++;
1450} 1474}
1451 1475
1452static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep) 1476static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep)
@@ -1556,7 +1580,7 @@ static void mii_display_status(struct net_device *dev)
1556static void mii_display_config(struct net_device *dev) 1580static void mii_display_config(struct net_device *dev)
1557{ 1581{
1558 struct fec_enet_private *fep = netdev_priv(dev); 1582 struct fec_enet_private *fep = netdev_priv(dev);
1559 volatile uint *s = &(fep->phy_status); 1583 uint status = fep->phy_status;
1560 1584
1561 /* 1585 /*
1562 ** When we get here, phy_task is already removed from 1586 ** When we get here, phy_task is already removed from
@@ -1565,23 +1589,23 @@ static void mii_display_config(struct net_device *dev)
1565 fep->mii_phy_task_queued = 0; 1589 fep->mii_phy_task_queued = 0;
1566 printk("%s: config: auto-negotiation ", dev->name); 1590 printk("%s: config: auto-negotiation ", dev->name);
1567 1591
1568 if (*s & PHY_CONF_ANE) 1592 if (status & PHY_CONF_ANE)
1569 printk("on"); 1593 printk("on");
1570 else 1594 else
1571 printk("off"); 1595 printk("off");
1572 1596
1573 if (*s & PHY_CONF_100FDX) 1597 if (status & PHY_CONF_100FDX)
1574 printk(", 100FDX"); 1598 printk(", 100FDX");
1575 if (*s & PHY_CONF_100HDX) 1599 if (status & PHY_CONF_100HDX)
1576 printk(", 100HDX"); 1600 printk(", 100HDX");
1577 if (*s & PHY_CONF_10FDX) 1601 if (status & PHY_CONF_10FDX)
1578 printk(", 10FDX"); 1602 printk(", 10FDX");
1579 if (*s & PHY_CONF_10HDX) 1603 if (status & PHY_CONF_10HDX)
1580 printk(", 10HDX"); 1604 printk(", 10HDX");
1581 if (!(*s & PHY_CONF_SPMASK)) 1605 if (!(status & PHY_CONF_SPMASK))
1582 printk(", No speed/duplex selected?"); 1606 printk(", No speed/duplex selected?");
1583 1607
1584 if (*s & PHY_CONF_LOOP) 1608 if (status & PHY_CONF_LOOP)
1585 printk(", loopback enabled"); 1609 printk(", loopback enabled");
1586 1610
1587 printk(".\n"); 1611 printk(".\n");
@@ -1639,7 +1663,7 @@ static void mii_queue_relink(uint mii_reg, struct net_device *dev)
1639 schedule_work(&fep->phy_task); 1663 schedule_work(&fep->phy_task);
1640} 1664}
1641 1665
1642/* mii_queue_config is called in user context from fec_enet_open */ 1666/* mii_queue_config is called in interrupt context from fec_enet_mii */
1643static void mii_queue_config(uint mii_reg, struct net_device *dev) 1667static void mii_queue_config(uint mii_reg, struct net_device *dev)
1644{ 1668{
1645 struct fec_enet_private *fep = netdev_priv(dev); 1669 struct fec_enet_private *fep = netdev_priv(dev);
@@ -1652,14 +1676,14 @@ static void mii_queue_config(uint mii_reg, struct net_device *dev)
1652 schedule_work(&fep->phy_task); 1676 schedule_work(&fep->phy_task);
1653} 1677}
1654 1678
1655 1679phy_cmd_t const phy_cmd_relink[] = {
1656 1680 { mk_mii_read(MII_REG_CR), mii_queue_relink },
1657phy_cmd_t phy_cmd_relink[] = { { mk_mii_read(MII_REG_CR), mii_queue_relink }, 1681 { mk_mii_end, }
1658 { mk_mii_end, } }; 1682 };
1659phy_cmd_t phy_cmd_config[] = { { mk_mii_read(MII_REG_CR), mii_queue_config }, 1683phy_cmd_t const phy_cmd_config[] = {
1660 { mk_mii_end, } }; 1684 { mk_mii_read(MII_REG_CR), mii_queue_config },
1661 1685 { mk_mii_end, }
1662 1686 };
1663 1687
1664/* Read remainder of PHY ID. 1688/* Read remainder of PHY ID.
1665*/ 1689*/
@@ -1897,17 +1921,15 @@ static void set_multicast_list(struct net_device *dev)
1897static void 1921static void
1898fec_set_mac_address(struct net_device *dev) 1922fec_set_mac_address(struct net_device *dev)
1899{ 1923{
1900 struct fec_enet_private *fep;
1901 volatile fec_t *fecp; 1924 volatile fec_t *fecp;
1902 1925
1903 fep = netdev_priv(dev); 1926 fecp = ((struct fec_enet_private *)netdev_priv(dev))->hwp;
1904 fecp = fep->hwp;
1905 1927
1906 /* Set station address. */ 1928 /* Set station address. */
1907 fecp->fec_addr_low = fep->mac_addr[3] | (fep->mac_addr[2] << 8) | 1929 fecp->fec_addr_low = dev->dev_addr[3] | (dev->dev_addr[2] << 8) |
1908 (fep->mac_addr[1] << 16) | (fep->mac_addr[0] << 24); 1930 (dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24);
1909 fecp->fec_addr_high = (fep->mac_addr[5] << 16) | 1931 fecp->fec_addr_high = (dev->dev_addr[5] << 16) |
1910 (fep->mac_addr[4] << 24); 1932 (dev->dev_addr[4] << 24);
1911 1933
1912} 1934}
1913 1935
@@ -1943,7 +1965,7 @@ int __init fec_enet_init(struct net_device *dev)
1943 udelay(10); 1965 udelay(10);
1944 1966
1945 /* Clear and enable interrupts */ 1967 /* Clear and enable interrupts */
1946 fecp->fec_ievent = 0xffc0; 1968 fecp->fec_ievent = 0xffc00000;
1947 fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB | 1969 fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB |
1948 FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII); 1970 FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII);
1949 fecp->fec_hash_table_high = 0; 1971 fecp->fec_hash_table_high = 0;
@@ -2063,11 +2085,6 @@ int __init fec_enet_init(struct net_device *dev)
2063 /* setup MII interface */ 2085 /* setup MII interface */
2064 fec_set_mii(dev, fep); 2086 fec_set_mii(dev, fep);
2065 2087
2066 printk("%s: FEC ENET Version 0.2, ", dev->name);
2067 for (i=0; i<5; i++)
2068 printk("%02x:", dev->dev_addr[i]);
2069 printk("%02x\n", dev->dev_addr[5]);
2070
2071 /* Queue up command to detect the PHY and initialize the 2088 /* Queue up command to detect the PHY and initialize the
2072 * remainder of the interface. 2089 * remainder of the interface.
2073 */ 2090 */
@@ -2106,18 +2123,12 @@ fec_restart(struct net_device *dev, int duplex)
2106 2123
2107 /* Clear any outstanding interrupt. 2124 /* Clear any outstanding interrupt.
2108 */ 2125 */
2109 fecp->fec_ievent = 0xffc0; 2126 fecp->fec_ievent = 0xffc00000;
2110 fec_enable_phy_intr(); 2127 fec_enable_phy_intr();
2111 2128
2112 /* Set station address. 2129 /* Set station address.
2113 */ 2130 */
2114 fecp->fec_addr_low = fep->mac_addr[3] | (fep->mac_addr[2] << 8) | 2131 fec_set_mac_address(dev);
2115 (fep->mac_addr[1] << 16) | (fep->mac_addr[0] << 24);
2116 fecp->fec_addr_high = (fep->mac_addr[5] << 16) |
2117 (fep->mac_addr[4] << 24);
2118
2119 for (i=0; i<ETH_ALEN; i++)
2120 dev->dev_addr[i] = fep->mac_addr[i];
2121 2132
2122 /* Reset all multicast. 2133 /* Reset all multicast.
2123 */ 2134 */
@@ -2215,7 +2226,7 @@ fec_stop(struct net_device *dev)
2215 2226
2216 fecp->fec_x_cntrl = 0x01; /* Graceful transmit stop */ 2227 fecp->fec_x_cntrl = 0x01; /* Graceful transmit stop */
2217 2228
2218 while(!(fecp->fec_ievent & 0x10000000)); 2229 while(!(fecp->fec_ievent & FEC_ENET_GRA));
2219 2230
2220 /* Whack a reset. We should wait for this. 2231 /* Whack a reset. We should wait for this.
2221 */ 2232 */
@@ -2234,7 +2245,9 @@ fec_stop(struct net_device *dev)
2234static int __init fec_enet_module_init(void) 2245static int __init fec_enet_module_init(void)
2235{ 2246{
2236 struct net_device *dev; 2247 struct net_device *dev;
2237 int i, err; 2248 int i, j, err;
2249
2250 printk("FEC ENET Version 0.2\n");
2238 2251
2239 for (i = 0; (i < FEC_MAX_PORTS); i++) { 2252 for (i = 0; (i < FEC_MAX_PORTS); i++) {
2240 dev = alloc_etherdev(sizeof(struct fec_enet_private)); 2253 dev = alloc_etherdev(sizeof(struct fec_enet_private));
@@ -2250,6 +2263,11 @@ static int __init fec_enet_module_init(void)
2250 free_netdev(dev); 2263 free_netdev(dev);
2251 return -EIO; 2264 return -EIO;
2252 } 2265 }
2266
2267 printk("%s: ethernet ", dev->name);
2268 for (j = 0; (j < 5); j++)
2269 printk("%02x:", dev->dev_addr[j]);
2270 printk("%02x\n", dev->dev_addr[5]);
2253 } 2271 }
2254 return 0; 2272 return 0;
2255} 2273}
diff --git a/drivers/net/fec.h b/drivers/net/fec.h
index c6e4f979ff5d..045761b8a600 100644
--- a/drivers/net/fec.h
+++ b/drivers/net/fec.h
@@ -1,8 +1,9 @@
1/****************************************************************************/ 1/****************************************************************************/
2 2
3/* 3/*
4 * fec.h -- Fast Ethernet Controller for Motorola ColdFire 5270, 4 * fec.h -- Fast Ethernet Controller for Motorola ColdFire 5230,
5 5271, 5272, 5274, 5275, 5280 and 5282. 5 * 5231, 5232, 5234, 5235, 5270, 5271, 5272, 5274, 5275,
6 * 5280 and 5282.
6 * 7 *
7 * (C) Copyright 2000-2003, Greg Ungerer (gerg@snapgear.com) 8 * (C) Copyright 2000-2003, Greg Ungerer (gerg@snapgear.com)
8 * (C) Copyright 2000-2001, Lineo (www.lineo.com) 9 * (C) Copyright 2000-2001, Lineo (www.lineo.com)
@@ -13,7 +14,7 @@
13#define FEC_H 14#define FEC_H
14/****************************************************************************/ 15/****************************************************************************/
15 16
16#if defined(CONFIG_M527x) || defined(CONFIG_M528x) 17#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
17/* 18/*
18 * Just figures, Motorola would have to change the offsets for 19 * Just figures, Motorola would have to change the offsets for
19 * registers in the same peripheral device on different models 20 * registers in the same peripheral device on different models
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
index 43b03c55f453..e2ebdcad553c 100644
--- a/drivers/serial/mcfserial.c
+++ b/drivers/serial/mcfserial.c
@@ -63,8 +63,13 @@ struct timer_list mcfrs_timer_struct;
63#endif 63#endif
64 64
65#if defined(CONFIG_HW_FEITH) 65#if defined(CONFIG_HW_FEITH)
66 #define CONSOLE_BAUD_RATE 38400 66#define CONSOLE_BAUD_RATE 38400
67 #define DEFAULT_CBAUD B38400 67#define DEFAULT_CBAUD B38400
68#endif
69
70#if defined(CONFIG_MOD5272)
71#define CONSOLE_BAUD_RATE 115200
72#define DEFAULT_CBAUD B115200
68#endif 73#endif
69 74
70#ifndef CONSOLE_BAUD_RATE 75#ifndef CONSOLE_BAUD_RATE
@@ -90,7 +95,7 @@ static struct tty_driver *mcfrs_serial_driver;
90#undef SERIAL_DEBUG_OPEN 95#undef SERIAL_DEBUG_OPEN
91#undef SERIAL_DEBUG_FLOW 96#undef SERIAL_DEBUG_FLOW
92 97
93#if defined(CONFIG_M527x) || defined(CONFIG_M528x) 98#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
94#define IRQBASE (MCFINT_VECBASE+MCFINT_UART0) 99#define IRQBASE (MCFINT_VECBASE+MCFINT_UART0)
95#else 100#else
96#define IRQBASE 73 101#define IRQBASE 73
@@ -1510,7 +1515,7 @@ static void mcfrs_irqinit(struct mcf_serial *info)
1510 *portp = (*portp & ~0x000000ff) | 0x00000055; 1515 *portp = (*portp & ~0x000000ff) | 0x00000055;
1511 portp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PDCNT); 1516 portp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PDCNT);
1512 *portp = (*portp & ~0x000003fc) | 0x000002a8; 1517 *portp = (*portp & ~0x000003fc) | 0x000002a8;
1513#elif defined(CONFIG_M527x) || defined(CONFIG_M528x) 1518#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
1514 volatile unsigned char *icrp, *uartp; 1519 volatile unsigned char *icrp, *uartp;
1515 volatile unsigned long *imrp; 1520 volatile unsigned long *imrp;
1516 1521
diff --git a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
index f8f21567cc22..50858273f8d3 100644
--- a/drivers/usb/class/audio.c
+++ b/drivers/usb/class/audio.c
@@ -631,8 +631,10 @@ static void usbin_stop(struct usb_audiodev *as)
631 i = u->flags; 631 i = u->flags;
632 spin_unlock_irqrestore(&as->lock, flags); 632 spin_unlock_irqrestore(&as->lock, flags);
633 while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) { 633 while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) {
634 set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); 634 if (notkilled)
635 schedule_timeout(1); 635 schedule_timeout_interruptible(1);
636 else
637 schedule_timeout_uninterruptible(1);
636 spin_lock_irqsave(&as->lock, flags); 638 spin_lock_irqsave(&as->lock, flags);
637 i = u->flags; 639 i = u->flags;
638 spin_unlock_irqrestore(&as->lock, flags); 640 spin_unlock_irqrestore(&as->lock, flags);
@@ -1102,8 +1104,10 @@ static void usbout_stop(struct usb_audiodev *as)
1102 i = u->flags; 1104 i = u->flags;
1103 spin_unlock_irqrestore(&as->lock, flags); 1105 spin_unlock_irqrestore(&as->lock, flags);
1104 while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) { 1106 while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) {
1105 set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); 1107 if (notkilled)
1106 schedule_timeout(1); 1108 schedule_timeout_interruptible(1);
1109 else
1110 schedule_timeout_uninterruptible(1);
1107 spin_lock_irqsave(&as->lock, flags); 1111 spin_lock_irqsave(&as->lock, flags);
1108 i = u->flags; 1112 i = u->flags;
1109 spin_unlock_irqrestore(&as->lock, flags); 1113 spin_unlock_irqrestore(&as->lock, flags);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 12ecdb03ee5f..1017a97a418b 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1606,7 +1606,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs * r)
1606 return IRQ_NONE; 1606 return IRQ_NONE;
1607 1607
1608 hcd->saw_irq = 1; 1608 hcd->saw_irq = 1;
1609 if (hcd->state != start && hcd->state == HC_STATE_HALT) 1609 if (hcd->state == HC_STATE_HALT)
1610 usb_hc_died (hcd); 1610 usb_hc_died (hcd);
1611 return IRQ_HANDLED; 1611 return IRQ_HANDLED;
1612} 1612}
@@ -1630,7 +1630,6 @@ void usb_hc_died (struct usb_hcd *hcd)
1630 spin_lock_irqsave (&hcd_root_hub_lock, flags); 1630 spin_lock_irqsave (&hcd_root_hub_lock, flags);
1631 if (hcd->rh_registered) { 1631 if (hcd->rh_registered) {
1632 hcd->poll_rh = 0; 1632 hcd->poll_rh = 0;
1633 del_timer(&hcd->rh_timer);
1634 1633
1635 /* make khubd clean up old urbs and devices */ 1634 /* make khubd clean up old urbs and devices */
1636 usb_set_device_state (hcd->self.root_hub, 1635 usb_set_device_state (hcd->self.root_hub,
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 758c7f0ed159..a12cab5314e9 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -435,6 +435,7 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
435static void hub_power_on(struct usb_hub *hub) 435static void hub_power_on(struct usb_hub *hub)
436{ 436{
437 int port1; 437 int port1;
438 unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2;
438 439
439 /* if hub supports power switching, enable power on each port */ 440 /* if hub supports power switching, enable power on each port */
440 if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) < 2) { 441 if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) < 2) {
@@ -444,8 +445,8 @@ static void hub_power_on(struct usb_hub *hub)
444 USB_PORT_FEAT_POWER); 445 USB_PORT_FEAT_POWER);
445 } 446 }
446 447
447 /* Wait for power to be enabled */ 448 /* Wait at least 100 msec for power to become stable */
448 msleep(hub->descriptor->bPwrOn2PwrGood * 2); 449 msleep(max(pgood_delay, (unsigned) 100));
449} 450}
450 451
451static void hub_quiesce(struct usb_hub *hub) 452static void hub_quiesce(struct usb_hub *hub)
@@ -1460,7 +1461,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
1460 port1, status); 1461 port1, status);
1461 else { 1462 else {
1462 status = hub_port_wait_reset(hub, port1, udev, delay); 1463 status = hub_port_wait_reset(hub, port1, udev, delay);
1463 if (status) 1464 if (status && status != -ENOTCONN)
1464 dev_dbg(hub->intfdev, 1465 dev_dbg(hub->intfdev,
1465 "port_wait_reset: err = %d\n", 1466 "port_wait_reset: err = %d\n",
1466 status); 1467 status);
@@ -1469,8 +1470,8 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
1469 /* return on disconnect or reset */ 1470 /* return on disconnect or reset */
1470 switch (status) { 1471 switch (status) {
1471 case 0: 1472 case 0:
1472 /* TRSTRCY = 10 ms */ 1473 /* TRSTRCY = 10 ms; plus some extra */
1473 msleep(10); 1474 msleep(10 + 40);
1474 /* FALL THROUGH */ 1475 /* FALL THROUGH */
1475 case -ENOTCONN: 1476 case -ENOTCONN:
1476 case -ENODEV: 1477 case -ENODEV:
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 020815397a49..5c40980a5bd9 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -483,6 +483,7 @@ ep_release (struct inode *inode, struct file *fd)
483 data->state = STATE_EP_DISABLED; 483 data->state = STATE_EP_DISABLED;
484 data->desc.bDescriptorType = 0; 484 data->desc.bDescriptorType = 0;
485 data->hs_desc.bDescriptorType = 0; 485 data->hs_desc.bDescriptorType = 0;
486 usb_ep_disable(data->ep);
486 } 487 }
487 put_ep (data); 488 put_ep (data);
488 return 0; 489 return 0;
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 2507e898af09..b948ffd94f45 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -400,6 +400,23 @@ static int ehci_hc_reset (struct usb_hcd *hcd)
400 return -EIO; 400 return -EIO;
401 } 401 }
402 break; 402 break;
403 case PCI_VENDOR_ID_NVIDIA:
404 /* NVidia reports that certain chips don't handle
405 * QH, ITD, or SITD addresses above 2GB. (But TD,
406 * data buffer, and periodic schedule are normal.)
407 */
408 switch (pdev->device) {
409 case 0x003c: /* MCP04 */
410 case 0x005b: /* CK804 */
411 case 0x00d8: /* CK8 */
412 case 0x00e8: /* CK8S */
413 if (pci_set_consistent_dma_mask(pdev,
414 DMA_31BIT_MASK) < 0)
415 ehci_warn (ehci, "can't enable NVidia "
416 "workaround for >2GB RAM\n");
417 break;
418 }
419 break;
403 } 420 }
404 421
405 /* optional debug port, normally in the first BAR */ 422 /* optional debug port, normally in the first BAR */
@@ -759,12 +776,16 @@ static int ehci_resume (struct usb_hcd *hcd)
759 if (time_before (jiffies, ehci->next_statechange)) 776 if (time_before (jiffies, ehci->next_statechange))
760 msleep (100); 777 msleep (100);
761 778
762 /* If any port is suspended, we know we can/must resume the HC. */ 779 /* If any port is suspended (or owned by the companion),
780 * we know we can/must resume the HC (and mustn't reset it).
781 */
763 for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) { 782 for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) {
764 u32 status; 783 u32 status;
765 port--; 784 port--;
766 status = readl (&ehci->regs->port_status [port]); 785 status = readl (&ehci->regs->port_status [port]);
767 if (status & PORT_SUSPEND) { 786 if (!(status & PORT_POWER))
787 continue;
788 if (status & (PORT_SUSPEND | PORT_OWNER)) {
768 down (&hcd->self.root_hub->serialize); 789 down (&hcd->self.root_hub->serialize);
769 retval = ehci_hub_resume (hcd); 790 retval = ehci_hub_resume (hcd);
770 up (&hcd->self.root_hub->serialize); 791 up (&hcd->self.root_hub->serialize);
@@ -1126,8 +1147,7 @@ rescan:
1126 case QH_STATE_UNLINK: /* wait for hw to finish? */ 1147 case QH_STATE_UNLINK: /* wait for hw to finish? */
1127idle_timeout: 1148idle_timeout:
1128 spin_unlock_irqrestore (&ehci->lock, flags); 1149 spin_unlock_irqrestore (&ehci->lock, flags);
1129 set_current_state (TASK_UNINTERRUPTIBLE); 1150 schedule_timeout_uninterruptible(1);
1130 schedule_timeout (1);
1131 goto rescan; 1151 goto rescan;
1132 case QH_STATE_IDLE: /* fully unlinked */ 1152 case QH_STATE_IDLE: /* fully unlinked */
1133 if (list_empty (&qh->qtd_list)) { 1153 if (list_empty (&qh->qtd_list)) {
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 36cc1f2218d5..18d3f2270316 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -54,7 +54,7 @@ static int ehci_hub_suspend (struct usb_hcd *hcd)
54 /* suspend any active/unsuspended ports, maybe allow wakeup */ 54 /* suspend any active/unsuspended ports, maybe allow wakeup */
55 while (port--) { 55 while (port--) {
56 u32 __iomem *reg = &ehci->regs->port_status [port]; 56 u32 __iomem *reg = &ehci->regs->port_status [port];
57 u32 t1 = readl (reg); 57 u32 t1 = readl (reg) & ~PORT_RWC_BITS;
58 u32 t2 = t1; 58 u32 t2 = t1;
59 59
60 if ((t1 & PORT_PE) && !(t1 & PORT_OWNER)) 60 if ((t1 & PORT_PE) && !(t1 & PORT_OWNER))
@@ -115,7 +115,8 @@ static int ehci_hub_resume (struct usb_hcd *hcd)
115 i = HCS_N_PORTS (ehci->hcs_params); 115 i = HCS_N_PORTS (ehci->hcs_params);
116 while (i--) { 116 while (i--) {
117 temp = readl (&ehci->regs->port_status [i]); 117 temp = readl (&ehci->regs->port_status [i]);
118 temp &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E); 118 temp &= ~(PORT_RWC_BITS
119 | PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E);
119 if (temp & PORT_SUSPEND) { 120 if (temp & PORT_SUSPEND) {
120 ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); 121 ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
121 temp |= PORT_RESUME; 122 temp |= PORT_RESUME;
@@ -128,7 +129,7 @@ static int ehci_hub_resume (struct usb_hcd *hcd)
128 temp = readl (&ehci->regs->port_status [i]); 129 temp = readl (&ehci->regs->port_status [i]);
129 if ((temp & PORT_SUSPEND) == 0) 130 if ((temp & PORT_SUSPEND) == 0)
130 continue; 131 continue;
131 temp &= ~PORT_RESUME; 132 temp &= ~(PORT_RWC_BITS | PORT_RESUME);
132 writel (temp, &ehci->regs->port_status [i]); 133 writel (temp, &ehci->regs->port_status [i]);
133 ehci_vdbg (ehci, "resumed port %d\n", i + 1); 134 ehci_vdbg (ehci, "resumed port %d\n", i + 1);
134 } 135 }
@@ -191,6 +192,7 @@ static int check_reset_complete (
191 192
192 // what happens if HCS_N_CC(params) == 0 ? 193 // what happens if HCS_N_CC(params) == 0 ?
193 port_status |= PORT_OWNER; 194 port_status |= PORT_OWNER;
195 port_status &= ~PORT_RWC_BITS;
194 writel (port_status, &ehci->regs->port_status [index]); 196 writel (port_status, &ehci->regs->port_status [index]);
195 197
196 } else 198 } else
@@ -233,7 +235,8 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
233 if (temp & PORT_OWNER) { 235 if (temp & PORT_OWNER) {
234 /* don't report this in GetPortStatus */ 236 /* don't report this in GetPortStatus */
235 if (temp & PORT_CSC) { 237 if (temp & PORT_CSC) {
236 temp &= ~PORT_CSC; 238 temp &= ~PORT_RWC_BITS;
239 temp |= PORT_CSC;
237 writel (temp, &ehci->regs->port_status [i]); 240 writel (temp, &ehci->regs->port_status [i]);
238 } 241 }
239 continue; 242 continue;
@@ -343,7 +346,7 @@ static int ehci_hub_control (
343 &ehci->regs->port_status [wIndex]); 346 &ehci->regs->port_status [wIndex]);
344 break; 347 break;
345 case USB_PORT_FEAT_C_ENABLE: 348 case USB_PORT_FEAT_C_ENABLE:
346 writel (temp | PORT_PEC, 349 writel((temp & ~PORT_RWC_BITS) | PORT_PEC,
347 &ehci->regs->port_status [wIndex]); 350 &ehci->regs->port_status [wIndex]);
348 break; 351 break;
349 case USB_PORT_FEAT_SUSPEND: 352 case USB_PORT_FEAT_SUSPEND:
@@ -353,7 +356,8 @@ static int ehci_hub_control (
353 if ((temp & PORT_PE) == 0) 356 if ((temp & PORT_PE) == 0)
354 goto error; 357 goto error;
355 /* resume signaling for 20 msec */ 358 /* resume signaling for 20 msec */
356 writel ((temp & ~PORT_WAKE_BITS) | PORT_RESUME, 359 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
360 writel (temp | PORT_RESUME,
357 &ehci->regs->port_status [wIndex]); 361 &ehci->regs->port_status [wIndex]);
358 ehci->reset_done [wIndex] = jiffies 362 ehci->reset_done [wIndex] = jiffies
359 + msecs_to_jiffies (20); 363 + msecs_to_jiffies (20);
@@ -364,15 +368,15 @@ static int ehci_hub_control (
364 break; 368 break;
365 case USB_PORT_FEAT_POWER: 369 case USB_PORT_FEAT_POWER:
366 if (HCS_PPC (ehci->hcs_params)) 370 if (HCS_PPC (ehci->hcs_params))
367 writel (temp & ~PORT_POWER, 371 writel (temp & ~(PORT_RWC_BITS | PORT_POWER),
368 &ehci->regs->port_status [wIndex]); 372 &ehci->regs->port_status [wIndex]);
369 break; 373 break;
370 case USB_PORT_FEAT_C_CONNECTION: 374 case USB_PORT_FEAT_C_CONNECTION:
371 writel (temp | PORT_CSC, 375 writel((temp & ~PORT_RWC_BITS) | PORT_CSC,
372 &ehci->regs->port_status [wIndex]); 376 &ehci->regs->port_status [wIndex]);
373 break; 377 break;
374 case USB_PORT_FEAT_C_OVER_CURRENT: 378 case USB_PORT_FEAT_C_OVER_CURRENT:
375 writel (temp | PORT_OCC, 379 writel((temp & ~PORT_RWC_BITS) | PORT_OCC,
376 &ehci->regs->port_status [wIndex]); 380 &ehci->regs->port_status [wIndex]);
377 break; 381 break;
378 case USB_PORT_FEAT_C_RESET: 382 case USB_PORT_FEAT_C_RESET:
@@ -416,7 +420,7 @@ static int ehci_hub_control (
416 420
417 /* stop resume signaling */ 421 /* stop resume signaling */
418 temp = readl (&ehci->regs->port_status [wIndex]); 422 temp = readl (&ehci->regs->port_status [wIndex]);
419 writel (temp & ~PORT_RESUME, 423 writel (temp & ~(PORT_RWC_BITS | PORT_RESUME),
420 &ehci->regs->port_status [wIndex]); 424 &ehci->regs->port_status [wIndex]);
421 retval = handshake ( 425 retval = handshake (
422 &ehci->regs->port_status [wIndex], 426 &ehci->regs->port_status [wIndex],
@@ -437,7 +441,7 @@ static int ehci_hub_control (
437 ehci->reset_done [wIndex] = 0; 441 ehci->reset_done [wIndex] = 0;
438 442
439 /* force reset to complete */ 443 /* force reset to complete */
440 writel (temp & ~PORT_RESET, 444 writel (temp & ~(PORT_RWC_BITS | PORT_RESET),
441 &ehci->regs->port_status [wIndex]); 445 &ehci->regs->port_status [wIndex]);
442 /* REVISIT: some hardware needs 550+ usec to clear 446 /* REVISIT: some hardware needs 550+ usec to clear
443 * this bit; seems too long to spin routinely... 447 * this bit; seems too long to spin routinely...
@@ -500,6 +504,7 @@ static int ehci_hub_control (
500 if (temp & PORT_OWNER) 504 if (temp & PORT_OWNER)
501 break; 505 break;
502 506
507 temp &= ~PORT_RWC_BITS;
503 switch (wValue) { 508 switch (wValue) {
504 case USB_PORT_FEAT_SUSPEND: 509 case USB_PORT_FEAT_SUSPEND:
505 if ((temp & PORT_PE) == 0 510 if ((temp & PORT_PE) == 0
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 20c9b550097d..f34a0516d35f 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -263,6 +263,7 @@ struct ehci_regs {
263#define PORT_PE (1<<2) /* port enable */ 263#define PORT_PE (1<<2) /* port enable */
264#define PORT_CSC (1<<1) /* connect status change */ 264#define PORT_CSC (1<<1) /* connect status change */
265#define PORT_CONNECT (1<<0) /* device connected */ 265#define PORT_CONNECT (1<<0) /* device connected */
266#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC)
266} __attribute__ ((packed)); 267} __attribute__ ((packed));
267 268
268/* Appendix C, Debug port ... intended for use with special "debug devices" 269/* Appendix C, Debug port ... intended for use with special "debug devices"
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 447f488f5d93..7924c74f958e 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -228,23 +228,22 @@ ohci_dump_roothub (
228 char **next, 228 char **next,
229 unsigned *size) 229 unsigned *size)
230{ 230{
231 u32 temp, ndp, i; 231 u32 temp, i;
232 232
233 temp = roothub_a (controller); 233 temp = roothub_a (controller);
234 if (temp == ~(u32)0) 234 if (temp == ~(u32)0)
235 return; 235 return;
236 ndp = (temp & RH_A_NDP);
237 236
238 if (verbose) { 237 if (verbose) {
239 ohci_dbg_sw (controller, next, size, 238 ohci_dbg_sw (controller, next, size,
240 "roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d\n", temp, 239 "roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d(%d)\n", temp,
241 ((temp & RH_A_POTPGT) >> 24) & 0xff, 240 ((temp & RH_A_POTPGT) >> 24) & 0xff,
242 (temp & RH_A_NOCP) ? " NOCP" : "", 241 (temp & RH_A_NOCP) ? " NOCP" : "",
243 (temp & RH_A_OCPM) ? " OCPM" : "", 242 (temp & RH_A_OCPM) ? " OCPM" : "",
244 (temp & RH_A_DT) ? " DT" : "", 243 (temp & RH_A_DT) ? " DT" : "",
245 (temp & RH_A_NPS) ? " NPS" : "", 244 (temp & RH_A_NPS) ? " NPS" : "",
246 (temp & RH_A_PSM) ? " PSM" : "", 245 (temp & RH_A_PSM) ? " PSM" : "",
247 ndp 246 (temp & RH_A_NDP), controller->num_ports
248 ); 247 );
249 temp = roothub_b (controller); 248 temp = roothub_b (controller);
250 ohci_dbg_sw (controller, next, size, 249 ohci_dbg_sw (controller, next, size,
@@ -266,7 +265,7 @@ ohci_dump_roothub (
266 ); 265 );
267 } 266 }
268 267
269 for (i = 0; i < ndp; i++) { 268 for (i = 0; i < controller->num_ports; i++) {
270 temp = roothub_portstatus (controller, i); 269 temp = roothub_portstatus (controller, i);
271 dbg_port_sw (controller, i, temp, next, size); 270 dbg_port_sw (controller, i, temp, next, size);
272 } 271 }
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 56b43f2a0e52..67c1aa5eb1c1 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -382,8 +382,7 @@ sanitize:
382 goto sanitize; 382 goto sanitize;
383 } 383 }
384 spin_unlock_irqrestore (&ohci->lock, flags); 384 spin_unlock_irqrestore (&ohci->lock, flags);
385 set_current_state (TASK_UNINTERRUPTIBLE); 385 schedule_timeout_uninterruptible(1);
386 schedule_timeout (1);
387 goto rescan; 386 goto rescan;
388 case ED_IDLE: /* fully unlinked */ 387 case ED_IDLE: /* fully unlinked */
389 if (list_empty (&ed->td_list)) { 388 if (list_empty (&ed->td_list)) {
@@ -485,6 +484,10 @@ static int ohci_init (struct ohci_hcd *ohci)
485 // flush the writes 484 // flush the writes
486 (void) ohci_readl (ohci, &ohci->regs->control); 485 (void) ohci_readl (ohci, &ohci->regs->control);
487 486
487 /* Read the number of ports unless overridden */
488 if (ohci->num_ports == 0)
489 ohci->num_ports = roothub_a(ohci) & RH_A_NDP;
490
488 if (ohci->hcca) 491 if (ohci->hcca)
489 return 0; 492 return 0;
490 493
@@ -561,10 +564,8 @@ static int ohci_run (struct ohci_hcd *ohci)
561 msleep(temp); 564 msleep(temp);
562 temp = roothub_a (ohci); 565 temp = roothub_a (ohci);
563 if (!(temp & RH_A_NPS)) { 566 if (!(temp & RH_A_NPS)) {
564 unsigned ports = temp & RH_A_NDP;
565
566 /* power down each port */ 567 /* power down each port */
567 for (temp = 0; temp < ports; temp++) 568 for (temp = 0; temp < ohci->num_ports; temp++)
568 ohci_writel (ohci, RH_PS_LSDA, 569 ohci_writel (ohci, RH_PS_LSDA,
569 &ohci->regs->roothub.portstatus [temp]); 570 &ohci->regs->roothub.portstatus [temp]);
570 } 571 }
@@ -720,6 +721,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
720 721
721 if (ints & OHCI_INTR_RD) { 722 if (ints & OHCI_INTR_RD) {
722 ohci_vdbg (ohci, "resume detect\n"); 723 ohci_vdbg (ohci, "resume detect\n");
724 ohci_writel (ohci, OHCI_INTR_RD, &regs->intrstatus);
723 if (hcd->state != HC_STATE_QUIESCING) 725 if (hcd->state != HC_STATE_QUIESCING)
724 schedule_work(&ohci->rh_resume); 726 schedule_work(&ohci->rh_resume);
725 } 727 }
@@ -861,7 +863,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
861 * and that if we try to turn them back on the root hub 863 * and that if we try to turn them back on the root hub
862 * will respond to CSC processing. 864 * will respond to CSC processing.
863 */ 865 */
864 i = roothub_a (ohci) & RH_A_NDP; 866 i = ohci->num_ports;
865 while (i--) 867 while (i--)
866 ohci_writel (ohci, RH_PS_PSS, 868 ohci_writel (ohci, RH_PS_PSS,
867 &ohci->regs->roothub.portstatus [temp]); 869 &ohci->regs->roothub.portstatus [temp]);
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 83ca4549a50e..ce7b28da7a15 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -184,7 +184,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
184 if (status != -EINPROGRESS) 184 if (status != -EINPROGRESS)
185 return status; 185 return status;
186 186
187 temp = roothub_a (ohci) & RH_A_NDP; 187 temp = ohci->num_ports;
188 enables = 0; 188 enables = 0;
189 while (temp--) { 189 while (temp--) {
190 u32 stat = ohci_readl (ohci, 190 u32 stat = ohci_readl (ohci,
@@ -304,7 +304,7 @@ static int
304ohci_hub_status_data (struct usb_hcd *hcd, char *buf) 304ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
305{ 305{
306 struct ohci_hcd *ohci = hcd_to_ohci (hcd); 306 struct ohci_hcd *ohci = hcd_to_ohci (hcd);
307 int ports, i, changed = 0, length = 1; 307 int i, changed = 0, length = 1;
308 int can_suspend = hcd->can_wakeup; 308 int can_suspend = hcd->can_wakeup;
309 unsigned long flags; 309 unsigned long flags;
310 310
@@ -319,9 +319,10 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
319 goto done; 319 goto done;
320 } 320 }
321 321
322 ports = roothub_a (ohci) & RH_A_NDP; 322 /* undocumented erratum seen on at least rev D */
323 if (ports > MAX_ROOT_PORTS) { 323 if ((ohci->flags & OHCI_QUIRK_AMD756)
324 ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ports, 324 && (roothub_a (ohci) & RH_A_NDP) > MAX_ROOT_PORTS) {
325 ohci_warn (ohci, "bogus NDP, rereads as NDP=%d\n",
325 ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP); 326 ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP);
326 /* retry later; "should not happen" */ 327 /* retry later; "should not happen" */
327 goto done; 328 goto done;
@@ -332,13 +333,13 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
332 buf [0] = changed = 1; 333 buf [0] = changed = 1;
333 else 334 else
334 buf [0] = 0; 335 buf [0] = 0;
335 if (ports > 7) { 336 if (ohci->num_ports > 7) {
336 buf [1] = 0; 337 buf [1] = 0;
337 length++; 338 length++;
338 } 339 }
339 340
340 /* look at each port */ 341 /* look at each port */
341 for (i = 0; i < ports; i++) { 342 for (i = 0; i < ohci->num_ports; i++) {
342 u32 status = roothub_portstatus (ohci, i); 343 u32 status = roothub_portstatus (ohci, i);
343 344
344 if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC 345 if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
@@ -395,15 +396,14 @@ ohci_hub_descriptor (
395 struct usb_hub_descriptor *desc 396 struct usb_hub_descriptor *desc
396) { 397) {
397 u32 rh = roothub_a (ohci); 398 u32 rh = roothub_a (ohci);
398 int ports = rh & RH_A_NDP;
399 u16 temp; 399 u16 temp;
400 400
401 desc->bDescriptorType = 0x29; 401 desc->bDescriptorType = 0x29;
402 desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24; 402 desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24;
403 desc->bHubContrCurrent = 0; 403 desc->bHubContrCurrent = 0;
404 404
405 desc->bNbrPorts = ports; 405 desc->bNbrPorts = ohci->num_ports;
406 temp = 1 + (ports / 8); 406 temp = 1 + (ohci->num_ports / 8);
407 desc->bDescLength = 7 + 2 * temp; 407 desc->bDescLength = 7 + 2 * temp;
408 408
409 temp = 0; 409 temp = 0;
@@ -421,7 +421,7 @@ ohci_hub_descriptor (
421 rh = roothub_b (ohci); 421 rh = roothub_b (ohci);
422 memset(desc->bitmap, 0xff, sizeof(desc->bitmap)); 422 memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
423 desc->bitmap [0] = rh & RH_B_DR; 423 desc->bitmap [0] = rh & RH_B_DR;
424 if (ports > 7) { 424 if (ohci->num_ports > 7) {
425 desc->bitmap [1] = (rh & RH_B_DR) >> 8; 425 desc->bitmap [1] = (rh & RH_B_DR) >> 8;
426 desc->bitmap [2] = 0xff; 426 desc->bitmap [2] = 0xff;
427 } else 427 } else
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index e5bc1789d18a..2fdb262d4726 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -75,33 +75,6 @@ static int pxa27x_ohci_select_pmm( int mode )
75 return 0; 75 return 0;
76} 76}
77 77
78/*
79 If you select PMM_PERPORT_MODE, you should set the port power
80 */
81static int pxa27x_ohci_set_port_power( int port )
82{
83 if ( (pxa27x_ohci_pmm_state==PMM_PERPORT_MODE)
84 && (port>0) && (port<PXA_UHC_MAX_PORTNUM) ) {
85 UHCRHPS(port) |= 0x100;
86 return 0;
87 }
88 return -1;
89}
90
91/*
92 If you select PMM_PERPORT_MODE, you should set the port power
93 */
94static int pxa27x_ohci_clear_port_power( int port )
95{
96 if ( (pxa27x_ohci_pmm_state==PMM_PERPORT_MODE)
97 && (port>0) && (port<PXA_UHC_MAX_PORTNUM) ) {
98 UHCRHPS(port) |= 0x200;
99 return 0;
100 }
101
102 return -1;
103}
104
105extern int usb_disabled(void); 78extern int usb_disabled(void);
106 79
107/*-------------------------------------------------------------------------*/ 80/*-------------------------------------------------------------------------*/
@@ -130,11 +103,17 @@ static void pxa27x_start_hc(struct platform_device *dev)
130 Polarity Low to active low. Supply power to USB ports. */ 103 Polarity Low to active low. Supply power to USB ports. */
131 UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) & 104 UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
132 ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE); 105 ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
106
107 pxa27x_ohci_pmm_state = PMM_PERPORT_MODE;
133 } 108 }
134 109
135 UHCHR &= ~UHCHR_SSE; 110 UHCHR &= ~UHCHR_SSE;
136 111
137 UHCHIE = (UHCHIE_UPRIE | UHCHIE_RWIE); 112 UHCHIE = (UHCHIE_UPRIE | UHCHIE_RWIE);
113
114 /* Clear any OTG Pin Hold */
115 if (PSSR & PSSR_OTGPH)
116 PSSR |= PSSR_OTGPH;
138} 117}
139 118
140static void pxa27x_stop_hc(struct platform_device *dev) 119static void pxa27x_stop_hc(struct platform_device *dev)
@@ -198,17 +177,7 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
198 pxa27x_start_hc(dev); 177 pxa27x_start_hc(dev);
199 178
200 /* Select Power Management Mode */ 179 /* Select Power Management Mode */
201 pxa27x_ohci_select_pmm( PMM_PERPORT_MODE ); 180 pxa27x_ohci_select_pmm(pxa27x_ohci_pmm_state);
202
203 /* If choosing PMM_PERPORT_MODE, we should set the port power before we use it. */
204 if (pxa27x_ohci_set_port_power(1) < 0)
205 printk(KERN_ERR "Setting port 1 power failed.\n");
206
207 if (pxa27x_ohci_clear_port_power(2) < 0)
208 printk(KERN_ERR "Setting port 2 power failed.\n");
209
210 if (pxa27x_ohci_clear_port_power(3) < 0)
211 printk(KERN_ERR "Setting port 3 power failed.\n");
212 181
213 ohci_hcd_init(hcd_to_ohci(hcd)); 182 ohci_hcd_init(hcd_to_ohci(hcd));
214 183
@@ -258,6 +227,9 @@ ohci_pxa27x_start (struct usb_hcd *hcd)
258 227
259 ohci_dbg (ohci, "ohci_pxa27x_start, ohci:%p", ohci); 228 ohci_dbg (ohci, "ohci_pxa27x_start, ohci:%p", ohci);
260 229
230 /* The value of NDP in roothub_a is incorrect on this hardware */
231 ohci->num_ports = 3;
232
261 if ((ret = ohci_init(ohci)) < 0) 233 if ((ret = ohci_init(ohci)) < 0)
262 return ret; 234 return ret;
263 235
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 71cdd2262860..8a9b9d9209e9 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -383,6 +383,7 @@ struct ohci_hcd {
383 /* 383 /*
384 * driver state 384 * driver state
385 */ 385 */
386 int num_ports;
386 int load [NUM_INTS]; 387 int load [NUM_INTS];
387 u32 hc_control; /* copy of hc control reg */ 388 u32 hc_control; /* copy of hc control reg */
388 unsigned long next_statechange; /* suspend/resume */ 389 unsigned long next_statechange; /* suspend/resume */
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 0d5d2545bf07..0c024898cbea 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -97,14 +97,9 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
97/* to make sure it doesn't hog all of the bandwidth */ 97/* to make sure it doesn't hog all of the bandwidth */
98#define DEPTH_INTERVAL 5 98#define DEPTH_INTERVAL 5
99 99
100static inline void restart_timer(struct uhci_hcd *uhci)
101{
102 mod_timer(&uhci->stall_timer, jiffies + msecs_to_jiffies(100));
103}
104
105#include "uhci-hub.c"
106#include "uhci-debug.c" 100#include "uhci-debug.c"
107#include "uhci-q.c" 101#include "uhci-q.c"
102#include "uhci-hub.c"
108 103
109/* 104/*
110 * Make sure the controller is completely inactive, unable to 105 * Make sure the controller is completely inactive, unable to
@@ -160,7 +155,6 @@ static void hc_died(struct uhci_hcd *uhci)
160{ 155{
161 reset_hc(uhci); 156 reset_hc(uhci);
162 uhci->hc_inaccessible = 1; 157 uhci->hc_inaccessible = 1;
163 del_timer(&uhci->stall_timer);
164} 158}
165 159
166/* 160/*
@@ -287,8 +281,11 @@ __acquires(uhci->lock)
287 /* Enable resume-detect interrupts if they work. 281 /* Enable resume-detect interrupts if they work.
288 * Then enter Global Suspend mode, still configured. 282 * Then enter Global Suspend mode, still configured.
289 */ 283 */
290 int_enable = (resume_detect_interrupts_are_broken(uhci) ? 284 uhci->working_RD = 1;
291 0 : USBINTR_RESUME); 285 int_enable = USBINTR_RESUME;
286 if (resume_detect_interrupts_are_broken(uhci)) {
287 uhci->working_RD = int_enable = 0;
288 }
292 outw(int_enable, uhci->io_addr + USBINTR); 289 outw(int_enable, uhci->io_addr + USBINTR);
293 outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD); 290 outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD);
294 mb(); 291 mb();
@@ -315,7 +312,6 @@ __acquires(uhci->lock)
315 312
316 uhci->rh_state = new_state; 313 uhci->rh_state = new_state;
317 uhci->is_stopped = UHCI_IS_STOPPED; 314 uhci->is_stopped = UHCI_IS_STOPPED;
318 del_timer(&uhci->stall_timer);
319 uhci_to_hcd(uhci)->poll_rh = !int_enable; 315 uhci_to_hcd(uhci)->poll_rh = !int_enable;
320 316
321 uhci_scan_schedule(uhci, NULL); 317 uhci_scan_schedule(uhci, NULL);
@@ -335,7 +331,6 @@ static void start_rh(struct uhci_hcd *uhci)
335 mb(); 331 mb();
336 uhci->rh_state = UHCI_RH_RUNNING; 332 uhci->rh_state = UHCI_RH_RUNNING;
337 uhci_to_hcd(uhci)->poll_rh = 1; 333 uhci_to_hcd(uhci)->poll_rh = 1;
338 restart_timer(uhci);
339} 334}
340 335
341static void wakeup_rh(struct uhci_hcd *uhci) 336static void wakeup_rh(struct uhci_hcd *uhci)
@@ -374,20 +369,6 @@ __acquires(uhci->lock)
374 mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); 369 mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
375} 370}
376 371
377static void stall_callback(unsigned long _uhci)
378{
379 struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci;
380 unsigned long flags;
381
382 spin_lock_irqsave(&uhci->lock, flags);
383 uhci_scan_schedule(uhci, NULL);
384 check_fsbr(uhci);
385
386 if (!uhci->is_stopped)
387 restart_timer(uhci);
388 spin_unlock_irqrestore(&uhci->lock, flags);
389}
390
391static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) 372static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
392{ 373{
393 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 374 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
@@ -418,8 +399,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
418 "host controller halted, " 399 "host controller halted, "
419 "very bad!\n"); 400 "very bad!\n");
420 hc_died(uhci); 401 hc_died(uhci);
421 spin_unlock_irqrestore(&uhci->lock, flags); 402
422 return IRQ_HANDLED; 403 /* Force a callback in case there are
404 * pending unlinks */
405 mod_timer(&hcd->rh_timer, jiffies);
423 } 406 }
424 spin_unlock_irqrestore(&uhci->lock, flags); 407 spin_unlock_irqrestore(&uhci->lock, flags);
425 } 408 }
@@ -427,10 +410,11 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
427 410
428 if (status & USBSTS_RD) 411 if (status & USBSTS_RD)
429 usb_hcd_poll_rh_status(hcd); 412 usb_hcd_poll_rh_status(hcd);
430 413 else {
431 spin_lock_irqsave(&uhci->lock, flags); 414 spin_lock_irqsave(&uhci->lock, flags);
432 uhci_scan_schedule(uhci, regs); 415 uhci_scan_schedule(uhci, regs);
433 spin_unlock_irqrestore(&uhci->lock, flags); 416 spin_unlock_irqrestore(&uhci->lock, flags);
417 }
434 418
435 return IRQ_HANDLED; 419 return IRQ_HANDLED;
436} 420}
@@ -595,10 +579,6 @@ static int uhci_start(struct usb_hcd *hcd)
595 579
596 init_waitqueue_head(&uhci->waitqh); 580 init_waitqueue_head(&uhci->waitqh);
597 581
598 init_timer(&uhci->stall_timer);
599 uhci->stall_timer.function = stall_callback;
600 uhci->stall_timer.data = (unsigned long) uhci;
601
602 uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl), 582 uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
603 &dma_handle, 0); 583 &dma_handle, 0);
604 if (!uhci->fl) { 584 if (!uhci->fl) {
@@ -745,11 +725,11 @@ static void uhci_stop(struct usb_hcd *hcd)
745 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 725 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
746 726
747 spin_lock_irq(&uhci->lock); 727 spin_lock_irq(&uhci->lock);
748 reset_hc(uhci); 728 if (!uhci->hc_inaccessible)
729 reset_hc(uhci);
749 uhci_scan_schedule(uhci, NULL); 730 uhci_scan_schedule(uhci, NULL);
750 spin_unlock_irq(&uhci->lock); 731 spin_unlock_irq(&uhci->lock);
751 732
752 del_timer_sync(&uhci->stall_timer);
753 release_uhci(uhci); 733 release_uhci(uhci);
754} 734}
755 735
@@ -811,13 +791,12 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
811 */ 791 */
812 pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); 792 pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
813 uhci->hc_inaccessible = 1; 793 uhci->hc_inaccessible = 1;
794 hcd->poll_rh = 0;
814 795
815 /* FIXME: Enable non-PME# remote wakeup? */ 796 /* FIXME: Enable non-PME# remote wakeup? */
816 797
817done: 798done:
818 spin_unlock_irq(&uhci->lock); 799 spin_unlock_irq(&uhci->lock);
819 if (rc == 0)
820 del_timer_sync(&hcd->rh_timer);
821 return rc; 800 return rc;
822} 801}
823 802
@@ -850,8 +829,11 @@ static int uhci_resume(struct usb_hcd *hcd)
850 829
851 spin_unlock_irq(&uhci->lock); 830 spin_unlock_irq(&uhci->lock);
852 831
853 if (hcd->poll_rh) 832 if (!uhci->working_RD) {
833 /* Suspended root hub needs to be polled */
834 hcd->poll_rh = 1;
854 usb_hcd_poll_rh_status(hcd); 835 usb_hcd_poll_rh_status(hcd);
836 }
855 return 0; 837 return 0;
856} 838}
857#endif 839#endif
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index bf9c5f9b508b..282f40b75881 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -345,9 +345,6 @@ enum uhci_rh_state {
345 345
346/* 346/*
347 * This describes the full uhci information. 347 * This describes the full uhci information.
348 *
349 * Note how the "proper" USB information is just
350 * a subset of what the full implementation needs.
351 */ 348 */
352struct uhci_hcd { 349struct uhci_hcd {
353 350
@@ -360,8 +357,6 @@ struct uhci_hcd {
360 struct dma_pool *qh_pool; 357 struct dma_pool *qh_pool;
361 struct dma_pool *td_pool; 358 struct dma_pool *td_pool;
362 359
363 struct usb_bus *bus;
364
365 struct uhci_td *term_td; /* Terminating TD, see UHCI bug */ 360 struct uhci_td *term_td; /* Terminating TD, see UHCI bug */
366 struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */ 361 struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */
367 362
@@ -380,6 +375,8 @@ struct uhci_hcd {
380 unsigned int scan_in_progress:1; /* Schedule scan is running */ 375 unsigned int scan_in_progress:1; /* Schedule scan is running */
381 unsigned int need_rescan:1; /* Redo the schedule scan */ 376 unsigned int need_rescan:1; /* Redo the schedule scan */
382 unsigned int hc_inaccessible:1; /* HC is suspended or dead */ 377 unsigned int hc_inaccessible:1; /* HC is suspended or dead */
378 unsigned int working_RD:1; /* Suspended root hub doesn't
379 need to be polled */
383 380
384 /* Support for port suspend/resume/reset */ 381 /* Support for port suspend/resume/reset */
385 unsigned long port_c_suspend; /* Bit-arrays of ports */ 382 unsigned long port_c_suspend; /* Bit-arrays of ports */
@@ -405,9 +402,7 @@ struct uhci_hcd {
405 /* List of URB's awaiting completion callback */ 402 /* List of URB's awaiting completion callback */
406 struct list_head complete_list; /* P: uhci->lock */ 403 struct list_head complete_list; /* P: uhci->lock */
407 404
408 int rh_numports; 405 int rh_numports; /* Number of root-hub ports */
409
410 struct timer_list stall_timer;
411 406
412 wait_queue_head_t waitqh; /* endpoint_disable waiters */ 407 wait_queue_head_t waitqh; /* endpoint_disable waiters */
413}; 408};
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index 4eace2b19ddb..a71e48a66805 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -145,15 +145,16 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
145{ 145{
146 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 146 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
147 unsigned long flags; 147 unsigned long flags;
148 int status; 148 int status = 0;
149 149
150 spin_lock_irqsave(&uhci->lock, flags); 150 spin_lock_irqsave(&uhci->lock, flags);
151 if (uhci->hc_inaccessible) {
152 status = 0;
153 goto done;
154 }
155 151
152 uhci_scan_schedule(uhci, NULL);
153 if (uhci->hc_inaccessible)
154 goto done;
155 check_fsbr(uhci);
156 uhci_check_ports(uhci); 156 uhci_check_ports(uhci);
157
157 status = get_hub_status_data(uhci, buf); 158 status = get_hub_status_data(uhci, buf);
158 159
159 switch (uhci->rh_state) { 160 switch (uhci->rh_state) {
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index bbb36cd6ed61..ea0d168a8c67 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -33,7 +33,7 @@ static void uhci_free_pending_tds(struct uhci_hcd *uhci);
33static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci) 33static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci)
34{ 34{
35 if (uhci->is_stopped) 35 if (uhci->is_stopped)
36 mod_timer(&uhci->stall_timer, jiffies); 36 mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
37 uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); 37 uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC);
38} 38}
39 39
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index 482c4be521f5..1e53934907c0 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -286,3 +286,23 @@ config USB_KEYSPAN_REMOTE
286 286
287 To compile this driver as a module, choose M here: the module will 287 To compile this driver as a module, choose M here: the module will
288 be called keyspan_remote. 288 be called keyspan_remote.
289
290config USB_APPLETOUCH
291 tristate "Apple USB Touchpad support"
292 depends on USB && INPUT
293 ---help---
294 Say Y here if you want to use an Apple USB Touchpad.
295
296 These are the touchpads that can be found on post-February 2005
297 Apple Powerbooks (prior models have a Synaptics touchpad connected
298 to the ADB bus).
299
300 This driver provides a basic mouse driver but can be interfaced
301 with the synaptics X11 driver to provide acceleration and
302 scrolling in X11.
303
304 For further information, see
305 <file:Documentation/input/appletouch.txt>.
306
307 To compile this driver as a module, choose M here: the
308 module will be called appletouch.
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
index 43b2f999edfe..5e03b93f29f6 100644
--- a/drivers/usb/input/Makefile
+++ b/drivers/usb/input/Makefile
@@ -41,3 +41,4 @@ obj-$(CONFIG_USB_WACOM) += wacom.o
41obj-$(CONFIG_USB_ACECAD) += acecad.o 41obj-$(CONFIG_USB_ACECAD) += acecad.o
42obj-$(CONFIG_USB_YEALINK) += yealink.o 42obj-$(CONFIG_USB_YEALINK) += yealink.o
43obj-$(CONFIG_USB_XPAD) += xpad.o 43obj-$(CONFIG_USB_XPAD) += xpad.o
44obj-$(CONFIG_USB_APPLETOUCH) += appletouch.o
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c
new file mode 100644
index 000000000000..e03c1c567a14
--- /dev/null
+++ b/drivers/usb/input/appletouch.c
@@ -0,0 +1,469 @@
1/*
2 * Apple USB Touchpad (for post-February 2005 PowerBooks) driver
3 *
4 * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
5 * Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net)
6 * Copyright (C) 2005 Stelian Pop (stelian@popies.net)
7 * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de)
8 * Copyright (C) 2005 Peter Osterlund (petero2@telia.com)
9 *
10 * Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *
26 */
27
28#include <linux/config.h>
29#include <linux/kernel.h>
30#include <linux/errno.h>
31#include <linux/init.h>
32#include <linux/slab.h>
33#include <linux/module.h>
34#include <linux/usb.h>
35#include <linux/input.h>
36#include <linux/usb_input.h>
37
38/* Apple has powerbooks which have the keyboard with different Product IDs */
39#define APPLE_VENDOR_ID 0x05AC
40
41#define ATP_DEVICE(prod) \
42 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
43 USB_DEVICE_ID_MATCH_INT_CLASS | \
44 USB_DEVICE_ID_MATCH_INT_PROTOCOL, \
45 .idVendor = APPLE_VENDOR_ID, \
46 .idProduct = (prod), \
47 .bInterfaceClass = 0x03, \
48 .bInterfaceProtocol = 0x02
49
50/* table of devices that work with this driver */
51static struct usb_device_id atp_table [] = {
52 { ATP_DEVICE(0x020E) },
53 { ATP_DEVICE(0x020F) },
54 { ATP_DEVICE(0x030A) },
55 { ATP_DEVICE(0x030B) },
56 { } /* Terminating entry */
57};
58MODULE_DEVICE_TABLE (usb, atp_table);
59
60/* size of a USB urb transfer */
61#define ATP_DATASIZE 81
62
63/*
64 * number of sensors. Note that only 16 instead of 26 X (horizontal)
65 * sensors exist on 12" and 15" PowerBooks. All models have 16 Y
66 * (vertical) sensors.
67 */
68#define ATP_XSENSORS 26
69#define ATP_YSENSORS 16
70
71/* amount of fuzz this touchpad generates */
72#define ATP_FUZZ 16
73
74/* maximum pressure this driver will report */
75#define ATP_PRESSURE 300
76/*
77 * multiplication factor for the X and Y coordinates.
78 * We try to keep the touchpad aspect ratio while still doing only simple
79 * arithmetics.
80 * The factors below give coordinates like:
81 * 0 <= x < 960 on 12" and 15" Powerbooks
82 * 0 <= x < 1600 on 17" Powerbooks
83 * 0 <= y < 646
84 */
85#define ATP_XFACT 64
86#define ATP_YFACT 43
87
88/*
89 * Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is
90 * ignored.
91 */
92#define ATP_THRESHOLD 5
93
94/* Structure to hold all of our device specific stuff */
95struct atp {
96 struct usb_device * udev; /* usb device */
97 struct urb * urb; /* usb request block */
98 signed char * data; /* transferred data */
99 int open; /* non-zero if opened */
100 struct input_dev input; /* input dev */
101 int valid; /* are the sensors valid ? */
102 int x_old; /* last reported x/y, */
103 int y_old; /* used for smoothing */
104 /* current value of the sensors */
105 signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS];
106 /* last value of the sensors */
107 signed char xy_old[ATP_XSENSORS + ATP_YSENSORS];
108 /* accumulated sensors */
109 int xy_acc[ATP_XSENSORS + ATP_YSENSORS];
110};
111
112#define dbg_dump(msg, tab) \
113 if (debug > 1) { \
114 int i; \
115 printk("appletouch: %s %lld", msg, (long long)jiffies); \
116 for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) \
117 printk(" %02x", tab[i]); \
118 printk("\n"); \
119 }
120
121#define dprintk(format, a...) \
122 do { \
123 if (debug) printk(format, ##a); \
124 } while (0)
125
126MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold");
127MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
128MODULE_LICENSE("GPL");
129
130static int debug = 1;
131module_param(debug, int, 0644);
132MODULE_PARM_DESC(debug, "Activate debugging output");
133
134static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
135 int *z, int *fingers)
136{
137 int i;
138 /* values to calculate mean */
139 int pcum = 0, psum = 0;
140
141 *fingers = 0;
142
143 for (i = 0; i < nb_sensors; i++) {
144 if (xy_sensors[i] < ATP_THRESHOLD)
145 continue;
146 if ((i - 1 < 0) || (xy_sensors[i - 1] < ATP_THRESHOLD))
147 (*fingers)++;
148 pcum += xy_sensors[i] * i;
149 psum += xy_sensors[i];
150 }
151
152 if (psum > 0) {
153 *z = psum;
154 return pcum * fact / psum;
155 }
156
157 return 0;
158}
159
160static inline void atp_report_fingers(struct input_dev *input, int fingers)
161{
162 input_report_key(input, BTN_TOOL_FINGER, fingers == 1);
163 input_report_key(input, BTN_TOOL_DOUBLETAP, fingers == 2);
164 input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2);
165}
166
167static void atp_complete(struct urb* urb, struct pt_regs* regs)
168{
169 int x, y, x_z, y_z, x_f, y_f;
170 int retval, i;
171 struct atp *dev = urb->context;
172
173 switch (urb->status) {
174 case 0:
175 /* success */
176 break;
177 case -ECONNRESET:
178 case -ENOENT:
179 case -ESHUTDOWN:
180 /* This urb is terminated, clean up */
181 dbg("%s - urb shutting down with status: %d",
182 __FUNCTION__, urb->status);
183 return;
184 default:
185 dbg("%s - nonzero urb status received: %d",
186 __FUNCTION__, urb->status);
187 goto exit;
188 }
189
190 /* drop incomplete datasets */
191 if (dev->urb->actual_length != ATP_DATASIZE) {
192 dprintk("appletouch: incomplete data package.\n");
193 goto exit;
194 }
195
196 /* reorder the sensors values */
197 for (i = 0; i < 8; i++) {
198 /* X values */
199 dev->xy_cur[i ] = dev->data[5 * i + 2];
200 dev->xy_cur[i + 8] = dev->data[5 * i + 4];
201 dev->xy_cur[i + 16] = dev->data[5 * i + 42];
202 if (i < 2)
203 dev->xy_cur[i + 24] = dev->data[5 * i + 44];
204
205 /* Y values */
206 dev->xy_cur[i + 26] = dev->data[5 * i + 1];
207 dev->xy_cur[i + 34] = dev->data[5 * i + 3];
208 }
209
210 dbg_dump("sample", dev->xy_cur);
211
212 if (!dev->valid) {
213 /* first sample */
214 dev->valid = 1;
215 dev->x_old = dev->y_old = -1;
216 memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
217
218 /* 17" Powerbooks have 10 extra X sensors */
219 for (i = 16; i < ATP_XSENSORS; i++)
220 if (dev->xy_cur[i]) {
221 printk("appletouch: 17\" model detected.\n");
222 input_set_abs_params(&dev->input, ABS_X, 0,
223 (ATP_XSENSORS - 1) *
224 ATP_XFACT - 1,
225 ATP_FUZZ, 0);
226 break;
227 }
228
229 goto exit;
230 }
231
232 for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) {
233 /* accumulate the change */
234 signed char change = dev->xy_old[i] - dev->xy_cur[i];
235 dev->xy_acc[i] -= change;
236
237 /* prevent down drifting */
238 if (dev->xy_acc[i] < 0)
239 dev->xy_acc[i] = 0;
240 }
241
242 memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
243
244 dbg_dump("accumulator", dev->xy_acc);
245
246 x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS,
247 ATP_XFACT, &x_z, &x_f);
248 y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,
249 ATP_YFACT, &y_z, &y_f);
250
251 if (x && y) {
252 if (dev->x_old != -1) {
253 x = (dev->x_old * 3 + x) >> 2;
254 y = (dev->y_old * 3 + y) >> 2;
255 dev->x_old = x;
256 dev->y_old = y;
257
258 if (debug > 1)
259 printk("appletouch: X: %3d Y: %3d "
260 "Xz: %3d Yz: %3d\n",
261 x, y, x_z, y_z);
262
263 input_report_key(&dev->input, BTN_TOUCH, 1);
264 input_report_abs(&dev->input, ABS_X, x);
265 input_report_abs(&dev->input, ABS_Y, y);
266 input_report_abs(&dev->input, ABS_PRESSURE,
267 min(ATP_PRESSURE, x_z + y_z));
268 atp_report_fingers(&dev->input, max(x_f, y_f));
269 }
270 dev->x_old = x;
271 dev->y_old = y;
272 }
273 else if (!x && !y) {
274
275 dev->x_old = dev->y_old = -1;
276 input_report_key(&dev->input, BTN_TOUCH, 0);
277 input_report_abs(&dev->input, ABS_PRESSURE, 0);
278 atp_report_fingers(&dev->input, 0);
279
280 /* reset the accumulator on release */
281 memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
282 }
283
284 input_report_key(&dev->input, BTN_LEFT, !!dev->data[80]);
285
286 input_sync(&dev->input);
287
288exit:
289 retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
290 if (retval) {
291 err("%s - usb_submit_urb failed with result %d",
292 __FUNCTION__, retval);
293 }
294}
295
296static int atp_open(struct input_dev *input)
297{
298 struct atp *dev = input->private;
299
300 if (usb_submit_urb(dev->urb, GFP_ATOMIC))
301 return -EIO;
302
303 dev->open = 1;
304 return 0;
305}
306
307static void atp_close(struct input_dev *input)
308{
309 struct atp *dev = input->private;
310
311 usb_kill_urb(dev->urb);
312 dev->open = 0;
313}
314
315static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id)
316{
317 struct atp *dev = NULL;
318 struct usb_host_interface *iface_desc;
319 struct usb_endpoint_descriptor *endpoint;
320 int int_in_endpointAddr = 0;
321 int i, retval = -ENOMEM;
322
323 /* allocate memory for our device state and initialize it */
324 dev = kmalloc(sizeof(struct atp), GFP_KERNEL);
325 if (dev == NULL) {
326 err("Out of memory");
327 goto err_kmalloc;
328 }
329 memset(dev, 0, sizeof(struct atp));
330
331 dev->udev = interface_to_usbdev(iface);
332
333 /* set up the endpoint information */
334 /* use only the first interrupt-in endpoint */
335 iface_desc = iface->cur_altsetting;
336 for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
337 endpoint = &iface_desc->endpoint[i].desc;
338 if (!int_in_endpointAddr &&
339 (endpoint->bEndpointAddress & USB_DIR_IN) &&
340 ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
341 == USB_ENDPOINT_XFER_INT)) {
342 /* we found an interrupt in endpoint */
343 int_in_endpointAddr = endpoint->bEndpointAddress;
344 break;
345 }
346 }
347 if (!int_in_endpointAddr) {
348 retval = -EIO;
349 err("Could not find int-in endpoint");
350 goto err_endpoint;
351 }
352
353 /* save our data pointer in this interface device */
354 usb_set_intfdata(iface, dev);
355
356 dev->urb = usb_alloc_urb(0, GFP_KERNEL);
357 if (!dev->urb) {
358 retval = -ENOMEM;
359 goto err_usballoc;
360 }
361 dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL,
362 &dev->urb->transfer_dma);
363 if (!dev->data) {
364 retval = -ENOMEM;
365 goto err_usbbufalloc;
366 }
367 usb_fill_int_urb(dev->urb, dev->udev,
368 usb_rcvintpipe(dev->udev, int_in_endpointAddr),
369 dev->data, ATP_DATASIZE, atp_complete, dev, 1);
370
371 init_input_dev(&dev->input);
372 dev->input.name = "appletouch";
373 dev->input.dev = &iface->dev;
374 dev->input.private = dev;
375 dev->input.open = atp_open;
376 dev->input.close = atp_close;
377
378 usb_to_input_id(dev->udev, &dev->input.id);
379
380 set_bit(EV_ABS, dev->input.evbit);
381
382 /*
383 * 12" and 15" Powerbooks only have 16 x sensors,
384 * 17" models are detected later.
385 */
386 input_set_abs_params(&dev->input, ABS_X, 0,
387 (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
388 input_set_abs_params(&dev->input, ABS_Y, 0,
389 (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
390 input_set_abs_params(&dev->input, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
391
392 set_bit(EV_KEY, dev->input.evbit);
393 set_bit(BTN_TOUCH, dev->input.keybit);
394 set_bit(BTN_TOOL_FINGER, dev->input.keybit);
395 set_bit(BTN_TOOL_DOUBLETAP, dev->input.keybit);
396 set_bit(BTN_TOOL_TRIPLETAP, dev->input.keybit);
397 set_bit(BTN_LEFT, dev->input.keybit);
398
399 input_register_device(&dev->input);
400
401 printk(KERN_INFO "input: appletouch connected\n");
402
403 return 0;
404
405err_usbbufalloc:
406 usb_free_urb(dev->urb);
407err_usballoc:
408 usb_set_intfdata(iface, NULL);
409err_endpoint:
410 kfree(dev);
411err_kmalloc:
412 return retval;
413}
414
415static void atp_disconnect(struct usb_interface *iface)
416{
417 struct atp *dev = usb_get_intfdata(iface);
418
419 usb_set_intfdata(iface, NULL);
420 if (dev) {
421 usb_kill_urb(dev->urb);
422 input_unregister_device(&dev->input);
423 usb_free_urb(dev->urb);
424 usb_buffer_free(dev->udev, ATP_DATASIZE,
425 dev->data, dev->urb->transfer_dma);
426 kfree(dev);
427 }
428 printk(KERN_INFO "input: appletouch disconnected\n");
429}
430
431static int atp_suspend(struct usb_interface *iface, pm_message_t message)
432{
433 struct atp *dev = usb_get_intfdata(iface);
434 usb_kill_urb(dev->urb);
435 dev->valid = 0;
436 return 0;
437}
438
439static int atp_resume(struct usb_interface *iface)
440{
441 struct atp *dev = usb_get_intfdata(iface);
442 if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC))
443 return -EIO;
444
445 return 0;
446}
447
448static struct usb_driver atp_driver = {
449 .owner = THIS_MODULE,
450 .name = "appletouch",
451 .probe = atp_probe,
452 .disconnect = atp_disconnect,
453 .suspend = atp_suspend,
454 .resume = atp_resume,
455 .id_table = atp_table,
456};
457
458static int __init atp_init(void)
459{
460 return usb_register(&atp_driver);
461}
462
463static void __exit atp_exit(void)
464{
465 usb_deregister(&atp_driver);
466}
467
468module_init(atp_init);
469module_exit(atp_exit);
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index e108e0a36b74..a99865c689c5 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1446,7 +1446,6 @@ void hid_init_reports(struct hid_device *hid)
1446 1446
1447#define USB_VENDOR_ID_APPLE 0x05ac 1447#define USB_VENDOR_ID_APPLE 0x05ac
1448#define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304 1448#define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304
1449#define USB_DEVICE_ID_APPLE_BLUETOOTH 0x1000
1450 1449
1451/* 1450/*
1452 * Alphabetically sorted blacklist by quirk type. 1451 * Alphabetically sorted blacklist by quirk type.
@@ -1465,7 +1464,6 @@ static struct hid_blacklist {
1465 { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE }, 1464 { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE },
1466 { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE }, 1465 { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE },
1467 { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE }, 1466 { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE },
1468 { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_BLUETOOTH, HID_QUIRK_IGNORE },
1469 { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE }, 1467 { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
1470 { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE }, 1468 { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE },
1471 { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE }, 1469 { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE },
diff --git a/drivers/usb/misc/sisusbvga/Kconfig b/drivers/usb/misc/sisusbvga/Kconfig
index 3957e144caf7..7603cbe0865d 100644
--- a/drivers/usb/misc/sisusbvga/Kconfig
+++ b/drivers/usb/misc/sisusbvga/Kconfig
@@ -4,11 +4,43 @@ config USB_SISUSBVGA
4 depends on USB && USB_EHCI_HCD 4 depends on USB && USB_EHCI_HCD
5 ---help--- 5 ---help---
6 Say Y here if you intend to attach a USB2VGA dongle based on a 6 Say Y here if you intend to attach a USB2VGA dongle based on a
7 Net2280 and a SiS315 chip. 7 Net2280 and a SiS315 chip.
8 8
9 Note that this device requires a USB 2.0 host controller. It will not 9 Note that this device requires a USB 2.0 host controller. It will not
10 work with USB 1.x controllers. 10 work with USB 1.x controllers.
11 11
12 To compile this driver as a module, choose M here: the module will be 12 To compile this driver as a module, choose M here; the module will be
13 called sisusb. If unsure, say N. 13 called sisusbvga. If unsure, say N.
14
15config USB_SISUSBVGA_CON
16 bool "Text console and mode switching support" if USB_SISUSBVGA
17 depends on VT
18 select FONT_8x16
19 ---help---
20 Say Y here if you want a VGA text console via the USB dongle or
21 want to support userland applications that utilize the driver's
22 display mode switching capabilities.
23
24 Note that this console supports VGA/EGA text mode only.
25
26 By default, the console part of the driver will not kick in when
27 the driver is initialized. If you want the driver to take over
28 one or more of the consoles, you need to specify the number of
29 the first and last consoles (starting at 1) as driver parameters.
30
31 For example, if the driver is compiled as a module:
32
33 modprobe sisusbvga first=1 last=5
34
35 If you use hotplug, add this to your modutils config files with
36 the "options" keyword, such as eg.
37
38 options sisusbvga first=1 last=5
39
40 If the driver is compiled into the kernel image, the parameters
41 must be given in the kernel command like, such as
42
43 sisusbvga.first=1 sisusbvga.last=5
44
45
14 46
diff --git a/drivers/usb/misc/sisusbvga/Makefile b/drivers/usb/misc/sisusbvga/Makefile
index 76f1643ceaf8..7f934cfc906c 100644
--- a/drivers/usb/misc/sisusbvga/Makefile
+++ b/drivers/usb/misc/sisusbvga/Makefile
@@ -2,5 +2,7 @@
2# Makefile for the sisusb driver (if driver is inside kernel tree). 2# Makefile for the sisusb driver (if driver is inside kernel tree).
3# 3#
4 4
5obj-$(CONFIG_USB_SISUSBVGA) += sisusb.o 5obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga.o
6
7sisusbvga-objs := sisusb.o sisusb_init.o sisusb_con.o
6 8
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index d63ce6c030f3..39db3155723a 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -1,6 +1,8 @@
1/* 1/*
2 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles 2 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
3 * 3 *
4 * Main part
5 *
4 * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria 6 * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
5 * 7 *
6 * If distributed as part of the Linux kernel, this code is licensed under the 8 * If distributed as part of the Linux kernel, this code is licensed under the
@@ -48,16 +50,60 @@
48#include <linux/kref.h> 50#include <linux/kref.h>
49#include <linux/usb.h> 51#include <linux/usb.h>
50#include <linux/smp_lock.h> 52#include <linux/smp_lock.h>
53#include <linux/vmalloc.h>
51 54
52#include "sisusb.h" 55#include "sisusb.h"
53 56
57#ifdef INCL_SISUSB_CON
58#include <linux/font.h>
59#endif
60
54#define SISUSB_DONTSYNC 61#define SISUSB_DONTSYNC
55 62
56/* Forward declarations / clean-up routines */ 63/* Forward declarations / clean-up routines */
57 64
65#ifdef INCL_SISUSB_CON
66int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data);
67int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data);
68int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data);
69int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data);
70int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand, u8 myor);
71int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor);
72int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand);
73
74int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);
75int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data);
76int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data);
77int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data);
78int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
79 u32 dest, int length, size_t *bytes_written);
80
81int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);
82
83extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
84extern int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
85
86extern void sisusb_init_concode(void);
87extern int sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last);
88extern void sisusb_console_exit(struct sisusb_usb_data *sisusb);
89
90extern void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location);
91
92extern int sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
93 u8 *arg, int cmapsz, int ch512, int dorecalc,
94 struct vc_data *c, int fh, int uplock);
95
96static int sisusb_first_vc = 0;
97static int sisusb_last_vc = 0;
98module_param_named(first, sisusb_first_vc, int, 0);
99module_param_named(last, sisusb_last_vc, int, 0);
100MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
101MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
102#endif
103
58static struct usb_driver sisusb_driver; 104static struct usb_driver sisusb_driver;
59 105
60static DECLARE_MUTEX(disconnect_sem); 106DECLARE_MUTEX(disconnect_sem);
61 107
62static void 108static void
63sisusb_free_buffers(struct sisusb_usb_data *sisusb) 109sisusb_free_buffers(struct sisusb_usb_data *sisusb)
@@ -639,7 +685,10 @@ static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
639 685
640/* The following routines assume being used to transfer byte, word, 686/* The following routines assume being used to transfer byte, word,
641 * long etc. 687 * long etc.
642 * This means that they assume "data" in machine endianness format. 688 * This means that
689 * - the write routines expect "data" in machine endianness format.
690 * The data will be converted to leXX in sisusb_xxx_packet.
691 * - the read routines can expect read data in machine-endianess.
643 */ 692 */
644 693
645static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type, 694static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,
@@ -839,7 +888,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
839 if (get_user(swap16, (u16 __user *)userbuffer)) 888 if (get_user(swap16, (u16 __user *)userbuffer))
840 return -EFAULT; 889 return -EFAULT;
841 } else 890 } else
842 swap16 = (kernbuffer[0] << 8) | kernbuffer[1]; 891 swap16 = *((u16 *)kernbuffer);
843 892
844 ret = sisusb_write_memio_word(sisusb, 893 ret = sisusb_write_memio_word(sisusb,
845 SISUSB_TYPE_MEM, 894 SISUSB_TYPE_MEM,
@@ -855,14 +904,25 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
855 if (userbuffer) { 904 if (userbuffer) {
856 if (copy_from_user(&buf, userbuffer, 3)) 905 if (copy_from_user(&buf, userbuffer, 3))
857 return -EFAULT; 906 return -EFAULT;
858 907#ifdef __BIG_ENDIAN
859 swap32 = (buf[0] << 16) | 908 swap32 = (buf[0] << 16) |
860 (buf[1] << 8) | 909 (buf[1] << 8) |
861 buf[2]; 910 buf[2];
911#else
912 swap32 = (buf[2] << 16) |
913 (buf[1] << 8) |
914 buf[0];
915#endif
862 } else 916 } else
917#ifdef __BIG_ENDIAN
863 swap32 = (kernbuffer[0] << 16) | 918 swap32 = (kernbuffer[0] << 16) |
864 (kernbuffer[1] << 8) | 919 (kernbuffer[1] << 8) |
865 kernbuffer[2]; 920 kernbuffer[2];
921#else
922 swap32 = (kernbuffer[2] << 16) |
923 (kernbuffer[1] << 8) |
924 kernbuffer[0];
925#endif
866 926
867 ret = sisusb_write_memio_24bit(sisusb, 927 ret = sisusb_write_memio_24bit(sisusb,
868 SISUSB_TYPE_MEM, 928 SISUSB_TYPE_MEM,
@@ -879,10 +939,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
879 if (get_user(swap32, (u32 __user *)userbuffer)) 939 if (get_user(swap32, (u32 __user *)userbuffer))
880 return -EFAULT; 940 return -EFAULT;
881 } else 941 } else
882 swap32 = (kernbuffer[0] << 24) | 942 swap32 = *((u32 *)kernbuffer);
883 (kernbuffer[1] << 16) |
884 (kernbuffer[2] << 8) |
885 kernbuffer[3];
886 943
887 ret = sisusb_write_memio_long(sisusb, 944 ret = sisusb_write_memio_long(sisusb,
888 SISUSB_TYPE_MEM, 945 SISUSB_TYPE_MEM,
@@ -1005,6 +1062,10 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1005 return ret ? -EIO : 0; 1062 return ret ? -EIO : 0;
1006} 1063}
1007 1064
1065/* Remember: Read data in packet is in machine-endianess! So for
1066 * byte, word, 24bit, long no endian correction is necessary.
1067 */
1068
1008static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type, 1069static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
1009 u32 addr, u8 *data) 1070 u32 addr, u8 *data)
1010{ 1071{
@@ -1191,8 +1252,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1191 (u16 __user *)userbuffer)) 1252 (u16 __user *)userbuffer))
1192 return -EFAULT; 1253 return -EFAULT;
1193 } else { 1254 } else {
1194 kernbuffer[0] = swap16 >> 8; 1255 *((u16 *)kernbuffer) = swap16;
1195 kernbuffer[1] = swap16 & 0xff;
1196 } 1256 }
1197 } 1257 }
1198 return ret; 1258 return ret;
@@ -1202,9 +1262,15 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1202 addr, &swap32); 1262 addr, &swap32);
1203 if (!ret) { 1263 if (!ret) {
1204 (*bytes_read) += 3; 1264 (*bytes_read) += 3;
1265#ifdef __BIG_ENDIAN
1205 buf[0] = (swap32 >> 16) & 0xff; 1266 buf[0] = (swap32 >> 16) & 0xff;
1206 buf[1] = (swap32 >> 8) & 0xff; 1267 buf[1] = (swap32 >> 8) & 0xff;
1207 buf[2] = swap32 & 0xff; 1268 buf[2] = swap32 & 0xff;
1269#else
1270 buf[2] = (swap32 >> 16) & 0xff;
1271 buf[1] = (swap32 >> 8) & 0xff;
1272 buf[0] = swap32 & 0xff;
1273#endif
1208 if (userbuffer) { 1274 if (userbuffer) {
1209 if (copy_to_user(userbuffer, &buf[0], 3)) 1275 if (copy_to_user(userbuffer, &buf[0], 3))
1210 return -EFAULT; 1276 return -EFAULT;
@@ -1228,10 +1294,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1228 1294
1229 userbuffer += 4; 1295 userbuffer += 4;
1230 } else { 1296 } else {
1231 kernbuffer[0] = (swap32 >> 24) & 0xff; 1297 *((u32 *)kernbuffer) = swap32;
1232 kernbuffer[1] = (swap32 >> 16) & 0xff;
1233 kernbuffer[2] = (swap32 >> 8) & 0xff;
1234 kernbuffer[3] = swap32 & 0xff;
1235 kernbuffer += 4; 1298 kernbuffer += 4;
1236 } 1299 }
1237 addr += 4; 1300 addr += 4;
@@ -1289,7 +1352,24 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
1289 1352
1290/* High level: Gfx (indexed) register access */ 1353/* High level: Gfx (indexed) register access */
1291 1354
1292static int 1355#ifdef INCL_SISUSB_CON
1356int
1357sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data)
1358{
1359 return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1360}
1361
1362int
1363sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data)
1364{
1365 return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
1366}
1367#endif
1368
1369#ifndef INCL_SISUSB_CON
1370static
1371#endif
1372int
1293sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data) 1373sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
1294{ 1374{
1295 int ret; 1375 int ret;
@@ -1298,7 +1378,10 @@ sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
1298 return ret; 1378 return ret;
1299} 1379}
1300 1380
1301static int 1381#ifndef INCL_SISUSB_CON
1382static
1383#endif
1384int
1302sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data) 1385sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
1303{ 1386{
1304 int ret; 1387 int ret;
@@ -1307,7 +1390,10 @@ sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
1307 return ret; 1390 return ret;
1308} 1391}
1309 1392
1310static int 1393#ifndef INCL_SISUSB_CON
1394static
1395#endif
1396int
1311sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, 1397sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
1312 u8 myand, u8 myor) 1398 u8 myand, u8 myor)
1313{ 1399{
@@ -1336,18 +1422,89 @@ sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx,
1336 return ret; 1422 return ret;
1337} 1423}
1338 1424
1339static int 1425#ifndef INCL_SISUSB_CON
1426static
1427#endif
1428int
1340sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor) 1429sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor)
1341{ 1430{
1342 return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor)); 1431 return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));
1343} 1432}
1344 1433
1345static int 1434#ifndef INCL_SISUSB_CON
1435static
1436#endif
1437int
1346sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand) 1438sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand)
1347{ 1439{
1348 return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00)); 1440 return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00));
1349} 1441}
1350 1442
1443/* Write/read video ram */
1444
1445#ifdef INCL_SISUSB_CON
1446int
1447sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data)
1448{
1449 return(sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
1450}
1451
1452int
1453sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)
1454{
1455 return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
1456}
1457
1458int
1459sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data)
1460{
1461 return(sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
1462}
1463
1464int
1465sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data)
1466{
1467 return(sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
1468}
1469
1470int
1471sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
1472 u32 dest, int length, size_t *bytes_written)
1473{
1474 return(sisusb_write_mem_bulk(sisusb, dest, src, length, NULL, 0, bytes_written));
1475}
1476
1477#ifdef SISUSBENDIANTEST
1478int
1479sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
1480 u32 src, int length, size_t *bytes_written)
1481{
1482 return(sisusb_read_mem_bulk(sisusb, src, dest, length, NULL, bytes_written));
1483}
1484#endif
1485#endif
1486
1487#ifdef SISUSBENDIANTEST
1488static void
1489sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
1490{
1491 static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
1492 char destbuffer[10];
1493 size_t dummy;
1494 int i,j;
1495
1496 sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy);
1497
1498 for(i = 1; i <= 7; i++) {
1499 printk(KERN_DEBUG "sisusb: rwtest %d bytes\n", i);
1500 sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy);
1501 for(j = 0; j < i; j++) {
1502 printk(KERN_DEBUG "sisusb: rwtest read[%d] = %x\n", j, destbuffer[j]);
1503 }
1504 }
1505}
1506#endif
1507
1351/* access pci config registers (reg numbers 0, 4, 8, etc) */ 1508/* access pci config registers (reg numbers 0, 4, 8, etc) */
1352 1509
1353static int 1510static int
@@ -2270,6 +2427,129 @@ sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
2270 return ret; 2427 return ret;
2271} 2428}
2272 2429
2430
2431#ifdef INCL_SISUSB_CON
2432
2433/* Set up default text mode:
2434 - Set text mode (0x03)
2435 - Upload default font
2436 - Upload user font (if available)
2437*/
2438
2439int
2440sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
2441{
2442 int ret = 0, slot = sisusb->font_slot, i;
2443 struct font_desc *myfont;
2444 u8 *tempbuf;
2445 u16 *tempbufb;
2446 size_t written;
2447 static char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
2448 static char bootlogo[] = "(o_ //\\ V_/_";
2449
2450 /* sisusb->lock is down */
2451
2452 if (!sisusb->SiS_Pr)
2453 return 1;
2454
2455 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
2456 sisusb->SiS_Pr->sisusb = (void *)sisusb;
2457
2458 /* Set mode 0x03 */
2459 SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
2460
2461 if (!(myfont = find_font("VGA8x16")))
2462 return 1;
2463
2464 if (!(tempbuf = vmalloc(8192)))
2465 return 1;
2466
2467 for (i = 0; i < 256; i++)
2468 memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
2469
2470 /* Upload default font */
2471 ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, 0, 1, NULL, 16, 0);
2472
2473 vfree(tempbuf);
2474
2475 /* Upload user font (and reset current slot) */
2476 if (sisusb->font_backup) {
2477 ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
2478 8192, sisusb->font_backup_512, 1, NULL,
2479 sisusb->font_backup_height, 0);
2480 if (slot != 2)
2481 sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
2482 NULL, 16, 0);
2483 }
2484
2485 if (init && !sisusb->scrbuf) {
2486
2487 if ((tempbuf = vmalloc(8192))) {
2488
2489 i = 4096;
2490 tempbufb = (u16 *)tempbuf;
2491 while (i--)
2492 *(tempbufb++) = 0x0720;
2493
2494 i = 0;
2495 tempbufb = (u16 *)tempbuf;
2496 while (bootlogo[i]) {
2497 *(tempbufb++) = 0x0700 | bootlogo[i++];
2498 if (!(i % 4))
2499 tempbufb += 76;
2500 }
2501
2502 i = 0;
2503 tempbufb = (u16 *)tempbuf + 6;
2504 while (bootstring[i])
2505 *(tempbufb++) = 0x0700 | bootstring[i++];
2506
2507 ret |= sisusb_copy_memory(sisusb, tempbuf,
2508 sisusb->vrambase, 8192, &written);
2509
2510 vfree(tempbuf);
2511
2512 }
2513
2514 } else if (sisusb->scrbuf) {
2515
2516 ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
2517 sisusb->vrambase, sisusb->scrbuf_size, &written);
2518
2519 }
2520
2521 if (sisusb->sisusb_cursor_size_from >= 0 &&
2522 sisusb->sisusb_cursor_size_to >= 0) {
2523 sisusb_setidxreg(sisusb, SISCR, 0x0a,
2524 sisusb->sisusb_cursor_size_from);
2525 sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
2526 sisusb->sisusb_cursor_size_to);
2527 } else {
2528 sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
2529 sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
2530 sisusb->sisusb_cursor_size_to = -1;
2531 }
2532
2533 slot = sisusb->sisusb_cursor_loc;
2534 if(slot < 0) slot = 0;
2535
2536 sisusb->sisusb_cursor_loc = -1;
2537 sisusb->bad_cursor_pos = 1;
2538
2539 sisusb_set_cursor(sisusb, slot);
2540
2541 sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
2542 sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
2543
2544 sisusb->textmodedestroyed = 0;
2545
2546 /* sisusb->lock is down */
2547
2548 return ret;
2549}
2550
2551#endif
2552
2273/* fops */ 2553/* fops */
2274 2554
2275static int 2555static int
@@ -2329,7 +2609,7 @@ sisusb_open(struct inode *inode, struct file *file)
2329 } 2609 }
2330 } 2610 }
2331 2611
2332 /* increment usage count for the device */ 2612 /* Increment usage count for our sisusb */
2333 kref_get(&sisusb->kref); 2613 kref_get(&sisusb->kref);
2334 2614
2335 sisusb->isopen = 1; 2615 sisusb->isopen = 1;
@@ -2340,12 +2620,10 @@ sisusb_open(struct inode *inode, struct file *file)
2340 2620
2341 up(&disconnect_sem); 2621 up(&disconnect_sem);
2342 2622
2343 printk(KERN_DEBUG "sisusbvga[%d]: opened", sisusb->minor);
2344
2345 return 0; 2623 return 0;
2346} 2624}
2347 2625
2348static void 2626void
2349sisusb_delete(struct kref *kref) 2627sisusb_delete(struct kref *kref)
2350{ 2628{
2351 struct sisusb_usb_data *sisusb = to_sisusb_dev(kref); 2629 struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
@@ -2359,6 +2637,9 @@ sisusb_delete(struct kref *kref)
2359 sisusb->sisusb_dev = NULL; 2637 sisusb->sisusb_dev = NULL;
2360 sisusb_free_buffers(sisusb); 2638 sisusb_free_buffers(sisusb);
2361 sisusb_free_urbs(sisusb); 2639 sisusb_free_urbs(sisusb);
2640#ifdef INCL_SISUSB_CON
2641 kfree(sisusb->SiS_Pr);
2642#endif
2362 kfree(sisusb); 2643 kfree(sisusb);
2363} 2644}
2364 2645
@@ -2395,8 +2676,6 @@ sisusb_release(struct inode *inode, struct file *file)
2395 2676
2396 up(&disconnect_sem); 2677 up(&disconnect_sem);
2397 2678
2398 printk(KERN_DEBUG "sisusbvga[%d]: released", myminor);
2399
2400 return 0; 2679 return 0;
2401} 2680}
2402 2681
@@ -2733,6 +3012,12 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
2733 int retval, port, length; 3012 int retval, port, length;
2734 u32 address; 3013 u32 address;
2735 3014
3015 /* All our commands require the device
3016 * to be initialized.
3017 */
3018 if (!sisusb->devinit)
3019 return -ENODEV;
3020
2736 port = y->data3 - 3021 port = y->data3 -
2737 SISUSB_PCI_PSEUDO_IOPORTBASE + 3022 SISUSB_PCI_PSEUDO_IOPORTBASE +
2738 SISUSB_PCI_IOPORTBASE; 3023 SISUSB_PCI_IOPORTBASE;
@@ -2774,6 +3059,10 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
2774 break; 3059 break;
2775 3060
2776 case SUCMD_CLRSCR: 3061 case SUCMD_CLRSCR:
3062 /* Gfx core must be initialized */
3063 if (!sisusb->gfxinit)
3064 return -ENODEV;
3065
2777 length = (y->data0 << 16) | (y->data1 << 8) | y->data2; 3066 length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
2778 address = y->data3 - 3067 address = y->data3 -
2779 SISUSB_PCI_PSEUDO_MEMBASE + 3068 SISUSB_PCI_PSEUDO_MEMBASE +
@@ -2781,11 +3070,61 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
2781 retval = sisusb_clear_vram(sisusb, address, length); 3070 retval = sisusb_clear_vram(sisusb, address, length);
2782 break; 3071 break;
2783 3072
3073 case SUCMD_HANDLETEXTMODE:
3074 retval = 0;
3075#ifdef INCL_SISUSB_CON
3076 /* Gfx core must be initialized, SiS_Pr must exist */
3077 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
3078 return -ENODEV;
3079
3080 switch (y->data0) {
3081 case 0:
3082 retval = sisusb_reset_text_mode(sisusb, 0);
3083 break;
3084 case 1:
3085 sisusb->textmodedestroyed = 1;
3086 break;
3087 }
3088#endif
3089 break;
3090
3091#ifdef INCL_SISUSB_CON
3092 case SUCMD_SETMODE:
3093 /* Gfx core must be initialized, SiS_Pr must exist */
3094 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
3095 return -ENODEV;
3096
3097 retval = 0;
3098
3099 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
3100 sisusb->SiS_Pr->sisusb = (void *)sisusb;
3101
3102 if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
3103 retval = -EINVAL;
3104
3105 break;
3106
3107 case SUCMD_SETVESAMODE:
3108 /* Gfx core must be initialized, SiS_Pr must exist */
3109 if (!sisusb->gfxinit || !sisusb->SiS_Pr)
3110 return -ENODEV;
3111
3112 retval = 0;
3113
3114 sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
3115 sisusb->SiS_Pr->sisusb = (void *)sisusb;
3116
3117 if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
3118 retval = -EINVAL;
3119
3120 break;
3121#endif
3122
2784 default: 3123 default:
2785 retval = -EINVAL; 3124 retval = -EINVAL;
2786 } 3125 }
2787 3126
2788 if(retval > 0) 3127 if (retval > 0)
2789 retval = -EIO; 3128 retval = -EIO;
2790 3129
2791 return retval; 3130 return retval;
@@ -2835,6 +3174,11 @@ sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
2835 x.sisusb_vramsize = sisusb->vramsize; 3174 x.sisusb_vramsize = sisusb->vramsize;
2836 x.sisusb_minor = sisusb->minor; 3175 x.sisusb_minor = sisusb->minor;
2837 x.sisusb_fbdevactive= 0; 3176 x.sisusb_fbdevactive= 0;
3177#ifdef INCL_SISUSB_CON
3178 x.sisusb_conactive = sisusb->haveconsole ? 1 : 0;
3179#else
3180 x.sisusb_conactive = 0;
3181#endif
2838 3182
2839 if (copy_to_user((void __user *)arg, &x, sizeof(x))) 3183 if (copy_to_user((void __user *)arg, &x, sizeof(x)))
2840 retval = -EFAULT; 3184 retval = -EFAULT;
@@ -2895,9 +3239,13 @@ static struct file_operations usb_sisusb_fops = {
2895}; 3239};
2896 3240
2897static struct usb_class_driver usb_sisusb_class = { 3241static struct usb_class_driver usb_sisusb_class = {
3242#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
2898 .name = "usb/sisusbvga%d", 3243 .name = "usb/sisusbvga%d",
2899 .fops = &usb_sisusb_fops,
2900 .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, 3244 .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
3245#else
3246 .name = "sisusbvga%d",
3247#endif
3248 .fops = &usb_sisusb_fops,
2901 .minor_base = SISUSB_MINOR 3249 .minor_base = SISUSB_MINOR
2902}; 3250};
2903 3251
@@ -2994,12 +3342,25 @@ static int sisusb_probe(struct usb_interface *intf,
2994 printk(KERN_INFO "sisusbvga[%d]: Allocated %d output buffers\n", 3342 printk(KERN_INFO "sisusbvga[%d]: Allocated %d output buffers\n",
2995 sisusb->minor, sisusb->numobufs); 3343 sisusb->minor, sisusb->numobufs);
2996 3344
3345#ifdef INCL_SISUSB_CON
3346 /* Allocate our SiS_Pr */
3347 if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) {
3348 printk(KERN_ERR
3349 "sisusbvga[%d]: Failed to allocate SiS_Pr\n",
3350 sisusb->minor);
3351 }
3352#endif
3353
2997 /* Do remaining init stuff */ 3354 /* Do remaining init stuff */
2998 3355
2999 init_waitqueue_head(&sisusb->wait_q); 3356 init_waitqueue_head(&sisusb->wait_q);
3000 3357
3001 usb_set_intfdata(intf, sisusb); 3358 usb_set_intfdata(intf, sisusb);
3002 3359
3360 usb_get_dev(sisusb->sisusb_dev);
3361
3362 sisusb->present = 1;
3363
3003#ifdef SISUSB_OLD_CONFIG_COMPAT 3364#ifdef SISUSB_OLD_CONFIG_COMPAT
3004 { 3365 {
3005 int ret; 3366 int ret;
@@ -3014,14 +3375,19 @@ static int sisusb_probe(struct usb_interface *intf,
3014 sisusb->minor); 3375 sisusb->minor);
3015 else 3376 else
3016 sisusb->ioctl32registered = 1; 3377 sisusb->ioctl32registered = 1;
3017
3018 } 3378 }
3019#endif 3379#endif
3020 3380
3021 sisusb->present = 1;
3022
3023 if (dev->speed == USB_SPEED_HIGH) { 3381 if (dev->speed == USB_SPEED_HIGH) {
3024 if (sisusb_init_gfxdevice(sisusb, 1)) 3382 int initscreen = 1;
3383#ifdef INCL_SISUSB_CON
3384 if (sisusb_first_vc > 0 &&
3385 sisusb_last_vc > 0 &&
3386 sisusb_first_vc <= sisusb_last_vc &&
3387 sisusb_last_vc <= MAX_NR_CONSOLES)
3388 initscreen = 0;
3389#endif
3390 if (sisusb_init_gfxdevice(sisusb, initscreen))
3025 printk(KERN_ERR 3391 printk(KERN_ERR
3026 "sisusbvga[%d]: Failed to early " 3392 "sisusbvga[%d]: Failed to early "
3027 "initialize device\n", 3393 "initialize device\n",
@@ -3035,6 +3401,16 @@ static int sisusb_probe(struct usb_interface *intf,
3035 3401
3036 sisusb->ready = 1; 3402 sisusb->ready = 1;
3037 3403
3404#ifdef SISUSBENDIANTEST
3405 printk(KERN_DEBUG "sisusb: *** RWTEST ***\n");
3406 sisusb_testreadwrite(sisusb);
3407 printk(KERN_DEBUG "sisusb: *** RWTEST END ***\n");
3408#endif
3409
3410#ifdef INCL_SISUSB_CON
3411 sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
3412#endif
3413
3038 return 0; 3414 return 0;
3039 3415
3040error_4: 3416error_4:
@@ -3053,13 +3429,20 @@ static void sisusb_disconnect(struct usb_interface *intf)
3053 struct sisusb_usb_data *sisusb; 3429 struct sisusb_usb_data *sisusb;
3054 int minor; 3430 int minor;
3055 3431
3056 down(&disconnect_sem);
3057
3058 /* This should *not* happen */ 3432 /* This should *not* happen */
3059 if (!(sisusb = usb_get_intfdata(intf))) { 3433 if (!(sisusb = usb_get_intfdata(intf)))
3060 up(&disconnect_sem);
3061 return; 3434 return;
3062 } 3435
3436#ifdef INCL_SISUSB_CON
3437 sisusb_console_exit(sisusb);
3438#endif
3439
3440 /* The above code doesn't need the disconnect
3441 * semaphore to be down; its meaning is to
3442 * protect all other routines from the disconnect
3443 * case, not the other way round.
3444 */
3445 down(&disconnect_sem);
3063 3446
3064 down(&sisusb->lock); 3447 down(&sisusb->lock);
3065 3448
@@ -3123,11 +3506,17 @@ static int __init usb_sisusb_init(void)
3123{ 3506{
3124 int retval; 3507 int retval;
3125 3508
3509#ifdef INCL_SISUSB_CON
3510 sisusb_init_concode();
3511#endif
3512
3126 if (!(retval = usb_register(&sisusb_driver))) { 3513 if (!(retval = usb_register(&sisusb_driver))) {
3514
3127 printk(KERN_INFO "sisusb: Driver version %d.%d.%d\n", 3515 printk(KERN_INFO "sisusb: Driver version %d.%d.%d\n",
3128 SISUSB_VERSION, SISUSB_REVISION, SISUSB_PATCHLEVEL); 3516 SISUSB_VERSION, SISUSB_REVISION, SISUSB_PATCHLEVEL);
3129 printk(KERN_INFO 3517 printk(KERN_INFO
3130 "sisusb: Copyright (C) 2005 Thomas Winischhofer\n"); 3518 "sisusb: Copyright (C) 2005 Thomas Winischhofer\n");
3519
3131 } 3520 }
3132 3521
3133 return retval; 3522 return retval;
@@ -3142,6 +3531,6 @@ module_init(usb_sisusb_init);
3142module_exit(usb_sisusb_exit); 3531module_exit(usb_sisusb_exit);
3143 3532
3144MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>"); 3533MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
3145MODULE_DESCRIPTION("sisusb - Driver for Net2280/SiS315-based USB2VGA dongles"); 3534MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
3146MODULE_LICENSE("GPL"); 3535MODULE_LICENSE("GPL");
3147 3536
diff --git a/drivers/usb/misc/sisusbvga/sisusb.h b/drivers/usb/misc/sisusbvga/sisusb.h
index 1306d006a25a..401ff21d7881 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.h
+++ b/drivers/usb/misc/sisusbvga/sisusb.h
@@ -46,15 +46,36 @@
46#endif 46#endif
47#endif 47#endif
48 48
49/* For older kernels, support for text consoles is by default
50 * off. To ensable text console support, change the following:
51 */
52#if 0
53#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
54#define CONFIG_USB_SISUSBVGA_CON
55#endif
56#endif
57
49/* Version Information */ 58/* Version Information */
50 59
51#define SISUSB_VERSION 0 60#define SISUSB_VERSION 0
52#define SISUSB_REVISION 0 61#define SISUSB_REVISION 0
53#define SISUSB_PATCHLEVEL 7 62#define SISUSB_PATCHLEVEL 8
63
64/* Include console and mode switching code? */
65
66#ifdef CONFIG_USB_SISUSBVGA_CON
67#define INCL_SISUSB_CON 1
68#endif
69
70#ifdef INCL_SISUSB_CON
71#include <linux/console.h>
72#include <linux/vt_kern.h>
73#include "sisusb_struct.h"
74#endif
54 75
55/* USB related */ 76/* USB related */
56 77
57#define SISUSB_MINOR 133 /* FIXME */ 78#define SISUSB_MINOR 133 /* official */
58 79
59/* Size of the sisusb input/output buffers */ 80/* Size of the sisusb input/output buffers */
60#define SISUSB_IBUF_SIZE 0x01000 81#define SISUSB_IBUF_SIZE 0x01000
@@ -131,6 +152,26 @@ struct sisusb_usb_data {
131 unsigned char gfxinit; /* graphics core initialized? */ 152 unsigned char gfxinit; /* graphics core initialized? */
132 unsigned short chipid, chipvendor; 153 unsigned short chipid, chipvendor;
133 unsigned short chiprevision; 154 unsigned short chiprevision;
155#ifdef INCL_SISUSB_CON
156 struct SiS_Private *SiS_Pr;
157 unsigned long scrbuf;
158 unsigned int scrbuf_size;
159 int haveconsole, con_first, con_last;
160 int havethisconsole[MAX_NR_CONSOLES];
161 int textmodedestroyed;
162 unsigned int sisusb_num_columns; /* real number, not vt's idea */
163 int cur_start_addr, con_rolled_over;
164 int sisusb_cursor_loc, bad_cursor_pos;
165 int sisusb_cursor_size_from;
166 int sisusb_cursor_size_to;
167 int current_font_height, current_font_512;
168 int font_backup_size, font_backup_height, font_backup_512;
169 char *font_backup;
170 int font_slot;
171 struct vc_data *sisusb_display_fg;
172 int is_gfx;
173 int con_blanked;
174#endif
134}; 175};
135 176
136#define to_sisusb_dev(d) container_of(d, struct sisusb_usb_data, kref) 177#define to_sisusb_dev(d) container_of(d, struct sisusb_usb_data, kref)
@@ -249,7 +290,9 @@ struct sisusb_info {
249 290
250 __u32 sisusb_fbdevactive; /* != 0 if framebuffer device active */ 291 __u32 sisusb_fbdevactive; /* != 0 if framebuffer device active */
251 292
252 __u8 sisusb_reserved[32]; /* for future use */ 293 __u32 sisusb_conactive; /* != 0 if console driver active */
294
295 __u8 sisusb_reserved[28]; /* for future use */
253}; 296};
254 297
255struct sisusb_command { 298struct sisusb_command {
@@ -261,18 +304,24 @@ struct sisusb_command {
261 __u32 data4; /* for future use */ 304 __u32 data4; /* for future use */
262}; 305};
263 306
264#define SUCMD_GET 0x01 /* for all: data0 = index, data3 = port */ 307#define SUCMD_GET 0x01 /* for all: data0 = index, data3 = port */
265#define SUCMD_SET 0x02 /* data1 = value */ 308#define SUCMD_SET 0x02 /* data1 = value */
266#define SUCMD_SETOR 0x03 /* data1 = or */ 309#define SUCMD_SETOR 0x03 /* data1 = or */
267#define SUCMD_SETAND 0x04 /* data1 = and */ 310#define SUCMD_SETAND 0x04 /* data1 = and */
268#define SUCMD_SETANDOR 0x05 /* data1 = and, data2 = or */ 311#define SUCMD_SETANDOR 0x05 /* data1 = and, data2 = or */
269#define SUCMD_SETMASK 0x06 /* data1 = data, data2 = mask */ 312#define SUCMD_SETMASK 0x06 /* data1 = data, data2 = mask */
270 313
271#define SUCMD_CLRSCR 0x07 /* data0:1:2 = length, data3 = address */ 314#define SUCMD_CLRSCR 0x07 /* data0:1:2 = length, data3 = address */
315
316#define SUCMD_HANDLETEXTMODE 0x08 /* Reset/destroy text mode */
317
318#define SUCMD_SETMODE 0x09 /* Set a display mode (data3 = SiS mode) */
319#define SUCMD_SETVESAMODE 0x0a /* Set a display mode (data3 = VESA mode) */
272 320
273#define SISUSB_COMMAND _IOWR(0xF3,0x3D,struct sisusb_command) 321#define SISUSB_COMMAND _IOWR(0xF3,0x3D,struct sisusb_command)
274#define SISUSB_GET_CONFIG_SIZE _IOR(0xF3,0x3E,__u32) 322#define SISUSB_GET_CONFIG_SIZE _IOR(0xF3,0x3E,__u32)
275#define SISUSB_GET_CONFIG _IOR(0xF3,0x3F,struct sisusb_info) 323#define SISUSB_GET_CONFIG _IOR(0xF3,0x3F,struct sisusb_info)
324
276 325
277#endif /* SISUSB_H */ 326#endif /* SISUSB_H */
278 327
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c
new file mode 100644
index 000000000000..24584463553d
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_con.c
@@ -0,0 +1,1658 @@
1/*
2 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
3 *
4 * VGA text mode console part
5 *
6 * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
7 *
8 * If distributed as part of the Linux kernel, this code is licensed under the
9 * terms of the GPL v2.
10 *
11 * Otherwise, the following license terms apply:
12 *
13 * * Redistribution and use in source and binary forms, with or without
14 * * modification, are permitted provided that the following conditions
15 * * are met:
16 * * 1) Redistributions of source code must retain the above copyright
17 * * notice, this list of conditions and the following disclaimer.
18 * * 2) Redistributions in binary form must reproduce the above copyright
19 * * notice, this list of conditions and the following disclaimer in the
20 * * documentation and/or other materials provided with the distribution.
21 * * 3) The name of the author may not be used to endorse or promote products
22 * * derived from this software without specific psisusbr written permission.
23 * *
24 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
25 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 * Author: Thomas Winischhofer <thomas@winischhofer.net>
36 *
37 * Portions based on vgacon.c which are
38 * Created 28 Sep 1997 by Geert Uytterhoeven
39 * Rewritten by Martin Mares <mj@ucw.cz>, July 1998
40 * based on code Copyright (C) 1991, 1992 Linus Torvalds
41 * 1995 Jay Estabrook
42 *
43 * A note on using in_atomic() in here: We can't handle console
44 * calls from non-schedulable context due to our USB-dependend
45 * nature. For now, this driver just ignores any calls if it
46 * detects this state.
47 *
48 */
49
50#include <linux/config.h>
51#include <linux/version.h>
52#include <linux/module.h>
53#include <linux/kernel.h>
54#include <linux/signal.h>
55#include <linux/sched.h>
56#include <linux/fs.h>
57#include <linux/tty.h>
58#include <linux/console.h>
59#include <linux/string.h>
60#include <linux/kd.h>
61#include <linux/init.h>
62#include <linux/slab.h>
63#include <linux/vt_kern.h>
64#include <linux/selection.h>
65#include <linux/spinlock.h>
66#include <linux/kref.h>
67#include <linux/smp_lock.h>
68#include <linux/ioport.h>
69#include <linux/interrupt.h>
70#include <linux/vmalloc.h>
71
72#include "sisusb.h"
73
74#ifdef INCL_SISUSB_CON
75extern int sisusb_setreg(struct sisusb_usb_data *, int, u8);
76extern int sisusb_getreg(struct sisusb_usb_data *, int, u8 *);
77extern int sisusb_setidxreg(struct sisusb_usb_data *, int, u8, u8);
78extern int sisusb_getidxreg(struct sisusb_usb_data *, int, u8, u8 *);
79extern int sisusb_setidxregor(struct sisusb_usb_data *, int, u8, u8);
80extern int sisusb_setidxregand(struct sisusb_usb_data *, int, u8, u8);
81extern int sisusb_setidxregandor(struct sisusb_usb_data *, int, u8, u8, u8);
82
83extern int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);
84extern int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data);
85extern int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data);
86extern int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data);
87extern int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
88 u32 dest, int length, size_t *bytes_written);
89
90extern void sisusb_delete(struct kref *kref);
91extern int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);
92
93extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
94
95#define sisusbcon_writew(val, addr) (*(addr) = (val))
96#define sisusbcon_readw(addr) (*(addr))
97#define sisusbcon_memmovew(d, s, c) memmove(d, s, c)
98#define sisusbcon_memcpyw(d, s, c) memcpy(d, s, c)
99
100/* vc_data -> sisusb conversion table */
101static struct sisusb_usb_data *mysisusbs[MAX_NR_CONSOLES];
102
103/* Forward declaration */
104static const struct consw sisusb_con;
105
106extern struct semaphore disconnect_sem;
107
108static inline void
109sisusbcon_memsetw(u16 *s, u16 c, unsigned int count)
110{
111 count /= 2;
112 while (count--)
113 sisusbcon_writew(c, s++);
114}
115
116static inline void
117sisusb_initialize(struct sisusb_usb_data *sisusb)
118{
119 /* Reset cursor and start address */
120 if (sisusb_setidxreg(sisusb, SISCR, 0x0c, 0x00))
121 return;
122 if (sisusb_setidxreg(sisusb, SISCR, 0x0d, 0x00))
123 return;
124 if (sisusb_setidxreg(sisusb, SISCR, 0x0e, 0x00))
125 return;
126 sisusb_setidxreg(sisusb, SISCR, 0x0f, 0x00);
127}
128
129static inline void
130sisusbcon_set_start_address(struct sisusb_usb_data *sisusb, struct vc_data *c)
131{
132 sisusb->cur_start_addr = (c->vc_visible_origin - sisusb->scrbuf) / 2;
133
134 sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
135 sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
136}
137
138void
139sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location)
140{
141 if (sisusb->sisusb_cursor_loc == location)
142 return;
143
144 sisusb->sisusb_cursor_loc = location;
145
146 /* Hardware bug: Text cursor appears twice or not at all
147 * at some positions. Work around it with the cursor skew
148 * bits.
149 */
150
151 if ((location & 0x0007) == 0x0007) {
152 sisusb->bad_cursor_pos = 1;
153 location--;
154 if (sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0x1f, 0x20))
155 return;
156 } else if (sisusb->bad_cursor_pos) {
157 if (sisusb_setidxregand(sisusb, SISCR, 0x0b, 0x1f))
158 return;
159 sisusb->bad_cursor_pos = 0;
160 }
161
162 if (sisusb_setidxreg(sisusb, SISCR, 0x0e, (location >> 8)))
163 return;
164 sisusb_setidxreg(sisusb, SISCR, 0x0f, (location & 0xff));
165}
166
167static inline struct sisusb_usb_data *
168sisusb_get_sisusb(unsigned short console)
169{
170 return mysisusbs[console];
171}
172
173static inline int
174sisusb_sisusb_valid(struct sisusb_usb_data *sisusb)
175{
176 if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev)
177 return 0;
178
179 return 1;
180}
181
182static struct sisusb_usb_data *
183sisusb_get_sisusb_lock_and_check(unsigned short console)
184{
185 struct sisusb_usb_data *sisusb;
186
187 /* We can't handle console calls in non-schedulable
188 * context due to our locks and the USB transport.
189 * So we simply ignore them. This should only affect
190 * some calls to printk.
191 */
192 if (in_atomic())
193 return NULL;
194
195 if (!(sisusb = sisusb_get_sisusb(console)))
196 return NULL;
197
198 down(&sisusb->lock);
199
200 if (!sisusb_sisusb_valid(sisusb) ||
201 !sisusb->havethisconsole[console]) {
202 up(&sisusb->lock);
203 return NULL;
204 }
205
206 return sisusb;
207}
208
209static int
210sisusb_is_inactive(struct vc_data *c, struct sisusb_usb_data *sisusb)
211{
212 if (sisusb->is_gfx ||
213 sisusb->textmodedestroyed ||
214 c->vc_mode != KD_TEXT)
215 return 1;
216
217 return 0;
218}
219
220/* con_startup console interface routine */
221static const char *
222sisusbcon_startup(void)
223{
224 return "SISUSBCON";
225}
226
227/* con_init console interface routine */
228static void
229sisusbcon_init(struct vc_data *c, int init)
230{
231 struct sisusb_usb_data *sisusb;
232 int cols, rows;
233
234 /* This is called by take_over_console(),
235 * ie by us/under our control. It is
236 * only called after text mode and fonts
237 * are set up/restored.
238 */
239
240 down(&disconnect_sem);
241
242 if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
243 up(&disconnect_sem);
244 return;
245 }
246
247 down(&sisusb->lock);
248
249 if (!sisusb_sisusb_valid(sisusb)) {
250 up(&sisusb->lock);
251 up(&disconnect_sem);
252 return;
253 }
254
255 c->vc_can_do_color = 1;
256
257 c->vc_complement_mask = 0x7700;
258
259 c->vc_hi_font_mask = sisusb->current_font_512 ? 0x0800 : 0;
260
261 sisusb->haveconsole = 1;
262
263 sisusb->havethisconsole[c->vc_num] = 1;
264
265 /* We only support 640x400 */
266 c->vc_scan_lines = 400;
267
268 c->vc_font.height = sisusb->current_font_height;
269
270 /* We only support width = 8 */
271 cols = 80;
272 rows = c->vc_scan_lines / c->vc_font.height;
273
274 /* Increment usage count for our sisusb.
275 * Doing so saves us from upping/downing
276 * the disconnect semaphore; we can't
277 * lose our sisusb until this is undone
278 * in con_deinit. For all other console
279 * interface functions, it suffices to
280 * use sisusb->lock and do a quick check
281 * of sisusb for device disconnection.
282 */
283 kref_get(&sisusb->kref);
284
285 if (!*c->vc_uni_pagedir_loc)
286 con_set_default_unimap(c);
287
288 up(&sisusb->lock);
289
290 up(&disconnect_sem);
291
292 if (init) {
293 c->vc_cols = cols;
294 c->vc_rows = rows;
295 } else
296 vc_resize(c, cols, rows);
297}
298
299/* con_deinit console interface routine */
300static void
301sisusbcon_deinit(struct vc_data *c)
302{
303 struct sisusb_usb_data *sisusb;
304 int i;
305
306 /* This is called by take_over_console()
307 * and others, ie not under our control.
308 */
309
310 down(&disconnect_sem);
311
312 if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
313 up(&disconnect_sem);
314 return;
315 }
316
317 down(&sisusb->lock);
318
319 /* Clear ourselves in mysisusbs */
320 mysisusbs[c->vc_num] = NULL;
321
322 sisusb->havethisconsole[c->vc_num] = 0;
323
324 /* Free our font buffer if all consoles are gone */
325 if (sisusb->font_backup) {
326 for(i = 0; i < MAX_NR_CONSOLES; i++) {
327 if (sisusb->havethisconsole[c->vc_num])
328 break;
329 }
330 if (i == MAX_NR_CONSOLES) {
331 vfree(sisusb->font_backup);
332 sisusb->font_backup = NULL;
333 }
334 }
335
336 up(&sisusb->lock);
337
338 /* decrement the usage count on our sisusb */
339 kref_put(&sisusb->kref, sisusb_delete);
340
341 up(&disconnect_sem);
342}
343
344/* interface routine */
345static u8
346sisusbcon_build_attr(struct vc_data *c, u8 color, u8 intensity,
347 u8 blink, u8 underline, u8 reverse)
348{
349 u8 attr = color;
350
351 if (underline)
352 attr = (attr & 0xf0) | c->vc_ulcolor;
353 else if (intensity == 0)
354 attr = (attr & 0xf0) | c->vc_halfcolor;
355
356 if (reverse)
357 attr = ((attr) & 0x88) |
358 ((((attr) >> 4) |
359 ((attr) << 4)) & 0x77);
360
361 if (blink)
362 attr ^= 0x80;
363
364 if (intensity == 2)
365 attr ^= 0x08;
366
367 return attr;
368}
369
370/* Interface routine */
371static void
372sisusbcon_invert_region(struct vc_data *vc, u16 *p, int count)
373{
374 /* Invert a region. This is called with a pointer
375 * to the console's internal screen buffer. So we
376 * simply do the inversion there and rely on
377 * a call to putc(s) to update the real screen.
378 */
379
380 while (count--) {
381 u16 a = sisusbcon_readw(p);
382
383 a = ((a) & 0x88ff) |
384 (((a) & 0x7000) >> 4) |
385 (((a) & 0x0700) << 4);
386
387 sisusbcon_writew(a, p++);
388 }
389}
390
391#define SISUSB_VADDR(x,y) \
392 ((u16 *)c->vc_origin + \
393 (y) * sisusb->sisusb_num_columns + \
394 (x))
395
396#define SISUSB_HADDR(x,y) \
397 ((u16 *)(sisusb->vrambase + (c->vc_origin - sisusb->scrbuf)) + \
398 (y) * sisusb->sisusb_num_columns + \
399 (x))
400
401/* Interface routine */
402static void
403sisusbcon_putc(struct vc_data *c, int ch, int y, int x)
404{
405 struct sisusb_usb_data *sisusb;
406 ssize_t written;
407
408 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
409 return;
410
411 /* sisusb->lock is down */
412
413 /* Don't need to put the character into buffer ourselves,
414 * because the vt does this BEFORE calling us.
415 */
416#if 0
417 sisusbcon_writew(ch, SISUSB_VADDR(x, y));
418#endif
419
420 if (sisusb_is_inactive(c, sisusb)) {
421 up(&sisusb->lock);
422 return;
423 }
424
425
426 sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
427 (u32)SISUSB_HADDR(x, y), 2, &written);
428
429 up(&sisusb->lock);
430}
431
432/* Interface routine */
433static void
434sisusbcon_putcs(struct vc_data *c, const unsigned short *s,
435 int count, int y, int x)
436{
437 struct sisusb_usb_data *sisusb;
438 ssize_t written;
439 u16 *dest;
440 int i;
441
442 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
443 return;
444
445 /* sisusb->lock is down */
446
447 /* Need to put the characters into the buffer ourselves,
448 * because the vt does this AFTER calling us.
449 */
450
451 dest = SISUSB_VADDR(x, y);
452
453 for (i = count; i > 0; i--)
454 sisusbcon_writew(sisusbcon_readw(s++), dest++);
455
456 if (sisusb_is_inactive(c, sisusb)) {
457 up(&sisusb->lock);
458 return;
459 }
460
461 sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
462 (u32)SISUSB_HADDR(x, y), count * 2, &written);
463
464 up(&sisusb->lock);
465}
466
467/* Interface routine */
468static void
469sisusbcon_clear(struct vc_data *c, int y, int x, int height, int width)
470{
471 struct sisusb_usb_data *sisusb;
472 u16 eattr = c->vc_video_erase_char;
473 ssize_t written;
474 int i, length, cols;
475 u16 *dest;
476
477 if (width <= 0 || height <= 0)
478 return;
479
480 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
481 return;
482
483 /* sisusb->lock is down */
484
485 /* Need to clear buffer ourselves, because the vt does
486 * this AFTER calling us.
487 */
488
489 dest = SISUSB_VADDR(x, y);
490
491 cols = sisusb->sisusb_num_columns;
492
493 if (width > cols)
494 width = cols;
495
496 if (x == 0 && width >= c->vc_cols) {
497
498 sisusbcon_memsetw(dest, eattr, height * cols * 2);
499
500 } else {
501
502 for (i = height; i > 0; i--, dest += cols)
503 sisusbcon_memsetw(dest, eattr, width * 2);
504
505 }
506
507 if (sisusb_is_inactive(c, sisusb)) {
508 up(&sisusb->lock);
509 return;
510 }
511
512 length = ((height * cols) - x - (cols - width - x)) * 2;
513
514
515 sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(x, y),
516 (u32)SISUSB_HADDR(x, y), length, &written);
517
518 up(&sisusb->lock);
519}
520
521/* Interface routine */
522static void
523sisusbcon_bmove(struct vc_data *c, int sy, int sx,
524 int dy, int dx, int height, int width)
525{
526 struct sisusb_usb_data *sisusb;
527 ssize_t written;
528 int cols, length;
529#if 0
530 u16 *src, *dest;
531 int i;
532#endif
533
534 if (width <= 0 || height <= 0)
535 return;
536
537 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
538 return;
539
540 /* sisusb->lock is down */
541
542 cols = sisusb->sisusb_num_columns;
543
544 /* Don't need to move data outselves, because
545 * vt does this BEFORE calling us.
546 * This is only used by vt's insert/deletechar.
547 */
548#if 0
549 if (sx == 0 && dx == 0 && width >= c->vc_cols && width <= cols) {
550
551 sisusbcon_memmovew(SISUSB_VADDR(0, dy), SISUSB_VADDR(0, sy),
552 height * width * 2);
553
554 } else if (dy < sy || (dy == sy && dx < sx)) {
555
556 src = SISUSB_VADDR(sx, sy);
557 dest = SISUSB_VADDR(dx, dy);
558
559 for (i = height; i > 0; i--) {
560 sisusbcon_memmovew(dest, src, width * 2);
561 src += cols;
562 dest += cols;
563 }
564
565 } else {
566
567 src = SISUSB_VADDR(sx, sy + height - 1);
568 dest = SISUSB_VADDR(dx, dy + height - 1);
569
570 for (i = height; i > 0; i--) {
571 sisusbcon_memmovew(dest, src, width * 2);
572 src -= cols;
573 dest -= cols;
574 }
575
576 }
577#endif
578
579 if (sisusb_is_inactive(c, sisusb)) {
580 up(&sisusb->lock);
581 return;
582 }
583
584 length = ((height * cols) - dx - (cols - width - dx)) * 2;
585
586
587 sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(dx, dy),
588 (u32)SISUSB_HADDR(dx, dy), length, &written);
589
590 up(&sisusb->lock);
591}
592
593/* interface routine */
594static int
595sisusbcon_switch(struct vc_data *c)
596{
597 struct sisusb_usb_data *sisusb;
598 ssize_t written;
599 int length;
600
601 /* Returnvalue 0 means we have fully restored screen,
602 * and vt doesn't need to call do_update_region().
603 * Returnvalue != 0 naturally means the opposite.
604 */
605
606 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
607 return 0;
608
609 /* sisusb->lock is down */
610
611 /* Don't write to screen if in gfx mode */
612 if (sisusb_is_inactive(c, sisusb)) {
613 up(&sisusb->lock);
614 return 0;
615 }
616
617 /* That really should not happen. It would mean we are
618 * being called while the vc is using its private buffer
619 * as origin.
620 */
621 if (c->vc_origin == (unsigned long)c->vc_screenbuf) {
622 up(&sisusb->lock);
623 printk(KERN_DEBUG "sisusb: ASSERT ORIGIN != SCREENBUF!\n");
624 return 0;
625 }
626
627 /* Check that we don't copy too much */
628 length = min((int)c->vc_screenbuf_size,
629 (int)(sisusb->scrbuf + sisusb->scrbuf_size - c->vc_origin));
630
631 /* Restore the screen contents */
632 sisusbcon_memcpyw((u16 *)c->vc_origin, (u16 *)c->vc_screenbuf,
633 length);
634
635 sisusb_copy_memory(sisusb, (unsigned char *)c->vc_origin,
636 (u32)SISUSB_HADDR(0, 0),
637 length, &written);
638
639 up(&sisusb->lock);
640
641 return 0;
642}
643
644/* interface routine */
645static void
646sisusbcon_save_screen(struct vc_data *c)
647{
648 struct sisusb_usb_data *sisusb;
649 int length;
650
651 /* Save the current screen contents to vc's private
652 * buffer.
653 */
654
655 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
656 return;
657
658 /* sisusb->lock is down */
659
660 if (sisusb_is_inactive(c, sisusb)) {
661 up(&sisusb->lock);
662 return;
663 }
664
665 /* Check that we don't copy too much */
666 length = min((int)c->vc_screenbuf_size,
667 (int)(sisusb->scrbuf + sisusb->scrbuf_size - c->vc_origin));
668
669 /* Save the screen contents to vc's private buffer */
670 sisusbcon_memcpyw((u16 *)c->vc_screenbuf, (u16 *)c->vc_origin,
671 length);
672
673 up(&sisusb->lock);
674}
675
676/* interface routine */
677static int
678sisusbcon_set_palette(struct vc_data *c, unsigned char *table)
679{
680 struct sisusb_usb_data *sisusb;
681 int i, j;
682
683 /* Return value not used by vt */
684
685 if (!CON_IS_VISIBLE(c))
686 return -EINVAL;
687
688 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
689 return -EINVAL;
690
691 /* sisusb->lock is down */
692
693 if (sisusb_is_inactive(c, sisusb)) {
694 up(&sisusb->lock);
695 return -EINVAL;
696 }
697
698 for (i = j = 0; i < 16; i++) {
699 if (sisusb_setreg(sisusb, SISCOLIDX, table[i]))
700 break;
701 if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))
702 break;
703 if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))
704 break;
705 if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))
706 break;
707 }
708
709 up(&sisusb->lock);
710
711 return 0;
712}
713
714/* interface routine */
715static int
716sisusbcon_blank(struct vc_data *c, int blank, int mode_switch)
717{
718 struct sisusb_usb_data *sisusb;
719 u8 sr1, cr17, pmreg, cr63;
720 ssize_t written;
721 int ret = 0;
722
723 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
724 return 0;
725
726 /* sisusb->lock is down */
727
728 if (mode_switch)
729 sisusb->is_gfx = blank ? 1 : 0;
730
731 if (sisusb_is_inactive(c, sisusb)) {
732 up(&sisusb->lock);
733 return 0;
734 }
735
736 switch (blank) {
737
738 case 1: /* Normal blanking: Clear screen */
739 case -1:
740 sisusbcon_memsetw((u16 *)c->vc_origin,
741 c->vc_video_erase_char,
742 c->vc_screenbuf_size);
743 sisusb_copy_memory(sisusb,
744 (unsigned char *)c->vc_origin,
745 (u32)(sisusb->vrambase +
746 (c->vc_origin - sisusb->scrbuf)),
747 c->vc_screenbuf_size, &written);
748 sisusb->con_blanked = 1;
749 ret = 1;
750 break;
751
752 default: /* VESA blanking */
753 switch (blank) {
754 case 0: /* Unblank */
755 sr1 = 0x00;
756 cr17 = 0x80;
757 pmreg = 0x00;
758 cr63 = 0x00;
759 ret = 1;
760 sisusb->con_blanked = 0;
761 break;
762 case VESA_VSYNC_SUSPEND + 1:
763 sr1 = 0x20;
764 cr17 = 0x80;
765 pmreg = 0x80;
766 cr63 = 0x40;
767 break;
768 case VESA_HSYNC_SUSPEND + 1:
769 sr1 = 0x20;
770 cr17 = 0x80;
771 pmreg = 0x40;
772 cr63 = 0x40;
773 break;
774 case VESA_POWERDOWN + 1:
775 sr1 = 0x20;
776 cr17 = 0x00;
777 pmreg = 0xc0;
778 cr63 = 0x40;
779 break;
780 default:
781 up(&sisusb->lock);
782 return -EINVAL;
783 }
784
785 sisusb_setidxregandor(sisusb, SISSR, 0x01, ~0x20, sr1);
786 sisusb_setidxregandor(sisusb, SISCR, 0x17, 0x7f, cr17);
787 sisusb_setidxregandor(sisusb, SISSR, 0x1f, 0x3f, pmreg);
788 sisusb_setidxregandor(sisusb, SISCR, 0x63, 0xbf, cr63);
789
790 }
791
792 up(&sisusb->lock);
793
794 return ret;
795}
796
797/* interface routine */
798static int
799sisusbcon_scrolldelta(struct vc_data *c, int lines)
800{
801 struct sisusb_usb_data *sisusb;
802 int margin = c->vc_size_row * 4;
803 int ul, we, p, st;
804
805 /* The return value does not seem to be used */
806
807 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
808 return 0;
809
810 /* sisusb->lock is down */
811
812 if (sisusb_is_inactive(c, sisusb)) {
813 up(&sisusb->lock);
814 return 0;
815 }
816
817 if (!lines) /* Turn scrollback off */
818 c->vc_visible_origin = c->vc_origin;
819 else {
820
821 if (sisusb->con_rolled_over >
822 (c->vc_scr_end - sisusb->scrbuf) + margin) {
823
824 ul = c->vc_scr_end - sisusb->scrbuf;
825 we = sisusb->con_rolled_over + c->vc_size_row;
826
827 } else {
828
829 ul = 0;
830 we = sisusb->scrbuf_size;
831
832 }
833
834 p = (c->vc_visible_origin - sisusb->scrbuf - ul + we) % we +
835 lines * c->vc_size_row;
836
837 st = (c->vc_origin - sisusb->scrbuf - ul + we) % we;
838
839 if (st < 2 * margin)
840 margin = 0;
841
842 if (p < margin)
843 p = 0;
844
845 if (p > st - margin)
846 p = st;
847
848 c->vc_visible_origin = sisusb->scrbuf + (p + ul) % we;
849 }
850
851 sisusbcon_set_start_address(sisusb, c);
852
853 up(&sisusb->lock);
854
855 return 1;
856}
857
858/* Interface routine */
859static void
860sisusbcon_cursor(struct vc_data *c, int mode)
861{
862 struct sisusb_usb_data *sisusb;
863 int from, to, baseline;
864
865 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
866 return;
867
868 /* sisusb->lock is down */
869
870 if (sisusb_is_inactive(c, sisusb)) {
871 up(&sisusb->lock);
872 return;
873 }
874
875 if (c->vc_origin != c->vc_visible_origin) {
876 c->vc_visible_origin = c->vc_origin;
877 sisusbcon_set_start_address(sisusb, c);
878 }
879
880 if (mode == CM_ERASE) {
881 sisusb_setidxregor(sisusb, SISCR, 0x0a, 0x20);
882 sisusb->sisusb_cursor_size_to = -1;
883 up(&sisusb->lock);
884 return;
885 }
886
887 sisusb_set_cursor(sisusb, (c->vc_pos - sisusb->scrbuf) / 2);
888
889 baseline = c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2);
890
891 switch (c->vc_cursor_type & 0x0f) {
892 case CUR_BLOCK: from = 1;
893 to = c->vc_font.height;
894 break;
895 case CUR_TWO_THIRDS: from = c->vc_font.height / 3;
896 to = baseline;
897 break;
898 case CUR_LOWER_HALF: from = c->vc_font.height / 2;
899 to = baseline;
900 break;
901 case CUR_LOWER_THIRD: from = (c->vc_font.height * 2) / 3;
902 to = baseline;
903 break;
904 case CUR_NONE: from = 31;
905 to = 30;
906 break;
907 default:
908 case CUR_UNDERLINE: from = baseline - 1;
909 to = baseline;
910 break;
911 }
912
913 if (sisusb->sisusb_cursor_size_from != from ||
914 sisusb->sisusb_cursor_size_to != to) {
915
916 sisusb_setidxreg(sisusb, SISCR, 0x0a, from);
917 sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0, to);
918
919 sisusb->sisusb_cursor_size_from = from;
920 sisusb->sisusb_cursor_size_to = to;
921 }
922
923 up(&sisusb->lock);
924}
925
926static int
927sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb,
928 int t, int b, int dir, int lines)
929{
930 int cols = sisusb->sisusb_num_columns;
931 int length = ((b - t) * cols) * 2;
932 u16 eattr = c->vc_video_erase_char;
933 ssize_t written;
934
935 /* sisusb->lock is down */
936
937 /* Scroll an area which does not match the
938 * visible screen's dimensions. This needs
939 * to be done separately, as it does not
940 * use hardware panning.
941 */
942
943 switch (dir) {
944
945 case SM_UP:
946 sisusbcon_memmovew(SISUSB_VADDR(0, t),
947 SISUSB_VADDR(0, t + lines),
948 (b - t - lines) * cols * 2);
949 sisusbcon_memsetw(SISUSB_VADDR(0, b - lines), eattr,
950 lines * cols * 2);
951 break;
952
953 case SM_DOWN:
954 sisusbcon_memmovew(SISUSB_VADDR(0, t + lines),
955 SISUSB_VADDR(0, t),
956 (b - t - lines) * cols * 2);
957 sisusbcon_memsetw(SISUSB_VADDR(0, t), eattr,
958 lines * cols * 2);
959 break;
960 }
961
962 sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(0, t),
963 (u32)SISUSB_HADDR(0, t), length, &written);
964
965 up(&sisusb->lock);
966
967 return 1;
968}
969
970/* Interface routine */
971static int
972sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
973{
974 struct sisusb_usb_data *sisusb;
975 u16 eattr = c->vc_video_erase_char;
976 ssize_t written;
977 int copyall = 0;
978 unsigned long oldorigin;
979 unsigned int delta = lines * c->vc_size_row;
980 u32 originoffset;
981
982 /* Returning != 0 means we have done the scrolling successfully.
983 * Returning 0 makes vt do the scrolling on its own.
984 * Note that con_scroll is only called if the console is
985 * visible. In that case, the origin should be our buffer,
986 * not the vt's private one.
987 */
988
989 if (!lines)
990 return 1;
991
992 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
993 return 0;
994
995 /* sisusb->lock is down */
996
997 if (sisusb_is_inactive(c, sisusb)) {
998 up(&sisusb->lock);
999 return 0;
1000 }
1001
1002 /* Special case */
1003 if (t || b != c->vc_rows)
1004 return sisusbcon_scroll_area(c, sisusb, t, b, dir, lines);
1005
1006 if (c->vc_origin != c->vc_visible_origin) {
1007 c->vc_visible_origin = c->vc_origin;
1008 sisusbcon_set_start_address(sisusb, c);
1009 }
1010
1011 /* limit amount to maximum realistic size */
1012 if (lines > c->vc_rows)
1013 lines = c->vc_rows;
1014
1015 oldorigin = c->vc_origin;
1016
1017 switch (dir) {
1018
1019 case SM_UP:
1020
1021 if (c->vc_scr_end + delta >=
1022 sisusb->scrbuf + sisusb->scrbuf_size) {
1023 sisusbcon_memcpyw((u16 *)sisusb->scrbuf,
1024 (u16 *)(oldorigin + delta),
1025 c->vc_screenbuf_size - delta);
1026 c->vc_origin = sisusb->scrbuf;
1027 sisusb->con_rolled_over = oldorigin - sisusb->scrbuf;
1028 copyall = 1;
1029 } else
1030 c->vc_origin += delta;
1031
1032 sisusbcon_memsetw(
1033 (u16 *)(c->vc_origin + c->vc_screenbuf_size - delta),
1034 eattr, delta);
1035
1036 break;
1037
1038 case SM_DOWN:
1039
1040 if (oldorigin - delta < sisusb->scrbuf) {
1041 sisusbcon_memmovew((u16 *)(sisusb->scrbuf +
1042 sisusb->scrbuf_size -
1043 c->vc_screenbuf_size +
1044 delta),
1045 (u16 *)oldorigin,
1046 c->vc_screenbuf_size - delta);
1047 c->vc_origin = sisusb->scrbuf +
1048 sisusb->scrbuf_size -
1049 c->vc_screenbuf_size;
1050 sisusb->con_rolled_over = 0;
1051 copyall = 1;
1052 } else
1053 c->vc_origin -= delta;
1054
1055 c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1056
1057 scr_memsetw((u16 *)(c->vc_origin), eattr, delta);
1058
1059 break;
1060 }
1061
1062 originoffset = (u32)(c->vc_origin - sisusb->scrbuf);
1063
1064 if (copyall)
1065 sisusb_copy_memory(sisusb,
1066 (char *)c->vc_origin,
1067 (u32)(sisusb->vrambase + originoffset),
1068 c->vc_screenbuf_size, &written);
1069 else if (dir == SM_UP)
1070 sisusb_copy_memory(sisusb,
1071 (char *)c->vc_origin + c->vc_screenbuf_size - delta,
1072 (u32)sisusb->vrambase + originoffset +
1073 c->vc_screenbuf_size - delta,
1074 delta, &written);
1075 else
1076 sisusb_copy_memory(sisusb,
1077 (char *)c->vc_origin,
1078 (u32)(sisusb->vrambase + originoffset),
1079 delta, &written);
1080
1081 c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1082 c->vc_visible_origin = c->vc_origin;
1083
1084 sisusbcon_set_start_address(sisusb, c);
1085
1086 c->vc_pos = c->vc_pos - oldorigin + c->vc_origin;
1087
1088 up(&sisusb->lock);
1089
1090 return 1;
1091}
1092
1093/* Interface routine */
1094static int
1095sisusbcon_set_origin(struct vc_data *c)
1096{
1097 struct sisusb_usb_data *sisusb;
1098
1099 /* Returning != 0 means we were successful.
1100 * Returning 0 will vt make to use its own
1101 * screenbuffer as the origin.
1102 */
1103
1104 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
1105 return 0;
1106
1107 /* sisusb->lock is down */
1108
1109 if (sisusb_is_inactive(c, sisusb) || sisusb->con_blanked) {
1110 up(&sisusb->lock);
1111 return 0;
1112 }
1113
1114 c->vc_origin = c->vc_visible_origin = sisusb->scrbuf;
1115
1116 sisusbcon_set_start_address(sisusb, c);
1117
1118 sisusb->con_rolled_over = 0;
1119
1120 up(&sisusb->lock);
1121
1122 return 1;
1123}
1124
1125/* Interface routine */
1126static int
1127sisusbcon_resize(struct vc_data *c, unsigned int newcols, unsigned int newrows)
1128{
1129 struct sisusb_usb_data *sisusb;
1130 int fh;
1131
1132 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
1133 return -ENODEV;
1134
1135 fh = sisusb->current_font_height;
1136
1137 up(&sisusb->lock);
1138
1139 /* We are quite unflexible as regards resizing. The vt code
1140 * handles sizes where the line length isn't equal the pitch
1141 * quite badly. As regards the rows, our panning tricks only
1142 * work well if the number of rows equals the visible number
1143 * of rows.
1144 */
1145
1146 if (newcols != 80 || c->vc_scan_lines / fh != newrows)
1147 return -EINVAL;
1148
1149 return 0;
1150}
1151
1152int
1153sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
1154 u8 *arg, int cmapsz, int ch512, int dorecalc,
1155 struct vc_data *c, int fh, int uplock)
1156{
1157 int font_select = 0x00, i, err = 0;
1158 u32 offset = 0;
1159 u8 dummy;
1160
1161 /* sisusb->lock is down */
1162
1163 /*
1164 * The default font is kept in slot 0.
1165 * A user font is loaded in slot 2 (256 ch)
1166 * or 2+3 (512 ch).
1167 */
1168
1169 if ((slot != 0 && slot != 2) || !fh) {
1170 if (uplock)
1171 up(&sisusb->lock);
1172 return -EINVAL;
1173 }
1174
1175 if (set)
1176 sisusb->font_slot = slot;
1177
1178 /* Default font is always 256 */
1179 if (slot == 0)
1180 ch512 = 0;
1181 else
1182 offset = 4 * cmapsz;
1183
1184 font_select = (slot == 0) ? 0x00 : (ch512 ? 0x0e : 0x0a);
1185
1186 err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x01); /* Reset */
1187 err |= sisusb_setidxreg(sisusb, SISSR, 0x02, 0x04); /* Write to plane 2 */
1188 err |= sisusb_setidxreg(sisusb, SISSR, 0x04, 0x07); /* Memory mode a0-bf */
1189 err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x03); /* Reset */
1190
1191 if (err)
1192 goto font_op_error;
1193
1194 err |= sisusb_setidxreg(sisusb, SISGR, 0x04, 0x03); /* Select plane read 2 */
1195 err |= sisusb_setidxreg(sisusb, SISGR, 0x05, 0x00); /* Disable odd/even */
1196 err |= sisusb_setidxreg(sisusb, SISGR, 0x06, 0x00); /* Address range a0-bf */
1197
1198 if (err)
1199 goto font_op_error;
1200
1201 if (arg) {
1202 if (set)
1203 for (i = 0; i < cmapsz; i++) {
1204 err |= sisusb_writeb(sisusb,
1205 sisusb->vrambase + offset + i,
1206 arg[i]);
1207 if (err)
1208 break;
1209 }
1210 else
1211 for (i = 0; i < cmapsz; i++) {
1212 err |= sisusb_readb(sisusb,
1213 sisusb->vrambase + offset + i,
1214 &arg[i]);
1215 if (err)
1216 break;
1217 }
1218
1219 /*
1220 * In 512-character mode, the character map is not contiguous if
1221 * we want to remain EGA compatible -- which we do
1222 */
1223
1224 if (ch512) {
1225 if (set)
1226 for (i = 0; i < cmapsz; i++) {
1227 err |= sisusb_writeb(sisusb,
1228 sisusb->vrambase + offset +
1229 (2 * cmapsz) + i,
1230 arg[cmapsz + i]);
1231 if (err)
1232 break;
1233 }
1234 else
1235 for (i = 0; i < cmapsz; i++) {
1236 err |= sisusb_readb(sisusb,
1237 sisusb->vrambase + offset +
1238 (2 * cmapsz) + i,
1239 &arg[cmapsz + i]);
1240 if (err)
1241 break;
1242 }
1243 }
1244 }
1245
1246 if (err)
1247 goto font_op_error;
1248
1249 err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x01); /* Reset */
1250 err |= sisusb_setidxreg(sisusb, SISSR, 0x02, 0x03); /* Write to planes 0+1 */
1251 err |= sisusb_setidxreg(sisusb, SISSR, 0x04, 0x03); /* Memory mode a0-bf */
1252 if (set)
1253 sisusb_setidxreg(sisusb, SISSR, 0x03, font_select);
1254 err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x03); /* Reset end */
1255
1256 if (err)
1257 goto font_op_error;
1258
1259 err |= sisusb_setidxreg(sisusb, SISGR, 0x04, 0x00); /* Select plane read 0 */
1260 err |= sisusb_setidxreg(sisusb, SISGR, 0x05, 0x10); /* Enable odd/even */
1261 err |= sisusb_setidxreg(sisusb, SISGR, 0x06, 0x06); /* Address range b8-bf */
1262
1263 if (err)
1264 goto font_op_error;
1265
1266 if ((set) && (ch512 != sisusb->current_font_512)) {
1267
1268 /* Font is shared among all our consoles.
1269 * And so is the hi_font_mask.
1270 */
1271 for (i = 0; i < MAX_NR_CONSOLES; i++) {
1272 struct vc_data *c = vc_cons[i].d;
1273 if (c && c->vc_sw == &sisusb_con)
1274 c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
1275 }
1276
1277 sisusb->current_font_512 = ch512;
1278
1279 /* color plane enable register:
1280 256-char: enable intensity bit
1281 512-char: disable intensity bit */
1282 sisusb_getreg(sisusb, SISINPSTAT, &dummy);
1283 sisusb_setreg(sisusb, SISAR, 0x12);
1284 sisusb_setreg(sisusb, SISAR, ch512 ? 0x07 : 0x0f);
1285
1286 sisusb_getreg(sisusb, SISINPSTAT, &dummy);
1287 sisusb_setreg(sisusb, SISAR, 0x20);
1288 sisusb_getreg(sisusb, SISINPSTAT, &dummy);
1289 }
1290
1291 if (dorecalc) {
1292
1293 /*
1294 * Adjust the screen to fit a font of a certain height
1295 */
1296
1297 unsigned char ovr, vde, fsr;
1298 int rows = 0, maxscan = 0;
1299
1300 if (c) {
1301
1302 /* Number of video rows */
1303 rows = c->vc_scan_lines / fh;
1304 /* Scan lines to actually display-1 */
1305 maxscan = rows * fh - 1;
1306
1307 /*printk(KERN_DEBUG "sisusb recalc rows %d maxscan %d fh %d sl %d\n",
1308 rows, maxscan, fh, c->vc_scan_lines);*/
1309
1310 sisusb_getidxreg(sisusb, SISCR, 0x07, &ovr);
1311 vde = maxscan & 0xff;
1312 ovr = (ovr & 0xbd) |
1313 ((maxscan & 0x100) >> 7) |
1314 ((maxscan & 0x200) >> 3);
1315 sisusb_setidxreg(sisusb, SISCR, 0x07, ovr);
1316 sisusb_setidxreg(sisusb, SISCR, 0x12, vde);
1317
1318 }
1319
1320 sisusb_getidxreg(sisusb, SISCR, 0x09, &fsr);
1321 fsr = (fsr & 0xe0) | (fh - 1);
1322 sisusb_setidxreg(sisusb, SISCR, 0x09, fsr);
1323 sisusb->current_font_height = fh;
1324
1325 sisusb->sisusb_cursor_size_from = -1;
1326 sisusb->sisusb_cursor_size_to = -1;
1327
1328 }
1329
1330 if (uplock)
1331 up(&sisusb->lock);
1332
1333 if (dorecalc && c) {
1334 int i, rows = c->vc_scan_lines / fh;
1335
1336 /* Now adjust our consoles' size */
1337
1338 for (i = 0; i < MAX_NR_CONSOLES; i++) {
1339 struct vc_data *vc = vc_cons[i].d;
1340
1341 if (vc && vc->vc_sw == &sisusb_con) {
1342 if (CON_IS_VISIBLE(vc)) {
1343 vc->vc_sw->con_cursor(vc, CM_DRAW);
1344 }
1345 vc->vc_font.height = fh;
1346 vc_resize(vc, 0, rows);
1347 }
1348 }
1349 }
1350
1351 return 0;
1352
1353font_op_error:
1354 if (uplock)
1355 up(&sisusb->lock);
1356
1357 return -EIO;
1358}
1359
1360/* Interface routine */
1361static int
1362sisusbcon_font_set(struct vc_data *c, struct console_font *font,
1363 unsigned flags)
1364{
1365 struct sisusb_usb_data *sisusb;
1366 unsigned charcount = font->charcount;
1367
1368 if (font->width != 8 || (charcount != 256 && charcount != 512))
1369 return -EINVAL;
1370
1371 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
1372 return -ENODEV;
1373
1374 /* sisusb->lock is down */
1375
1376 /* Save the user-provided font into a buffer. This
1377 * is used for restoring text mode after quitting
1378 * from X and for the con_getfont routine.
1379 */
1380 if (sisusb->font_backup) {
1381 if (sisusb->font_backup_size < charcount) {
1382 vfree(sisusb->font_backup);
1383 sisusb->font_backup = NULL;
1384 }
1385 }
1386
1387 if (!sisusb->font_backup)
1388 sisusb->font_backup = vmalloc(charcount * 32);
1389
1390 if (sisusb->font_backup) {
1391 memcpy(sisusb->font_backup, font->data, charcount * 32);
1392 sisusb->font_backup_size = charcount;
1393 sisusb->font_backup_height = font->height;
1394 sisusb->font_backup_512 = (charcount == 512) ? 1 : 0;
1395 }
1396
1397 /* do_font_op ups sisusb->lock */
1398
1399 return sisusbcon_do_font_op(sisusb, 1, 2, font->data,
1400 8192, (charcount == 512),
1401 (!(flags & KD_FONT_FLAG_DONT_RECALC)) ? 1 : 0,
1402 c, font->height, 1);
1403}
1404
1405/* Interface routine */
1406static int
1407sisusbcon_font_get(struct vc_data *c, struct console_font *font)
1408{
1409 struct sisusb_usb_data *sisusb;
1410
1411 if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
1412 return -ENODEV;
1413
1414 /* sisusb->lock is down */
1415
1416 font->width = 8;
1417 font->height = c->vc_font.height;
1418 font->charcount = 256;
1419
1420 if (!font->data) {
1421 up(&sisusb->lock);
1422 return 0;
1423 }
1424
1425 if (!sisusb->font_backup) {
1426 up(&sisusb->lock);
1427 return -ENODEV;
1428 }
1429
1430 /* Copy 256 chars only, like vgacon */
1431 memcpy(font->data, sisusb->font_backup, 256 * 32);
1432
1433 up(&sisusb->lock);
1434
1435 return 0;
1436}
1437
1438/*
1439 * The console `switch' structure for the sisusb console
1440 */
1441
1442static const struct consw sisusb_con = {
1443 .owner = THIS_MODULE,
1444 .con_startup = sisusbcon_startup,
1445 .con_init = sisusbcon_init,
1446 .con_deinit = sisusbcon_deinit,
1447 .con_clear = sisusbcon_clear,
1448 .con_putc = sisusbcon_putc,
1449 .con_putcs = sisusbcon_putcs,
1450 .con_cursor = sisusbcon_cursor,
1451 .con_scroll = sisusbcon_scroll,
1452 .con_bmove = sisusbcon_bmove,
1453 .con_switch = sisusbcon_switch,
1454 .con_blank = sisusbcon_blank,
1455 .con_font_set = sisusbcon_font_set,
1456 .con_font_get = sisusbcon_font_get,
1457 .con_set_palette = sisusbcon_set_palette,
1458 .con_scrolldelta = sisusbcon_scrolldelta,
1459 .con_build_attr = sisusbcon_build_attr,
1460 .con_invert_region = sisusbcon_invert_region,
1461 .con_set_origin = sisusbcon_set_origin,
1462 .con_save_screen = sisusbcon_save_screen,
1463 .con_resize = sisusbcon_resize,
1464};
1465
1466/* Our very own dummy console driver */
1467
1468static const char *sisusbdummycon_startup(void)
1469{
1470 return "SISUSBVGADUMMY";
1471}
1472
1473static void sisusbdummycon_init(struct vc_data *vc, int init)
1474{
1475 vc->vc_can_do_color = 1;
1476 if (init) {
1477 vc->vc_cols = 80;
1478 vc->vc_rows = 25;
1479 } else
1480 vc_resize(vc, 80, 25);
1481}
1482
1483static int sisusbdummycon_dummy(void)
1484{
1485 return 0;
1486}
1487
1488#define SISUSBCONDUMMY (void *)sisusbdummycon_dummy
1489
1490const struct consw sisusb_dummy_con = {
1491 .owner = THIS_MODULE,
1492 .con_startup = sisusbdummycon_startup,
1493 .con_init = sisusbdummycon_init,
1494 .con_deinit = SISUSBCONDUMMY,
1495 .con_clear = SISUSBCONDUMMY,
1496 .con_putc = SISUSBCONDUMMY,
1497 .con_putcs = SISUSBCONDUMMY,
1498 .con_cursor = SISUSBCONDUMMY,
1499 .con_scroll = SISUSBCONDUMMY,
1500 .con_bmove = SISUSBCONDUMMY,
1501 .con_switch = SISUSBCONDUMMY,
1502 .con_blank = SISUSBCONDUMMY,
1503 .con_font_set = SISUSBCONDUMMY,
1504 .con_font_get = SISUSBCONDUMMY,
1505 .con_font_default = SISUSBCONDUMMY,
1506 .con_font_copy = SISUSBCONDUMMY,
1507 .con_set_palette = SISUSBCONDUMMY,
1508 .con_scrolldelta = SISUSBCONDUMMY,
1509};
1510
1511int
1512sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
1513{
1514 int i, ret, minor = sisusb->minor;
1515
1516 down(&disconnect_sem);
1517
1518 down(&sisusb->lock);
1519
1520 /* Erm.. that should not happen */
1521 if (sisusb->haveconsole || !sisusb->SiS_Pr) {
1522 up(&sisusb->lock);
1523 up(&disconnect_sem);
1524 return 1;
1525 }
1526
1527 sisusb->con_first = first;
1528 sisusb->con_last = last;
1529
1530 if (first > last ||
1531 first > MAX_NR_CONSOLES ||
1532 last > MAX_NR_CONSOLES) {
1533 up(&sisusb->lock);
1534 up(&disconnect_sem);
1535 return 1;
1536 }
1537
1538 /* If gfxcore not initialized or no consoles given, quit graciously */
1539 if (!sisusb->gfxinit || first < 1 || last < 1) {
1540 up(&sisusb->lock);
1541 up(&disconnect_sem);
1542 return 0;
1543 }
1544
1545 sisusb->sisusb_cursor_loc = -1;
1546 sisusb->sisusb_cursor_size_from = -1;
1547 sisusb->sisusb_cursor_size_to = -1;
1548
1549 /* Set up text mode (and upload default font) */
1550 if (sisusb_reset_text_mode(sisusb, 1)) {
1551 up(&sisusb->lock);
1552 up(&disconnect_sem);
1553 printk(KERN_ERR
1554 "sisusbvga[%d]: Failed to set up text mode\n",
1555 minor);
1556 return 1;
1557 }
1558
1559 /* Initialize some gfx registers */
1560 sisusb_initialize(sisusb);
1561
1562 for (i = first - 1; i <= last - 1; i++) {
1563 /* Save sisusb for our interface routines */
1564 mysisusbs[i] = sisusb;
1565 }
1566
1567 /* Initial console setup */
1568 sisusb->sisusb_num_columns = 80;
1569
1570 /* Use a 32K buffer (matches b8000-bffff area) */
1571 sisusb->scrbuf_size = 32 * 1024;
1572
1573 /* Allocate screen buffer */
1574 if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) {
1575 up(&sisusb->lock);
1576 up(&disconnect_sem);
1577 printk(KERN_ERR
1578 "sisusbvga[%d]: Failed to allocate screen buffer\n",
1579 minor);
1580 return 1;
1581 }
1582
1583 up(&sisusb->lock);
1584 up(&disconnect_sem);
1585
1586 /* Now grab the desired console(s) */
1587 ret = take_over_console(&sisusb_con, first - 1, last - 1, 0);
1588
1589 if (!ret)
1590 sisusb->haveconsole = 1;
1591 else {
1592 for (i = first - 1; i <= last - 1; i++)
1593 mysisusbs[i] = NULL;
1594 }
1595
1596 return ret;
1597}
1598
1599void
1600sisusb_console_exit(struct sisusb_usb_data *sisusb)
1601{
1602 int i;
1603
1604 /* This is called if the device is disconnected
1605 * and while disconnect and lock semaphores
1606 * are up. This should be save because we
1607 * can't lose our sisusb any other way but by
1608 * disconnection (and hence, the disconnect
1609 * sema is for protecting all other access
1610 * functions from disconnection, not the
1611 * other way round).
1612 */
1613
1614 /* Now what do we do in case of disconnection:
1615 * One alternative would be to simply call
1616 * give_up_console(). Nah, not a good idea.
1617 * give_up_console() is obviously buggy as it
1618 * only discards the consw pointer from the
1619 * driver_map, but doesn't adapt vc->vc_sw
1620 * of the affected consoles. Hence, the next
1621 * call to any of the console functions will
1622 * eventually take a trip to oops county.
1623 * Also, give_up_console for some reason
1624 * doesn't decrement our module refcount.
1625 * Instead, we switch our consoles to a private
1626 * dummy console. This, of course, keeps our
1627 * refcount up as well, but it works perfectly.
1628 */
1629
1630 if (sisusb->haveconsole) {
1631 for (i = 0; i < MAX_NR_CONSOLES; i++)
1632 if (sisusb->havethisconsole[i])
1633 take_over_console(&sisusb_dummy_con, i, i, 0);
1634 /* At this point, con_deinit for all our
1635 * consoles is executed by take_over_console().
1636 */
1637 sisusb->haveconsole = 0;
1638 }
1639
1640 vfree((void *)sisusb->scrbuf);
1641 sisusb->scrbuf = 0;
1642
1643 vfree(sisusb->font_backup);
1644 sisusb->font_backup = NULL;
1645}
1646
1647void __init sisusb_init_concode(void)
1648{
1649 int i;
1650
1651 for (i = 0; i < MAX_NR_CONSOLES; i++)
1652 mysisusbs[i] = NULL;
1653}
1654
1655#endif /* INCL_CON */
1656
1657
1658
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.c b/drivers/usb/misc/sisusbvga/sisusb_init.c
new file mode 100644
index 000000000000..f28bc240f9b6
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_init.c
@@ -0,0 +1,1047 @@
1/*
2 * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
3 *
4 * Display mode initializing code
5 *
6 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
7 *
8 * If distributed as part of the Linux kernel, this code is licensed under the
9 * terms of the GPL v2.
10 *
11 * Otherwise, the following license terms apply:
12 *
13 * * Redistribution and use in source and binary forms, with or without
14 * * modification, are permitted provided that the following conditions
15 * * are met:
16 * * 1) Redistributions of source code must retain the above copyright
17 * * notice, this list of conditions and the following disclaimer.
18 * * 2) Redistributions in binary form must reproduce the above copyright
19 * * notice, this list of conditions and the following disclaimer in the
20 * * documentation and/or other materials provided with the distribution.
21 * * 3) The name of the author may not be used to endorse or promote products
22 * * derived from this software without specific prior written permission.
23 * *
24 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 * Author: Thomas Winischhofer <thomas@winischhofer.net>
36 *
37 */
38
39#include <linux/config.h>
40#include <linux/version.h>
41#include <linux/module.h>
42#include <linux/kernel.h>
43#include <linux/errno.h>
44#include <linux/poll.h>
45#include <linux/init.h>
46#include <linux/slab.h>
47#include <linux/spinlock.h>
48#include <linux/kref.h>
49
50#include "sisusb.h"
51
52#ifdef INCL_SISUSB_CON
53
54#include "sisusb_init.h"
55
56/*********************************************/
57/* POINTER INITIALIZATION */
58/*********************************************/
59
60static void
61SiSUSB_InitPtr(struct SiS_Private *SiS_Pr)
62{
63 SiS_Pr->SiS_ModeResInfo = SiSUSB_ModeResInfo;
64 SiS_Pr->SiS_StandTable = SiSUSB_StandTable;
65
66 SiS_Pr->SiS_SModeIDTable = SiSUSB_SModeIDTable;
67 SiS_Pr->SiS_EModeIDTable = SiSUSB_EModeIDTable;
68 SiS_Pr->SiS_RefIndex = SiSUSB_RefIndex;
69 SiS_Pr->SiS_CRT1Table = SiSUSB_CRT1Table;
70
71 SiS_Pr->SiS_VCLKData = SiSUSB_VCLKData;
72}
73
74/*********************************************/
75/* HELPER: Get ModeID */
76/*********************************************/
77
78unsigned short
79SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth)
80{
81 unsigned short ModeIndex = 0;
82
83 switch (HDisplay)
84 {
85 case 320:
86 if (VDisplay == 200)
87 ModeIndex = ModeIndex_320x200[Depth];
88 else if (VDisplay == 240)
89 ModeIndex = ModeIndex_320x240[Depth];
90 break;
91 case 400:
92 if (VDisplay == 300)
93 ModeIndex = ModeIndex_400x300[Depth];
94 break;
95 case 512:
96 if (VDisplay == 384)
97 ModeIndex = ModeIndex_512x384[Depth];
98 break;
99 case 640:
100 if (VDisplay == 480)
101 ModeIndex = ModeIndex_640x480[Depth];
102 else if (VDisplay == 400)
103 ModeIndex = ModeIndex_640x400[Depth];
104 break;
105 case 720:
106 if (VDisplay == 480)
107 ModeIndex = ModeIndex_720x480[Depth];
108 else if (VDisplay == 576)
109 ModeIndex = ModeIndex_720x576[Depth];
110 break;
111 case 768:
112 if (VDisplay == 576)
113 ModeIndex = ModeIndex_768x576[Depth];
114 break;
115 case 800:
116 if (VDisplay == 600)
117 ModeIndex = ModeIndex_800x600[Depth];
118 else if (VDisplay == 480)
119 ModeIndex = ModeIndex_800x480[Depth];
120 break;
121 case 848:
122 if (VDisplay == 480)
123 ModeIndex = ModeIndex_848x480[Depth];
124 break;
125 case 856:
126 if (VDisplay == 480)
127 ModeIndex = ModeIndex_856x480[Depth];
128 break;
129 case 960:
130 if (VDisplay == 540)
131 ModeIndex = ModeIndex_960x540[Depth];
132 else if (VDisplay == 600)
133 ModeIndex = ModeIndex_960x600[Depth];
134 break;
135 case 1024:
136 if (VDisplay == 576)
137 ModeIndex = ModeIndex_1024x576[Depth];
138 else if (VDisplay == 768)
139 ModeIndex = ModeIndex_1024x768[Depth];
140 break;
141 case 1152:
142 if (VDisplay == 864)
143 ModeIndex = ModeIndex_1152x864[Depth];
144 break;
145 case 1280:
146 switch (VDisplay) {
147 case 720:
148 ModeIndex = ModeIndex_1280x720[Depth];
149 break;
150 case 768:
151 ModeIndex = ModeIndex_1280x768[Depth];
152 break;
153 case 1024:
154 ModeIndex = ModeIndex_1280x1024[Depth];
155 break;
156 }
157 }
158
159 return ModeIndex;
160}
161
162/*********************************************/
163/* HELPER: SetReg, GetReg */
164/*********************************************/
165
166static void
167SiS_SetReg(struct SiS_Private *SiS_Pr, unsigned long port,
168 unsigned short index, unsigned short data)
169{
170 sisusb_setidxreg(SiS_Pr->sisusb, port, index, data);
171}
172
173static void
174SiS_SetRegByte(struct SiS_Private *SiS_Pr, unsigned long port,
175 unsigned short data)
176{
177 sisusb_setreg(SiS_Pr->sisusb, port, data);
178}
179
180static unsigned char
181SiS_GetReg(struct SiS_Private *SiS_Pr, unsigned long port,
182 unsigned short index)
183{
184 u8 data;
185
186 sisusb_getidxreg(SiS_Pr->sisusb, port, index, &data);
187
188 return data;
189}
190
191static unsigned char
192SiS_GetRegByte(struct SiS_Private *SiS_Pr, unsigned long port)
193{
194 u8 data;
195
196 sisusb_getreg(SiS_Pr->sisusb, port, &data);
197
198 return data;
199}
200
201static void
202SiS_SetRegANDOR(struct SiS_Private *SiS_Pr, unsigned long port,
203 unsigned short index, unsigned short DataAND,
204 unsigned short DataOR)
205{
206 sisusb_setidxregandor(SiS_Pr->sisusb, port, index, DataAND, DataOR);
207}
208
209static void
210SiS_SetRegAND(struct SiS_Private *SiS_Pr, unsigned long port,
211 unsigned short index, unsigned short DataAND)
212{
213 sisusb_setidxregand(SiS_Pr->sisusb, port, index, DataAND);
214}
215
216static void
217SiS_SetRegOR(struct SiS_Private *SiS_Pr,unsigned long port,
218 unsigned short index, unsigned short DataOR)
219{
220 sisusb_setidxregor(SiS_Pr->sisusb, port, index, DataOR);
221}
222
223/*********************************************/
224/* HELPER: DisplayOn, DisplayOff */
225/*********************************************/
226
227static void
228SiS_DisplayOn(struct SiS_Private *SiS_Pr)
229{
230 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0xDF);
231}
232
233/*********************************************/
234/* HELPER: Init Port Addresses */
235/*********************************************/
236
237void
238SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr)
239{
240 SiS_Pr->SiS_P3c4 = BaseAddr + 0x14;
241 SiS_Pr->SiS_P3d4 = BaseAddr + 0x24;
242 SiS_Pr->SiS_P3c0 = BaseAddr + 0x10;
243 SiS_Pr->SiS_P3ce = BaseAddr + 0x1e;
244 SiS_Pr->SiS_P3c2 = BaseAddr + 0x12;
245 SiS_Pr->SiS_P3ca = BaseAddr + 0x1a;
246 SiS_Pr->SiS_P3c6 = BaseAddr + 0x16;
247 SiS_Pr->SiS_P3c7 = BaseAddr + 0x17;
248 SiS_Pr->SiS_P3c8 = BaseAddr + 0x18;
249 SiS_Pr->SiS_P3c9 = BaseAddr + 0x19;
250 SiS_Pr->SiS_P3cb = BaseAddr + 0x1b;
251 SiS_Pr->SiS_P3cc = BaseAddr + 0x1c;
252 SiS_Pr->SiS_P3cd = BaseAddr + 0x1d;
253 SiS_Pr->SiS_P3da = BaseAddr + 0x2a;
254 SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;
255}
256
257/*********************************************/
258/* HELPER: GetSysFlags */
259/*********************************************/
260
261static void
262SiS_GetSysFlags(struct SiS_Private *SiS_Pr)
263{
264 SiS_Pr->SiS_MyCR63 = 0x63;
265}
266
267/*********************************************/
268/* HELPER: Init PCI & Engines */
269/*********************************************/
270
271static void
272SiSInitPCIetc(struct SiS_Private *SiS_Pr)
273{
274 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x20, 0xa1);
275 /* - Enable 2D (0x40)
276 * - Enable 3D (0x02)
277 * - Enable 3D vertex command fetch (0x10)
278 * - Enable 3D command parser (0x08)
279 * - Enable 3D G/L transformation engine (0x80)
280 */
281 SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1E, 0xDA);
282}
283
284/*********************************************/
285/* HELPER: SET SEGMENT REGISTERS */
286/*********************************************/
287
288static void
289SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value)
290{
291 unsigned short temp;
292
293 value &= 0x00ff;
294 temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0xf0;
295 temp |= (value >> 4);
296 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp);
297 temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0xf0;
298 temp |= (value & 0x0f);
299 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp);
300}
301
302static void
303SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value)
304{
305 unsigned short temp;
306
307 value &= 0x00ff;
308 temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0x0f;
309 temp |= (value & 0xf0);
310 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp);
311 temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0x0f;
312 temp |= (value << 4);
313 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp);
314}
315
316static void
317SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value)
318{
319 SiS_SetSegRegLower(SiS_Pr, value);
320 SiS_SetSegRegUpper(SiS_Pr, value);
321}
322
323static void
324SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr)
325{
326 SiS_SetSegmentReg(SiS_Pr, 0);
327}
328
329static void
330SiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value)
331{
332 unsigned short temp = value >> 8;
333
334 temp &= 0x07;
335 temp |= (temp << 4);
336 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1d, temp);
337 SiS_SetSegmentReg(SiS_Pr, value);
338}
339
340static void
341SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr)
342{
343 SiS_SetSegmentRegOver(SiS_Pr, 0);
344}
345
346static void
347SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr)
348{
349 SiS_ResetSegmentReg(SiS_Pr);
350 SiS_ResetSegmentRegOver(SiS_Pr);
351}
352
353/*********************************************/
354/* HELPER: SearchModeID */
355/*********************************************/
356
357static int
358SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
359 unsigned short *ModeIdIndex)
360{
361 if ((*ModeNo) <= 0x13) {
362
363 if ((*ModeNo) != 0x03)
364 return 0;
365
366 (*ModeIdIndex) = 0;
367
368 } else {
369
370 for(*ModeIdIndex = 0; ;(*ModeIdIndex)++) {
371
372 if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == (*ModeNo))
373 break;
374
375 if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF)
376 return 0;
377 }
378
379 }
380
381 return 1;
382}
383
384/*********************************************/
385/* HELPER: ENABLE CRT1 */
386/*********************************************/
387
388static void
389SiS_HandleCRT1(struct SiS_Private *SiS_Pr)
390{
391 /* Enable CRT1 gating */
392 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, SiS_Pr->SiS_MyCR63, 0xbf);
393}
394
395/*********************************************/
396/* HELPER: GetColorDepth */
397/*********************************************/
398
399static unsigned short
400SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
401 unsigned short ModeIdIndex)
402{
403 static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8};
404 unsigned short modeflag;
405 short index;
406
407 if (ModeNo <= 0x13) {
408 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
409 } else {
410 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
411 }
412
413 index = (modeflag & ModeTypeMask) - ModeEGA;
414 if (index < 0) index = 0;
415 return ColorDepth[index];
416}
417
418/*********************************************/
419/* HELPER: GetOffset */
420/*********************************************/
421
422static unsigned short
423SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
424 unsigned short ModeIdIndex, unsigned short rrti)
425{
426 unsigned short xres, temp, colordepth, infoflag;
427
428 infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
429 xres = SiS_Pr->SiS_RefIndex[rrti].XRes;
430
431 colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex);
432
433 temp = xres / 16;
434
435 if (infoflag & InterlaceMode)
436 temp <<= 1;
437
438 temp *= colordepth;
439
440 if (xres % 16)
441 temp += (colordepth >> 1);
442
443 return temp;
444}
445
446/*********************************************/
447/* SEQ */
448/*********************************************/
449
450static void
451SiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
452{
453 unsigned char SRdata;
454 int i;
455
456 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x00, 0x03);
457
458 SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20;
459 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, SRdata);
460
461 for(i = 2; i <= 4; i++) {
462 SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i-1];
463 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, SRdata);
464 }
465}
466
467/*********************************************/
468/* MISC */
469/*********************************************/
470
471static void
472SiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
473{
474 unsigned char Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC;
475
476 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, Miscdata);
477}
478
479/*********************************************/
480/* CRTC */
481/*********************************************/
482
483static void
484SiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
485{
486 unsigned char CRTCdata;
487 unsigned short i;
488
489 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, 0x11, 0x7f);
490
491 for(i = 0; i <= 0x18; i++) {
492 CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
493 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, i, CRTCdata);
494 }
495}
496
497/*********************************************/
498/* ATT */
499/*********************************************/
500
501static void
502SiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
503{
504 unsigned char ARdata;
505 unsigned short i;
506
507 for(i = 0; i <= 0x13; i++) {
508 ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i];
509 SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
510 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, i);
511 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, ARdata);
512 }
513 SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
514 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x14);
515 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x00);
516
517 SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
518 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x20);
519 SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
520}
521
522/*********************************************/
523/* GRC */
524/*********************************************/
525
526static void
527SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
528{
529 unsigned char GRdata;
530 unsigned short i;
531
532 for(i = 0; i <= 0x08; i++) {
533 GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i];
534 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3ce, i, GRdata);
535 }
536
537 if (SiS_Pr->SiS_ModeType > ModeVGA) {
538 /* 256 color disable */
539 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3ce, 0x05, 0xBF);
540 }
541}
542
543/*********************************************/
544/* CLEAR EXTENDED REGISTERS */
545/*********************************************/
546
547static void
548SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
549{
550 int i;
551
552 for(i = 0x0A; i <= 0x0E; i++) {
553 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, 0x00);
554 }
555
556 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x37, 0xFE);
557}
558
559/*********************************************/
560/* Get rate index */
561/*********************************************/
562
563static unsigned short
564SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
565 unsigned short ModeIdIndex)
566{
567 unsigned short rrti, i, index, temp;
568
569 if (ModeNo <= 0x13)
570 return 0xFFFF;
571
572 index = SiS_GetReg(SiS_Pr,SiS_Pr->SiS_P3d4, 0x33) & 0x0F;
573 if (index > 0) index--;
574
575 rrti = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
576 ModeNo = SiS_Pr->SiS_RefIndex[rrti].ModeID;
577
578 i = 0;
579 do {
580 if (SiS_Pr->SiS_RefIndex[rrti + i].ModeID != ModeNo)
581 break;
582
583 temp = SiS_Pr->SiS_RefIndex[rrti + i].Ext_InfoFlag & ModeTypeMask;
584 if (temp < SiS_Pr->SiS_ModeType)
585 break;
586
587 i++;
588 index--;
589 } while(index != 0xFFFF);
590
591 i--;
592
593 return (rrti + i);
594}
595
596/*********************************************/
597/* SYNC */
598/*********************************************/
599
600static void
601SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short rrti)
602{
603 unsigned short sync = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag >> 8;
604 sync &= 0xC0;
605 sync |= 0x2f;
606 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, sync);
607}
608
609/*********************************************/
610/* CRTC/2 */
611/*********************************************/
612
613static void
614SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
615 unsigned short ModeIdIndex, unsigned short rrti)
616{
617 unsigned char index;
618 unsigned short temp, i, j, modeflag;
619
620 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4,0x11,0x7f);
621
622 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
623
624 index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRT1CRTC;
625
626 for(i = 0,j = 0; i <= 7; i++, j++) {
627 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
628 SiS_Pr->SiS_CRT1Table[index].CR[i]);
629 }
630 for(j = 0x10; i <= 10; i++, j++) {
631 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
632 SiS_Pr->SiS_CRT1Table[index].CR[i]);
633 }
634 for(j = 0x15; i <= 12; i++, j++) {
635 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
636 SiS_Pr->SiS_CRT1Table[index].CR[i]);
637 }
638 for(j = 0x0A; i <= 15; i++, j++) {
639 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, j,
640 SiS_Pr->SiS_CRT1Table[index].CR[i]);
641 }
642
643 temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0;
644 SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4, 0x0E, temp);
645
646 temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5;
647 if (modeflag & DoubleScanMode) temp |= 0x80;
648 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x09, 0x5F, temp);
649
650 if (SiS_Pr->SiS_ModeType > ModeVGA)
651 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x14, 0x4F);
652}
653
654/*********************************************/
655/* OFFSET & PITCH */
656/*********************************************/
657/* (partly overruled by SetPitch() in XF86) */
658/*********************************************/
659
660static void
661SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
662 unsigned short ModeIdIndex, unsigned short rrti)
663{
664 unsigned short du = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, rrti);
665 unsigned short infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
666 unsigned short temp;
667
668 temp = (du >> 8) & 0x0f;
669 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0E, 0xF0, temp);
670
671 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x13, (du & 0xFF));
672
673 if (infoflag & InterlaceMode) du >>= 1;
674
675 du <<= 5;
676 temp = (du >> 8) & 0xff;
677 if (du & 0xff) temp++;
678 temp++;
679 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x10, temp);
680}
681
682/*********************************************/
683/* VCLK */
684/*********************************************/
685
686static void
687SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
688 unsigned short rrti)
689{
690 unsigned short index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK;
691 unsigned short clka = SiS_Pr->SiS_VCLKData[index].SR2B;
692 unsigned short clkb = SiS_Pr->SiS_VCLKData[index].SR2C;
693
694 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4,0x31,0xCF);
695
696 SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2B,clka);
697 SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2C,clkb);
698 SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2D,0x01);
699}
700
701/*********************************************/
702/* FIFO */
703/*********************************************/
704
705static void
706SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
707 unsigned short mi)
708{
709 unsigned short modeflag = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag;
710
711 /* disable auto-threshold */
712 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x3D, 0xFE);
713
714 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x08, 0xAE);
715 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x09, 0xF0);
716
717 if (ModeNo <= 0x13)
718 return;
719
720 if ((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
721 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x08, 0x34);
722 SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x3D, 0x01);
723 }
724}
725
726/*********************************************/
727/* MODE REGISTERS */
728/*********************************************/
729
730static void
731SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
732 unsigned short rrti)
733{
734 unsigned short data = 0, VCLK = 0, index = 0;
735
736 if (ModeNo > 0x13) {
737 index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK;
738 VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
739 }
740
741 if (VCLK >= 166) data |= 0x0c;
742 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x32, 0xf3, data);
743
744 if (VCLK >= 166)
745 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1f, 0xe7);
746
747 /* DAC speed */
748 data = 0x03;
749 if (VCLK >= 260)
750 data = 0x00;
751 else if (VCLK >= 160)
752 data = 0x01;
753 else if (VCLK >= 135)
754 data = 0x02;
755
756 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x07, 0xF8, data);
757}
758
759static void
760SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
761 unsigned short ModeIdIndex, unsigned short rrti)
762{
763 unsigned short data, infoflag = 0, modeflag;
764
765 if (ModeNo <= 0x13)
766 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
767 else {
768 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
769 infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
770 }
771
772 /* Disable DPMS */
773 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1F, 0x3F);
774
775 data = 0;
776 if (ModeNo > 0x13) {
777 if (SiS_Pr->SiS_ModeType > ModeEGA) {
778 data |= 0x02;
779 data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
780 }
781 if (infoflag & InterlaceMode) data |= 0x20;
782 }
783 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x06, 0xC0, data);
784
785 data = 0;
786 if (infoflag & InterlaceMode) {
787 /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */
788 unsigned short hrs = (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x04) |
789 ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0xc0) << 2)) - 3;
790 unsigned short hto = (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x00) |
791 ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0x03) << 8)) + 5;
792 data = hrs - (hto >> 1) + 3;
793 }
794 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x19, (data & 0xFF));
795 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x1a, 0xFC, (data >> 8));
796
797 if (modeflag & HalfDCLK)
798 SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0x08);
799
800 data = 0;
801 if (modeflag & LineCompareOff)
802 data = 0x08;
803 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0F, 0xB7, data);
804
805 if ((SiS_Pr->SiS_ModeType == ModeEGA) && (ModeNo > 0x13))
806 SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0F, 0x40);
807
808 SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x31, 0xfb);
809
810 data = 0x60;
811 if (SiS_Pr->SiS_ModeType != ModeText) {
812 data ^= 0x60;
813 if (SiS_Pr->SiS_ModeType != ModeEGA)
814 data ^= 0xA0;
815 }
816 SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x21, 0x1F, data);
817
818 SiS_SetVCLKState(SiS_Pr, ModeNo, rrti);
819
820 if (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x31) & 0x40)
821 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x52, 0x2c);
822 else
823 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x52, 0x6c);
824}
825
826/*********************************************/
827/* LOAD DAC */
828/*********************************************/
829
830static void
831SiS_WriteDAC(struct SiS_Private *SiS_Pr, unsigned long DACData,
832 unsigned short shiftflag, unsigned short dl, unsigned short ah,
833 unsigned short al, unsigned short dh)
834{
835 unsigned short d1, d2, d3;
836
837 switch (dl) {
838 case 0:
839 d1 = dh; d2 = ah; d3 = al;
840 break;
841 case 1:
842 d1 = ah; d2 = al; d3 = dh;
843 break;
844 default:
845 d1 = al; d2 = dh; d3 = ah;
846 }
847 SiS_SetRegByte(SiS_Pr, DACData, (d1 << shiftflag));
848 SiS_SetRegByte(SiS_Pr, DACData, (d2 << shiftflag));
849 SiS_SetRegByte(SiS_Pr, DACData, (d3 << shiftflag));
850}
851
852static void
853SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short mi)
854{
855 unsigned short data, data2, time, i, j, k, m, n, o;
856 unsigned short si, di, bx, sf;
857 unsigned long DACAddr, DACData;
858 const unsigned char *table = NULL;
859
860 if (ModeNo < 0x13)
861 data = SiS_Pr->SiS_SModeIDTable[mi].St_ModeFlag;
862 else
863 data = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag;
864
865 data &= DACInfoFlag;
866
867 j = time = 64;
868 if (data == 0x00)
869 table = SiS_MDA_DAC;
870 else if (data == 0x08)
871 table = SiS_CGA_DAC;
872 else if (data == 0x10)
873 table = SiS_EGA_DAC;
874 else {
875 j = 16;
876 time = 256;
877 table = SiS_VGA_DAC;
878 }
879
880 DACAddr = SiS_Pr->SiS_P3c8;
881 DACData = SiS_Pr->SiS_P3c9;
882 sf = 0;
883 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c6, 0xFF);
884
885 SiS_SetRegByte(SiS_Pr, DACAddr, 0x00);
886
887 for(i = 0; i < j; i++) {
888 data = table[i];
889 for(k = 0; k < 3; k++) {
890 data2 = 0;
891 if (data & 0x01) data2 += 0x2A;
892 if (data & 0x02) data2 += 0x15;
893 SiS_SetRegByte(SiS_Pr, DACData, (data2 << sf));
894 data >>= 2;
895 }
896 }
897
898 if (time == 256) {
899 for(i = 16; i < 32; i++) {
900 data = table[i] << sf;
901 for(k = 0; k < 3; k++)
902 SiS_SetRegByte(SiS_Pr, DACData, data);
903 }
904 si = 32;
905 for(m = 0; m < 9; m++) {
906 di = si;
907 bx = si + 4;
908 for(n = 0; n < 3; n++) {
909 for(o = 0; o < 5; o++) {
910 SiS_WriteDAC(SiS_Pr, DACData, sf, n,
911 table[di], table[bx], table[si]);
912 si++;
913 }
914 si -= 2;
915 for(o = 0; o < 3; o++) {
916 SiS_WriteDAC(SiS_Pr, DACData, sf, n,
917 table[di], table[si], table[bx]);
918 si--;
919 }
920 }
921 si += 5;
922 }
923 }
924}
925
926/*********************************************/
927/* SET CRT1 REGISTER GROUP */
928/*********************************************/
929
930static void
931SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
932 unsigned short ModeIdIndex)
933{
934 unsigned short StandTableIndex, rrti;
935
936 SiS_Pr->SiS_CRT1Mode = ModeNo;
937
938 if (ModeNo <= 0x13)
939 StandTableIndex = 0;
940 else
941 StandTableIndex = 1;
942
943 SiS_ResetSegmentRegisters(SiS_Pr);
944 SiS_SetSeqRegs(SiS_Pr, StandTableIndex);
945 SiS_SetMiscRegs(SiS_Pr, StandTableIndex);
946 SiS_SetCRTCRegs(SiS_Pr, StandTableIndex);
947 SiS_SetATTRegs(SiS_Pr, StandTableIndex);
948 SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
949 SiS_ClearExt1Regs(SiS_Pr, ModeNo);
950
951 rrti = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
952
953 if (rrti != 0xFFFF) {
954 SiS_SetCRT1Sync(SiS_Pr, rrti);
955 SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, rrti);
956 SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, rrti);
957 SiS_SetCRT1VCLK(SiS_Pr, ModeNo, rrti);
958 }
959
960 SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex);
961
962 SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, rrti);
963
964 SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
965
966 SiS_DisplayOn(SiS_Pr);
967}
968
969/*********************************************/
970/* SiSSetMode() */
971/*********************************************/
972
973int
974SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
975{
976 unsigned short ModeIdIndex;
977 unsigned long BaseAddr = SiS_Pr->IOAddress;
978
979 SiSUSB_InitPtr(SiS_Pr);
980 SiSUSBRegInit(SiS_Pr, BaseAddr);
981 SiS_GetSysFlags(SiS_Pr);
982
983 if (!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex)))
984 return 0;
985
986 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x05, 0x86);
987
988 SiSInitPCIetc(SiS_Pr);
989
990 ModeNo &= 0x7f;
991
992 SiS_Pr->SiS_ModeType =
993 SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag & ModeTypeMask;
994
995 SiS_Pr->SiS_SetFlag = LowModeTests;
996
997 /* Set mode on CRT1 */
998 SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
999
1000 SiS_HandleCRT1(SiS_Pr);
1001
1002 SiS_DisplayOn(SiS_Pr);
1003 SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c6, 0xFF);
1004
1005 /* Store mode number */
1006 SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x34, ModeNo);
1007
1008 return 1;
1009}
1010
1011int
1012SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo)
1013{
1014 unsigned short ModeNo = 0;
1015 int i;
1016
1017 SiSUSB_InitPtr(SiS_Pr);
1018
1019 if (VModeNo == 0x03) {
1020
1021 ModeNo = 0x03;
1022
1023 } else {
1024
1025 i = 0;
1026 do {
1027
1028 if (SiS_Pr->SiS_EModeIDTable[i].Ext_VESAID == VModeNo) {
1029 ModeNo = SiS_Pr->SiS_EModeIDTable[i].Ext_ModeID;
1030 break;
1031 }
1032
1033 } while (SiS_Pr->SiS_EModeIDTable[i++].Ext_ModeID != 0xff);
1034
1035 }
1036
1037 if (!ModeNo)
1038 return 0;
1039
1040 return SiSUSBSetMode(SiS_Pr, ModeNo);
1041}
1042
1043#endif /* INCL_SISUSB_CON */
1044
1045
1046
1047
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.h b/drivers/usb/misc/sisusbvga/sisusb_init.h
new file mode 100644
index 000000000000..5b11577835c8
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_init.h
@@ -0,0 +1,830 @@
1/* $XFree86$ */
2/* $XdotOrg$ */
3/*
4 * Data and prototypes for init.c
5 *
6 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
7 *
8 * If distributed as part of the Linux kernel, the following license terms
9 * apply:
10 *
11 * * This program is free software; you can redistribute it and/or modify
12 * * it under the terms of the GNU General Public License as published by
13 * * the Free Software Foundation; either version 2 of the named License,
14 * * or any later version.
15 * *
16 * * This program is distributed in the hope that it will be useful,
17 * * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * * GNU General Public License for more details.
20 * *
21 * * You should have received a copy of the GNU General Public License
22 * * along with this program; if not, write to the Free Software
23 * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
24 *
25 * Otherwise, the following license terms apply:
26 *
27 * * Redistribution and use in source and binary forms, with or without
28 * * modification, are permitted provided that the following conditions
29 * * are met:
30 * * 1) Redistributions of source code must retain the above copyright
31 * * notice, this list of conditions and the following disclaimer.
32 * * 2) Redistributions in binary form must reproduce the above copyright
33 * * notice, this list of conditions and the following disclaimer in the
34 * * documentation and/or other materials provided with the distribution.
35 * * 3) The name of the author may not be used to endorse or promote products
36 * * derived from this software without specific prior written permission.
37 * *
38 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
39 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
40 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
41 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
42 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
43 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
44 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
45 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
47 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48 *
49 * Author: Thomas Winischhofer <thomas@winischhofer.net>
50 *
51 */
52
53#ifndef _SISUSB_INIT_H_
54#define _SISUSB_INIT_H_
55
56/* SiS_ModeType */
57#define ModeText 0x00
58#define ModeCGA 0x01
59#define ModeEGA 0x02
60#define ModeVGA 0x03
61#define Mode15Bpp 0x04
62#define Mode16Bpp 0x05
63#define Mode24Bpp 0x06
64#define Mode32Bpp 0x07
65
66#define ModeTypeMask 0x07
67#define IsTextMode 0x07
68
69#define DACInfoFlag 0x0018
70#define MemoryInfoFlag 0x01E0
71#define MemorySizeShift 5
72
73/* modeflag */
74#define Charx8Dot 0x0200
75#define LineCompareOff 0x0400
76#define CRT2Mode 0x0800
77#define HalfDCLK 0x1000
78#define NoSupportSimuTV 0x2000
79#define NoSupportLCDScale 0x4000 /* SiS bridge: No scaling possible (no matter what panel) */
80#define DoubleScanMode 0x8000
81
82/* Infoflag */
83#define SupportTV 0x0008
84#define SupportTV1024 0x0800
85#define SupportCHTV 0x0800
86#define Support64048060Hz 0x0800 /* Special for 640x480 LCD */
87#define SupportHiVision 0x0010
88#define SupportYPbPr750p 0x1000
89#define SupportLCD 0x0020
90#define SupportRAMDAC2 0x0040 /* All (<= 100Mhz) */
91#define SupportRAMDAC2_135 0x0100 /* All except DH (<= 135Mhz) */
92#define SupportRAMDAC2_162 0x0200 /* B, C (<= 162Mhz) */
93#define SupportRAMDAC2_202 0x0400 /* C (<= 202Mhz) */
94#define InterlaceMode 0x0080
95#define SyncPP 0x0000
96#define SyncPN 0x4000
97#define SyncNP 0x8000
98#define SyncNN 0xc000
99
100/* SetFlag */
101#define ProgrammingCRT2 0x0001
102#define LowModeTests 0x0002
103#define LCDVESATiming 0x0008
104#define EnableLVDSDDA 0x0010
105#define SetDispDevSwitchFlag 0x0020
106#define CheckWinDos 0x0040
107#define SetDOSMode 0x0080
108
109/* Index in ModeResInfo table */
110#define SIS_RI_320x200 0
111#define SIS_RI_320x240 1
112#define SIS_RI_320x400 2
113#define SIS_RI_400x300 3
114#define SIS_RI_512x384 4
115#define SIS_RI_640x400 5
116#define SIS_RI_640x480 6
117#define SIS_RI_800x600 7
118#define SIS_RI_1024x768 8
119#define SIS_RI_1280x1024 9
120#define SIS_RI_1600x1200 10
121#define SIS_RI_1920x1440 11
122#define SIS_RI_2048x1536 12
123#define SIS_RI_720x480 13
124#define SIS_RI_720x576 14
125#define SIS_RI_1280x960 15
126#define SIS_RI_800x480 16
127#define SIS_RI_1024x576 17
128#define SIS_RI_1280x720 18
129#define SIS_RI_856x480 19
130#define SIS_RI_1280x768 20
131#define SIS_RI_1400x1050 21
132#define SIS_RI_1152x864 22 /* Up to here SiS conforming */
133#define SIS_RI_848x480 23
134#define SIS_RI_1360x768 24
135#define SIS_RI_1024x600 25
136#define SIS_RI_1152x768 26
137#define SIS_RI_768x576 27
138#define SIS_RI_1360x1024 28
139#define SIS_RI_1680x1050 29
140#define SIS_RI_1280x800 30
141#define SIS_RI_1920x1080 31
142#define SIS_RI_960x540 32
143#define SIS_RI_960x600 33
144
145#define SIS_VIDEO_CAPTURE 0x00 - 0x30
146#define SIS_VIDEO_PLAYBACK 0x02 - 0x30
147#define SIS_CRT2_PORT_04 0x04 - 0x30
148
149/* Mode numbers */
150static const unsigned short ModeIndex_320x200[] = {0x59, 0x41, 0x00, 0x4f};
151static const unsigned short ModeIndex_320x240[] = {0x50, 0x56, 0x00, 0x53};
152static const unsigned short ModeIndex_400x300[] = {0x51, 0x57, 0x00, 0x54};
153static const unsigned short ModeIndex_512x384[] = {0x52, 0x58, 0x00, 0x5c};
154static const unsigned short ModeIndex_640x400[] = {0x2f, 0x5d, 0x00, 0x5e};
155static const unsigned short ModeIndex_640x480[] = {0x2e, 0x44, 0x00, 0x62};
156static const unsigned short ModeIndex_720x480[] = {0x31, 0x33, 0x00, 0x35};
157static const unsigned short ModeIndex_720x576[] = {0x32, 0x34, 0x00, 0x36};
158static const unsigned short ModeIndex_768x576[] = {0x5f, 0x60, 0x00, 0x61};
159static const unsigned short ModeIndex_800x480[] = {0x70, 0x7a, 0x00, 0x76};
160static const unsigned short ModeIndex_800x600[] = {0x30, 0x47, 0x00, 0x63};
161static const unsigned short ModeIndex_848x480[] = {0x39, 0x3b, 0x00, 0x3e};
162static const unsigned short ModeIndex_856x480[] = {0x3f, 0x42, 0x00, 0x45};
163static const unsigned short ModeIndex_960x540[] = {0x1d, 0x1e, 0x00, 0x1f};
164static const unsigned short ModeIndex_960x600[] = {0x20, 0x21, 0x00, 0x22};
165static const unsigned short ModeIndex_1024x768[] = {0x38, 0x4a, 0x00, 0x64};
166static const unsigned short ModeIndex_1024x576[] = {0x71, 0x74, 0x00, 0x77};
167static const unsigned short ModeIndex_1152x864[] = {0x29, 0x2a, 0x00, 0x2b};
168static const unsigned short ModeIndex_1280x720[] = {0x79, 0x75, 0x00, 0x78};
169static const unsigned short ModeIndex_1280x768[] = {0x23, 0x24, 0x00, 0x25};
170static const unsigned short ModeIndex_1280x1024[] = {0x3a, 0x4d, 0x00, 0x65};
171
172static const unsigned char SiS_MDA_DAC[] =
173{
174 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
175 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
176 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
177 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
178 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
179 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
180 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
181 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F
182};
183
184static const unsigned char SiS_CGA_DAC[] =
185{
186 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
187 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
188 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
189 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
190 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
191 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
192 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
193 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F
194};
195
196static const unsigned char SiS_EGA_DAC[] =
197{
198 0x00,0x10,0x04,0x14,0x01,0x11,0x05,0x15,
199 0x20,0x30,0x24,0x34,0x21,0x31,0x25,0x35,
200 0x08,0x18,0x0C,0x1C,0x09,0x19,0x0D,0x1D,
201 0x28,0x38,0x2C,0x3C,0x29,0x39,0x2D,0x3D,
202 0x02,0x12,0x06,0x16,0x03,0x13,0x07,0x17,
203 0x22,0x32,0x26,0x36,0x23,0x33,0x27,0x37,
204 0x0A,0x1A,0x0E,0x1E,0x0B,0x1B,0x0F,0x1F,
205 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F
206};
207
208static const unsigned char SiS_VGA_DAC[] =
209{
210 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
211 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
212 0x00,0x05,0x08,0x0B,0x0E,0x11,0x14,0x18,
213 0x1C,0x20,0x24,0x28,0x2D,0x32,0x38,0x3F,
214 0x00,0x10,0x1F,0x2F,0x3F,0x1F,0x27,0x2F,
215 0x37,0x3F,0x2D,0x31,0x36,0x3A,0x3F,0x00,
216 0x07,0x0E,0x15,0x1C,0x0E,0x11,0x15,0x18,
217 0x1C,0x14,0x16,0x18,0x1A,0x1C,0x00,0x04,
218 0x08,0x0C,0x10,0x08,0x0A,0x0C,0x0E,0x10,
219 0x0B,0x0C,0x0D,0x0F,0x10
220};
221
222static const struct SiS_St SiSUSB_SModeIDTable[] =
223{
224 {0x03,0x0010,0x18,0x02,0x02,0x00,0x01,0x03,0x40},
225 {0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
226};
227
228static const struct SiS_StResInfo_S SiSUSB_StResInfo[] =
229{
230 { 640,400},
231 { 640,350},
232 { 720,400},
233 { 720,350},
234 { 640,480}
235};
236
237static const struct SiS_ModeResInfo SiSUSB_ModeResInfo[] =
238{
239 { 320, 200, 8, 8}, /* 0x00 */
240 { 320, 240, 8, 8}, /* 0x01 */
241 { 320, 400, 8, 8}, /* 0x02 */
242 { 400, 300, 8, 8}, /* 0x03 */
243 { 512, 384, 8, 8}, /* 0x04 */
244 { 640, 400, 8,16}, /* 0x05 */
245 { 640, 480, 8,16}, /* 0x06 */
246 { 800, 600, 8,16}, /* 0x07 */
247 { 1024, 768, 8,16}, /* 0x08 */
248 { 1280,1024, 8,16}, /* 0x09 */
249 { 1600,1200, 8,16}, /* 0x0a */
250 { 1920,1440, 8,16}, /* 0x0b */
251 { 2048,1536, 8,16}, /* 0x0c */
252 { 720, 480, 8,16}, /* 0x0d */
253 { 720, 576, 8,16}, /* 0x0e */
254 { 1280, 960, 8,16}, /* 0x0f */
255 { 800, 480, 8,16}, /* 0x10 */
256 { 1024, 576, 8,16}, /* 0x11 */
257 { 1280, 720, 8,16}, /* 0x12 */
258 { 856, 480, 8,16}, /* 0x13 */
259 { 1280, 768, 8,16}, /* 0x14 */
260 { 1400,1050, 8,16}, /* 0x15 */
261 { 1152, 864, 8,16}, /* 0x16 */
262 { 848, 480, 8,16}, /* 0x17 */
263 { 1360, 768, 8,16}, /* 0x18 */
264 { 1024, 600, 8,16}, /* 0x19 */
265 { 1152, 768, 8,16}, /* 0x1a */
266 { 768, 576, 8,16}, /* 0x1b */
267 { 1360,1024, 8,16}, /* 0x1c */
268 { 1680,1050, 8,16}, /* 0x1d */
269 { 1280, 800, 8,16}, /* 0x1e */
270 { 1920,1080, 8,16}, /* 0x1f */
271 { 960, 540, 8,16}, /* 0x20 */
272 { 960, 600, 8,16} /* 0x21 */
273};
274
275static const struct SiS_StandTable SiSUSB_StandTable[] =
276{
277 /* MD_3_400 - mode 0x03 - 400 */
278 {
279 0x50,0x18,0x10,0x1000,
280 { 0x00,0x03,0x00,0x02 },
281 0x67,
282 { 0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
283 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
284 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
285 0xff },
286 { 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
287 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
288 0x0c,0x00,0x0f,0x08 },
289 { 0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, 0xff }
290 },
291 /* Generic for VGA and higher */
292 {
293 0x00,0x00,0x00,0x0000,
294 { 0x01,0x0f,0x00,0x0e },
295 0x23,
296 { 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
297 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
298 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
299 0xff },
300 { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
301 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
302 0x01,0x00,0x00,0x00 },
303 { 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f, 0xff }
304 }
305};
306
307static const struct SiS_Ext SiSUSB_EModeIDTable[] =
308{
309 {0x2e,0x0a1b,0x0101,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x8 */
310 {0x2f,0x0a1b,0x0100,SIS_RI_640x400, 0x00,0x00,0x05,0x05,0x10, 0}, /* 640x400x8 */
311 {0x30,0x2a1b,0x0103,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x8 */
312 {0x31,0x4a1b,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x8 */
313 {0x32,0x4a1b,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x8 */
314 {0x33,0x4a1d,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x16 */
315 {0x34,0x6a1d,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x16 */
316 {0x35,0x4a1f,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x32 */
317 {0x36,0x6a1f,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x32 */
318 {0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x8 */
319 {0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x8 */
320 {0x41,0x9a1d,0x010e,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x16 */
321 {0x44,0x0a1d,0x0111,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x16 */
322 {0x47,0x2a1d,0x0114,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x16 */
323 {0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x16 */
324 {0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x16 */
325 {0x50,0x9a1b,0x0132,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x8 */
326 {0x51,0xba1b,0x0133,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x8 */
327 {0x52,0xba1b,0x0134,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x8 */
328 {0x56,0x9a1d,0x0135,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x16 */
329 {0x57,0xba1d,0x0136,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x16 */
330 {0x58,0xba1d,0x0137,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x16 */
331 {0x59,0x9a1b,0x0138,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x8 */
332 {0x5c,0xba1f,0x0000,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x32 */
333 {0x5d,0x0a1d,0x0139,SIS_RI_640x400, 0x00,0x00,0x05,0x07,0x10, 0}, /* 640x400x16 */
334 {0x5e,0x0a1f,0x0000,SIS_RI_640x400, 0x00,0x00,0x05,0x07,0x10, 0}, /* 640x400x32 */
335 {0x62,0x0a3f,0x013a,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x32 */
336 {0x63,0x2a3f,0x013b,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x32 */
337 {0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x32 */
338 {0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x32 */
339 {0x70,0x6a1b,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x8 */
340 {0x71,0x4a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x8 */
341 {0x74,0x4a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x16 */
342 {0x75,0x0a3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x16 */
343 {0x76,0x6a1f,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x32 */
344 {0x77,0x4a1f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x32 */
345 {0x78,0x0a3f,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x32 */
346 {0x79,0x0a3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x8 */
347 {0x7a,0x6a1d,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x16 */
348 {0x23,0x0e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x8 */
349 {0x24,0x0e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x16 */
350 {0x25,0x0eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x32 */
351 {0x39,0x6a1b,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x28,-1}, /* 848x480 */
352 {0x3b,0x6a3d,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x28,-1},
353 {0x3e,0x6a7f,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x28,-1},
354 {0x3f,0x6a1b,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x2a,-1}, /* 856x480 */
355 {0x42,0x6a3d,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x2a,-1},
356 {0x45,0x6a7f,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x2a,-1},
357 {0x4f,0x9a1f,0x0000,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x32 */
358 {0x53,0x9a1f,0x0000,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x32 */
359 {0x54,0xba1f,0x0000,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x32 */
360 {0x5f,0x6a1b,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x2c,-1}, /* 768x576 */
361 {0x60,0x6a1d,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x2c,-1},
362 {0x61,0x6a3f,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x2c,-1},
363 {0x1d,0x6a1b,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x2d,-1}, /* 960x540 */
364 {0x1e,0x6a3d,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x2d,-1},
365 {0x1f,0x6a7f,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x2d,-1},
366 {0x20,0x6a1b,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x2e,-1}, /* 960x600 */
367 {0x21,0x6a3d,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x2e,-1},
368 {0x22,0x6a7f,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x2e,-1},
369 {0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1}, /* 1152x864 */
370 {0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1},
371 {0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1},
372 {0xff,0x0000,0x0000,0, 0x00,0x00,0x00,0x00,0x00,-1}
373};
374
375static const struct SiS_Ext2 SiSUSB_RefIndex[] =
376{
377 {0x085f,0x0d,0x03,0x05,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x0 */
378 {0x0067,0x0e,0x04,0x05,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x1 */
379 {0x0067,0x0f,0x08,0x48,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x2 */
380 {0x0067,0x10,0x07,0x8b,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x3 */
381 {0x0047,0x11,0x0a,0x00,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x4 */
382 {0x0047,0x12,0x0d,0x00,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x5 */
383 {0x0047,0x13,0x13,0x00,0x05,0x30, 800, 600, 0x20, 0x00, 0x00}, /* 0x6 */
384 {0x0107,0x14,0x1c,0x00,0x05,0x30, 800, 600, 0x20, 0x00, 0x00}, /* 0x7 */
385 {0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0x8 */
386 {0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0x9 */
387 {0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xa */
388 {0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xb */
389 {0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xc */
390 {0xc047,0x0a,0x09,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xd */
391 {0xc047,0x0b,0x0e,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xe */
392 {0xc047,0x0c,0x15,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xf */
393 {0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0x30, 0x55, 0x6e}, /* 0x10 */
394 {0xc06f,0x3c,0x01,0x06,0x13,0x31, 720, 480, 0x30, 0x00, 0x00}, /* 0x11 */
395 {0x006f,0x3d,0x6f,0x06,0x14,0x32, 720, 576, 0x30, 0x00, 0x00}, /* 0x12 (6f was 03) */
396 {0x0087,0x15,0x06,0x00,0x06,0x38,1024, 768, 0x30, 0x00, 0x00}, /* 0x13 */
397 {0xc877,0x16,0x0b,0x06,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x14 */
398 {0xc067,0x17,0x0f,0x49,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x15 */
399 {0x0067,0x18,0x11,0x00,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x16 */
400 {0x0047,0x19,0x16,0x8c,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x17 */
401 {0x0107,0x1a,0x1b,0x00,0x06,0x38,1024, 768, 0x10, 0x00, 0x00}, /* 0x18 */
402 {0x0107,0x1b,0x1f,0x00,0x06,0x38,1024, 768, 0x10, 0x00, 0x00}, /* 0x19 */
403 {0x407f,0x00,0x00,0x00,0x00,0x41, 320, 200, 0x30, 0x56, 0x4e}, /* 0x1a */
404 {0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0x30, 0x00, 0x00}, /* 0x1b */
405 {0x007f,0x02,0x04,0x05,0x05,0x51, 400, 300, 0x30, 0x00, 0x00}, /* 0x1c */
406 {0xc077,0x03,0x0b,0x06,0x06,0x52, 512, 384, 0x30, 0x00, 0x00}, /* 0x1d */
407 {0x0077,0x32,0x40,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x1e */
408 {0x0047,0x33,0x07,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x1f */
409 {0x0047,0x34,0x0a,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x20 */
410 {0x0077,0x35,0x0b,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x21 */
411 {0x0047,0x36,0x11,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x22 */
412 {0x0047,0x37,0x16,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x23 */
413 {0x1137,0x38,0x19,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x24 */
414 {0x1107,0x39,0x1e,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x25 */
415 {0x1307,0x3a,0x20,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x26 */
416 {0x0077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00}, /* 0x27 */
417 {0x0087,0x45,0x57,0x00,0x16,0x39, 848, 480, 0x30, 0x00, 0x00}, /* 0x28 38Hzi */
418 {0xc067,0x46,0x55,0x0b,0x16,0x39, 848, 480, 0x30, 0x00, 0x00}, /* 0x29 848x480-60Hz */
419 {0x0087,0x47,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00}, /* 0x2a 856x480-38Hzi */
420 {0xc067,0x48,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00}, /* 0x2b 856x480-60Hz */
421 {0x006f,0x4d,0x71,0x06,0x15,0x5f, 768, 576, 0x30, 0x00, 0x00}, /* 0x2c 768x576-56Hz */
422 {0x0067,0x52,0x6a,0x00,0x1c,0x1d, 960, 540, 0x30, 0x00, 0x00}, /* 0x2d 960x540 60Hz */
423 {0x0077,0x53,0x6b,0x0b,0x1d,0x20, 960, 600, 0x30, 0x00, 0x00}, /* 0x2e 960x600 60Hz */
424 {0x0087,0x1c,0x11,0x00,0x07,0x3a,1280,1024, 0x30, 0x00, 0x00}, /* 0x2f */
425 {0x0137,0x1d,0x19,0x07,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x30 */
426 {0x0107,0x1e,0x1e,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x31 */
427 {0x0207,0x1f,0x20,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x32 */
428 {0x0127,0x54,0x6d,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x33 1152x864-60Hz */
429 {0x0127,0x44,0x19,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x34 1152x864-75Hz */
430 {0x0127,0x4a,0x1e,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x35 1152x864-85Hz */
431 {0xffff,0x00,0x00,0x00,0x00,0x00, 0, 0, 0, 0x00, 0x00}
432};
433
434static const struct SiS_CRT1Table SiSUSB_CRT1Table[] =
435{
436 {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
437 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00,
438 0x00}}, /* 0x0 */
439 {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e,
440 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
441 0x00}}, /* 0x1 */
442 {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0,
443 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05,
444 0x01}}, /* 0x2 */
445 {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
446 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01,
447 0x01}}, /* 0x3 */
448 {{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
449 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05,
450 0x00}}, /* 0x4 */
451 {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
452 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
453 0x00}}, /* 0x5 */
454 {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e,
455 0xe8,0x8a,0xdf,0xe7,0x07,0x00,0x00,0x01,
456 0x00}}, /* 0x6 */
457 {{0x64,0x4f,0x4f,0x88,0x55,0x9d,0xf2,0x1f,
458 0xe0,0x83,0xdf,0xdf,0xf3,0x10,0x00,0x01,
459 0x00}}, /* 0x7 */
460 {{0x63,0x4f,0x4f,0x87,0x5a,0x81,0xfb,0x1f,
461 0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
462 0x00}}, /* 0x8 */
463 {{0x65,0x4f,0x4f,0x89,0x58,0x80,0xfb,0x1f,
464 0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
465 0x61}}, /* 0x9 */
466 {{0x65,0x4f,0x4f,0x89,0x58,0x80,0x01,0x3e,
467 0xe0,0x83,0xdf,0xdf,0x02,0x00,0x00,0x05,
468 0x61}}, /* 0xa */
469 {{0x67,0x4f,0x4f,0x8b,0x58,0x81,0x0d,0x3e,
470 0xe0,0x83,0xdf,0xdf,0x0e,0x00,0x00,0x05,
471 0x61}}, /* 0xb */
472 {{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f,
473 0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01,
474 0x00}}, /* 0xc */
475 {{0x7b,0x63,0x63,0x9f,0x6a,0x93,0x6f,0xf0,
476 0x58,0x8a,0x57,0x57,0x70,0x20,0x00,0x05,
477 0x01}}, /* 0xd */
478 {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xf0,
479 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x06,
480 0x01}}, /* 0xe */
481 {{0x7d,0x63,0x63,0x81,0x6e,0x1d,0x98,0xf0,
482 0x7c,0x82,0x57,0x57,0x99,0x00,0x00,0x06,
483 0x01}}, /* 0xf */
484 {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xf0,
485 0x58,0x8b,0x57,0x57,0x70,0x20,0x00,0x06,
486 0x01}}, /* 0x10 */
487 {{0x7e,0x63,0x63,0x82,0x6b,0x13,0x75,0xf0,
488 0x58,0x8b,0x57,0x57,0x76,0x20,0x00,0x06,
489 0x01}}, /* 0x11 */
490 {{0x81,0x63,0x63,0x85,0x6d,0x18,0x7a,0xf0,
491 0x58,0x8b,0x57,0x57,0x7b,0x20,0x00,0x06,
492 0x61}}, /* 0x12 */
493 {{0x83,0x63,0x63,0x87,0x6e,0x19,0x81,0xf0,
494 0x58,0x8b,0x57,0x57,0x82,0x20,0x00,0x06,
495 0x61}}, /* 0x13 */
496 {{0x85,0x63,0x63,0x89,0x6f,0x1a,0x91,0xf0,
497 0x58,0x8b,0x57,0x57,0x92,0x20,0x00,0x06,
498 0x61}}, /* 0x14 */
499 {{0x99,0x7f,0x7f,0x9d,0x84,0x1a,0x96,0x1f,
500 0x7f,0x83,0x7f,0x7f,0x97,0x10,0x00,0x02,
501 0x00}}, /* 0x15 */
502 {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
503 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
504 0x01}}, /* 0x16 */
505 {{0xa1,0x7f,0x7f,0x85,0x86,0x97,0x24,0xf5,
506 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
507 0x01}}, /* 0x17 */
508 {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf5,
509 0x00,0x83,0xff,0xff,0x1f,0x10,0x00,0x02,
510 0x01}}, /* 0x18 */
511 {{0xa7,0x7f,0x7f,0x8b,0x89,0x95,0x26,0xf5,
512 0x00,0x83,0xff,0xff,0x27,0x10,0x00,0x02,
513 0x01}}, /* 0x19 */
514 {{0xa9,0x7f,0x7f,0x8d,0x8c,0x9a,0x2c,0xf5,
515 0x00,0x83,0xff,0xff,0x2d,0x14,0x00,0x02,
516 0x62}}, /* 0x1a */
517 {{0xab,0x7f,0x7f,0x8f,0x8d,0x9b,0x35,0xf5,
518 0x00,0x83,0xff,0xff,0x36,0x14,0x00,0x02,
519 0x62}}, /* 0x1b */
520 {{0xcf,0x9f,0x9f,0x93,0xb2,0x01,0x14,0xba,
521 0x00,0x83,0xff,0xff,0x15,0x00,0x00,0x03,
522 0x00}}, /* 0x1c */
523 {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0x5a,
524 0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
525 0x01}}, /* 0x1d */
526 {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0x5a,
527 0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
528 0x01}}, /* 0x1e */
529 {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0x5a,
530 0x00,0x83,0xff,0xff,0x2f,0x09,0x00,0x07,
531 0x01}}, /* 0x1f */
532 {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
533 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
534 0x00}}, /* 0x20 */
535 {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
536 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
537 0x00}}, /* 0x21 */
538 {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
539 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
540 0x00}}, /* 0x22 */
541 {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
542 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
543 0x00}}, /* 0x23 */
544 {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
545 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
546 0x00}}, /* 0x24 */
547 {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
548 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
549 0x00}}, /* 0x25 */
550 {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
551 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
552 0x00}}, /* 0x26 */
553 {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
554 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
555 0x00}}, /* 0x27 */
556 {{0x43,0xef,0xef,0x87,0x06,0x00,0xd4,0x1f,
557 0xa0,0x83,0x9f,0x9f,0xd5,0x1f,0x41,0x05,
558 0x63}}, /* 0x28 */
559 {{0x45,0xef,0xef,0x89,0x07,0x01,0xd9,0x1f,
560 0xa0,0x83,0x9f,0x9f,0xda,0x1f,0x41,0x05,
561 0x63}}, /* 0x29 */
562 {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
563 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
564 0x00}}, /* 0x2a */
565 {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
566 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
567 0x00}}, /* 0x2b */
568 {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
569 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
570 0x00}}, /* 0x2c */
571 {{0x59,0xff,0xff,0x9d,0x17,0x13,0x33,0xba,
572 0x00,0x83,0xff,0xff,0x34,0x0f,0x41,0x05,
573 0x44}}, /* 0x2d */
574 {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x38,0xba,
575 0x00,0x83,0xff,0xff,0x39,0x0f,0x41,0x05,
576 0x44}}, /* 0x2e */
577 {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x3d,0xba,
578 0x00,0x83,0xff,0xff,0x3e,0x0f,0x41,0x05,
579 0x44}}, /* 0x2f */
580 {{0x5d,0xff,0xff,0x81,0x19,0x95,0x41,0xba,
581 0x00,0x84,0xff,0xff,0x42,0x0f,0x41,0x05,
582 0x44}}, /* 0x30 */
583 {{0x55,0xff,0xff,0x99,0x0d,0x0c,0x3e,0xba,
584 0x00,0x84,0xff,0xff,0x3f,0x0f,0x41,0x05,
585 0x00}}, /* 0x31 */
586 {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba,
587 0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06,
588 0x01}}, /* 0x32 */
589 {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xba,
590 0x26,0x89,0xdf,0xdf,0x6f,0x00,0x00,0x06,
591 0x01}}, /* 0x33 */
592 {{0x7f,0x63,0x63,0x82,0x6b,0x13,0x75,0xba,
593 0x29,0x8c,0xdf,0xdf,0x75,0x00,0x00,0x06,
594 0x01}}, /* 0x34 */
595 {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf1,
596 0xaf,0x85,0x3f,0x3f,0x25,0x30,0x00,0x02,
597 0x01}}, /* 0x35 */
598 {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1,
599 0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02,
600 0x01}}, /* 0x36 */
601 {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1,
602 0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02,
603 0x01}}, /* 0x37 */
604 {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4,
605 0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
606 0x01}}, /* 0x38 */
607 {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xd4,
608 0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
609 0x01}}, /* 0x39 */
610 {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4,
611 0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07,
612 0x01}}, /* 0x3a */
613 {{0xdc,0x9f,0x9f,0x80,0xaf,0x9d,0xe6,0xff,
614 0xc0,0x83,0xbf,0xbf,0xe7,0x10,0x00,0x07,
615 0x01}}, /* 0x3b */
616 {{0x6b,0x59,0x59,0x8f,0x5e,0x8c,0x0b,0x3e,
617 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
618 0x00}}, /* 0x3c */
619 {{0x6d,0x59,0x59,0x91,0x60,0x89,0x53,0xf0,
620 0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
621 0x41}}, /* 0x3d */
622 {{0x86,0x6a,0x6a,0x8a,0x74,0x06,0x8c,0x15,
623 0x4f,0x83,0xef,0xef,0x8d,0x30,0x00,0x02,
624 0x00}}, /* 0x3e */
625 {{0x81,0x6a,0x6a,0x85,0x70,0x00,0x0f,0x3e,
626 0xeb,0x8e,0xdf,0xdf,0x10,0x00,0x00,0x02,
627 0x00}}, /* 0x3f */
628 {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1,
629 0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02,
630 0x01}}, /* 0x40 */
631 {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
632 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
633 0x01}}, /* 0x41 */
634 {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x20,0xf5,
635 0x03,0x88,0xff,0xff,0x21,0x10,0x00,0x07,
636 0x01}}, /* 0x42 */
637 {{0xe6,0xae,0xae,0x8a,0xbd,0x90,0x3d,0x10,
638 0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x00,0x03,
639 0x00}}, /* 0x43 */
640 {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef,
641 0x60,0x83,0x5f,0x5f,0x83,0x10,0x00,0x07,
642 0x01}}, /* 0x44 */
643 {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15,
644 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
645 0x00}}, /* 0x45 */
646 {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E,
647 0xE5,0x8d,0xDF,0xe4,0x04,0x00,0x00,0x06,
648 0x00}}, /* 0x46 */
649 {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15,
650 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
651 0x00}}, /* 0x47 */
652 {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E,
653 0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02,
654 0x00}}, /* 0x48 */
655 {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd,
656 0x01,0x8d,0xff,0x00,0x27,0x10,0x00,0x03,
657 0x01}}, /* 0x49 */
658 {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff,
659 0x60,0x8b,0x5f,0x5f,0x8b,0x10,0x00,0x03,
660 0x01}}, /* 0x4a */
661 {{0xea,0xae,0xae,0x8e,0xba,0x82,0x40,0x10,
662 0x1b,0x87,0x19,0x1a,0x41,0x0f,0x00,0x03,
663 0x00}}, /* 0x4b */
664 {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff,
665 0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07,
666 0x01}}, /* 0x4c */
667 {{0x75,0x5f,0x5f,0x99,0x66,0x90,0x53,0xf0,
668 0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
669 0x41}},
670 {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e,
671 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
672 0x00}}, /* 0x4e */
673 {{0xcd,0x9f,0x9f,0x91,0xab,0x1c,0x3a,0xff,
674 0x20,0x83,0x1f,0x1f,0x3b,0x10,0x00,0x07,
675 0x21}}, /* 0x4f */
676 {{0x15,0xd1,0xd1,0x99,0xe2,0x19,0x3d,0x10,
677 0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x01,0x0c,
678 0x20}}, /* 0x50 */
679 {{0x0e,0xef,0xef,0x92,0xfe,0x03,0x30,0xf0,
680 0x1e,0x83,0x1b,0x1c,0x31,0x00,0x01,0x00,
681 0x61}}, /* 0x51 */
682 {{0x85,0x77,0x77,0x89,0x7d,0x01,0x31,0xf0,
683 0x1e,0x84,0x1b,0x1c,0x32,0x00,0x00,0x02,
684 0x41}}, /* 0x52 */
685 {{0x87,0x77,0x77,0x8b,0x81,0x0b,0x68,0xf0,
686 0x5a,0x80,0x57,0x57,0x69,0x00,0x00,0x02,
687 0x01}}, /* 0x53 */
688 {{0xcd,0x8f,0x8f,0x91,0x9b,0x1b,0x7a,0xff,
689 0x64,0x8c,0x5f,0x62,0x7b,0x10,0x00,0x07,
690 0x41}} /* 0x54 */
691};
692
693static struct SiS_VCLKData SiSUSB_VCLKData[] =
694{
695 { 0x1b,0xe1, 25}, /* 0x00 */
696 { 0x4e,0xe4, 28}, /* 0x01 */
697 { 0x57,0xe4, 31}, /* 0x02 */
698 { 0xc3,0xc8, 36}, /* 0x03 */
699 { 0x42,0xe2, 40}, /* 0x04 */
700 { 0xfe,0xcd, 43}, /* 0x05 */
701 { 0x5d,0xc4, 44}, /* 0x06 */
702 { 0x52,0xe2, 49}, /* 0x07 */
703 { 0x53,0xe2, 50}, /* 0x08 */
704 { 0x74,0x67, 52}, /* 0x09 */
705 { 0x6d,0x66, 56}, /* 0x0a */
706 { 0x5a,0x64, 65}, /* 0x0b */
707 { 0x46,0x44, 67}, /* 0x0c */
708 { 0xb1,0x46, 68}, /* 0x0d */
709 { 0xd3,0x4a, 72}, /* 0x0e */
710 { 0x29,0x61, 75}, /* 0x0f */
711 { 0x6e,0x46, 76}, /* 0x10 */
712 { 0x2b,0x61, 78}, /* 0x11 */
713 { 0x31,0x42, 79}, /* 0x12 */
714 { 0xab,0x44, 83}, /* 0x13 */
715 { 0x46,0x25, 84}, /* 0x14 */
716 { 0x78,0x29, 86}, /* 0x15 */
717 { 0x62,0x44, 94}, /* 0x16 */
718 { 0x2b,0x41,104}, /* 0x17 */
719 { 0x3a,0x23,105}, /* 0x18 */
720 { 0x70,0x44,108}, /* 0x19 */
721 { 0x3c,0x23,109}, /* 0x1a */
722 { 0x5e,0x43,113}, /* 0x1b */
723 { 0xbc,0x44,116}, /* 0x1c */
724 { 0xe0,0x46,132}, /* 0x1d */
725 { 0x54,0x42,135}, /* 0x1e */
726 { 0xea,0x2a,139}, /* 0x1f */
727 { 0x41,0x22,157}, /* 0x20 */
728 { 0x70,0x24,162}, /* 0x21 */
729 { 0x30,0x21,175}, /* 0x22 */
730 { 0x4e,0x22,189}, /* 0x23 */
731 { 0xde,0x26,194}, /* 0x24 */
732 { 0x62,0x06,202}, /* 0x25 */
733 { 0x3f,0x03,229}, /* 0x26 */
734 { 0xb8,0x06,234}, /* 0x27 */
735 { 0x34,0x02,253}, /* 0x28 */
736 { 0x58,0x04,255}, /* 0x29 */
737 { 0x24,0x01,265}, /* 0x2a */
738 { 0x9b,0x02,267}, /* 0x2b */
739 { 0x70,0x05,270}, /* 0x2c */
740 { 0x25,0x01,272}, /* 0x2d */
741 { 0x9c,0x02,277}, /* 0x2e */
742 { 0x27,0x01,286}, /* 0x2f */
743 { 0x3c,0x02,291}, /* 0x30 */
744 { 0xef,0x0a,292}, /* 0x31 */
745 { 0xf6,0x0a,310}, /* 0x32 */
746 { 0x95,0x01,315}, /* 0x33 */
747 { 0xf0,0x09,324}, /* 0x34 */
748 { 0xfe,0x0a,331}, /* 0x35 */
749 { 0xf3,0x09,332}, /* 0x36 */
750 { 0xea,0x08,340}, /* 0x37 */
751 { 0xe8,0x07,376}, /* 0x38 */
752 { 0xde,0x06,389}, /* 0x39 */
753 { 0x52,0x2a, 54}, /* 0x3a 301 TV */
754 { 0x52,0x6a, 27}, /* 0x3b 301 TV */
755 { 0x62,0x24, 70}, /* 0x3c 301 TV */
756 { 0x62,0x64, 70}, /* 0x3d 301 TV */
757 { 0xa8,0x4c, 30}, /* 0x3e 301 TV */
758 { 0x20,0x26, 33}, /* 0x3f 301 TV */
759 { 0x31,0xc2, 39}, /* 0x40 */
760 { 0x60,0x36, 30}, /* 0x41 Chrontel */
761 { 0x40,0x4a, 28}, /* 0x42 Chrontel */
762 { 0x9f,0x46, 44}, /* 0x43 Chrontel */
763 { 0x97,0x2c, 26}, /* 0x44 */
764 { 0x44,0xe4, 25}, /* 0x45 Chrontel */
765 { 0x7e,0x32, 47}, /* 0x46 Chrontel */
766 { 0x8a,0x24, 31}, /* 0x47 Chrontel */
767 { 0x97,0x2c, 26}, /* 0x48 Chrontel */
768 { 0xce,0x3c, 39}, /* 0x49 */
769 { 0x52,0x4a, 36}, /* 0x4a Chrontel */
770 { 0x34,0x61, 95}, /* 0x4b */
771 { 0x78,0x27,108}, /* 0x4c - was 102 */
772 { 0x66,0x43,123}, /* 0x4d Modes 0x26-0x28 (1400x1050) */
773 { 0x41,0x4e, 21}, /* 0x4e */
774 { 0xa1,0x4a, 29}, /* 0x4f Chrontel */
775 { 0x19,0x42, 42}, /* 0x50 */
776 { 0x54,0x46, 58}, /* 0x51 Chrontel */
777 { 0x25,0x42, 61}, /* 0x52 */
778 { 0x44,0x44, 66}, /* 0x53 Chrontel */
779 { 0x3a,0x62, 70}, /* 0x54 Chrontel */
780 { 0x62,0xc6, 34}, /* 0x55 848x480-60 */
781 { 0x6a,0xc6, 37}, /* 0x56 848x480-75 - TEMP */
782 { 0xbf,0xc8, 35}, /* 0x57 856x480-38i,60 */
783 { 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) */
784 { 0x52,0x07,149}, /* 0x59 1280x960-85 */
785 { 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
786 { 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */
787 { 0x45,0x25, 83}, /* 0x5c 1280x800 */
788 { 0x70,0x0a,147}, /* 0x5d 1680x1050 */
789 { 0x70,0x24,162}, /* 0x5e 1600x1200 */
790 { 0x5a,0x64, 65}, /* 0x5f 1280x720 - temp */
791 { 0x63,0x46, 68}, /* 0x60 1280x768_2 */
792 { 0x31,0x42, 79}, /* 0x61 1280x768_3 - temp */
793 { 0, 0, 0}, /* 0x62 - custom (will be filled out at run-time) */
794 { 0x5a,0x64, 65}, /* 0x63 1280x720 (LCD LVDS) */
795 { 0x70,0x28, 90}, /* 0x64 1152x864@60 */
796 { 0x41,0xc4, 32}, /* 0x65 848x480@60 */
797 { 0x5c,0xc6, 32}, /* 0x66 856x480@60 */
798 { 0x76,0xe7, 27}, /* 0x67 720x480@60 */
799 { 0x5f,0xc6, 33}, /* 0x68 720/768x576@60 */
800 { 0x52,0x27, 75}, /* 0x69 1920x1080i 60Hz interlaced */
801 { 0x7c,0x6b, 38}, /* 0x6a 960x540@60 */
802 { 0xe3,0x56, 41}, /* 0x6b 960x600@60 */
803 { 0x45,0x25, 83}, /* 0x6c 1280x800 */
804 { 0x70,0x28, 90}, /* 0x6d 1152x864@60 */
805 { 0x15,0xe1, 20}, /* 0x6e 640x400@60 (fake, not actually used) */
806 { 0x5f,0xc6, 33}, /* 0x6f 720x576@60 */
807 { 0x37,0x5a, 10}, /* 0x70 320x200@60 (fake, not actually used) */
808 { 0x2b,0xc2, 35} /* 0x71 768@576@60 */
809};
810
811void SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr);
812unsigned short SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth);
813int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
814int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
815
816extern int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data);
817extern int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data);
818extern int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port,
819 u8 index, u8 data);
820extern int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port,
821 u8 index, u8 *data);
822extern int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port,
823 u8 idx, u8 myand, u8 myor);
824extern int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port,
825 u8 index, u8 myor);
826extern int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port,
827 u8 idx, u8 myand);
828
829#endif
830
diff --git a/drivers/usb/misc/sisusbvga/sisusb_struct.h b/drivers/usb/misc/sisusbvga/sisusb_struct.h
new file mode 100644
index 000000000000..94edd4726c42
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_struct.h
@@ -0,0 +1,169 @@
1/*
2 * General structure definitions for universal mode switching modules
3 *
4 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
5 *
6 * If distributed as part of the Linux kernel, the following license terms
7 * apply:
8 *
9 * * This program is free software; you can redistribute it and/or modify
10 * * it under the terms of the GNU General Public License as published by
11 * * the Free Software Foundation; either version 2 of the named License,
12 * * or any later version.
13 * *
14 * * This program is distributed in the hope that it will be useful,
15 * * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * * GNU General Public License for more details.
18 * *
19 * * You should have received a copy of the GNU General Public License
20 * * along with this program; if not, write to the Free Software
21 * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
22 *
23 * Otherwise, the following license terms apply:
24 *
25 * * Redistribution and use in source and binary forms, with or without
26 * * modification, are permitted provided that the following conditions
27 * * are met:
28 * * 1) Redistributions of source code must retain the above copyright
29 * * notice, this list of conditions and the following disclaimer.
30 * * 2) Redistributions in binary form must reproduce the above copyright
31 * * notice, this list of conditions and the following disclaimer in the
32 * * documentation and/or other materials provided with the distribution.
33 * * 3) The name of the author may not be used to endorse or promote products
34 * * derived from this software without specific prior written permission.
35 * *
36 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
37 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
39 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
40 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
45 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46 *
47 * Author: Thomas Winischhofer <thomas@winischhofer.net>
48 *
49 */
50
51#ifndef _SISUSB_STRUCT_H_
52#define _SISUSB_STRUCT_H_
53
54struct SiS_St {
55 unsigned char St_ModeID;
56 unsigned short St_ModeFlag;
57 unsigned char St_StTableIndex;
58 unsigned char St_CRT2CRTC;
59 unsigned char St_ResInfo;
60 unsigned char VB_StTVFlickerIndex;
61 unsigned char VB_StTVEdgeIndex;
62 unsigned char VB_StTVYFilterIndex;
63 unsigned char St_PDC;
64};
65
66struct SiS_StandTable
67{
68 unsigned char CRT_COLS;
69 unsigned char ROWS;
70 unsigned char CHAR_HEIGHT;
71 unsigned short CRT_LEN;
72 unsigned char SR[4];
73 unsigned char MISC;
74 unsigned char CRTC[0x19];
75 unsigned char ATTR[0x14];
76 unsigned char GRC[9];
77};
78
79struct SiS_StResInfo_S {
80 unsigned short HTotal;
81 unsigned short VTotal;
82};
83
84struct SiS_Ext
85{
86 unsigned char Ext_ModeID;
87 unsigned short Ext_ModeFlag;
88 unsigned short Ext_VESAID;
89 unsigned char Ext_RESINFO;
90 unsigned char VB_ExtTVFlickerIndex;
91 unsigned char VB_ExtTVEdgeIndex;
92 unsigned char VB_ExtTVYFilterIndex;
93 unsigned char VB_ExtTVYFilterIndexROM661;
94 unsigned char REFindex;
95 char ROMMODEIDX661;
96};
97
98struct SiS_Ext2
99{
100 unsigned short Ext_InfoFlag;
101 unsigned char Ext_CRT1CRTC;
102 unsigned char Ext_CRTVCLK;
103 unsigned char Ext_CRT2CRTC;
104 unsigned char Ext_CRT2CRTC_NS;
105 unsigned char ModeID;
106 unsigned short XRes;
107 unsigned short YRes;
108 unsigned char Ext_PDC;
109 unsigned char Ext_FakeCRT2CRTC;
110 unsigned char Ext_FakeCRT2Clk;
111};
112
113struct SiS_CRT1Table
114{
115 unsigned char CR[17];
116};
117
118struct SiS_VCLKData
119{
120 unsigned char SR2B,SR2C;
121 unsigned short CLOCK;
122};
123
124struct SiS_ModeResInfo
125{
126 unsigned short HTotal;
127 unsigned short VTotal;
128 unsigned char XChar;
129 unsigned char YChar;
130};
131
132struct SiS_Private
133{
134 void *sisusb;
135
136 unsigned long IOAddress;
137
138 unsigned long SiS_P3c4;
139 unsigned long SiS_P3d4;
140 unsigned long SiS_P3c0;
141 unsigned long SiS_P3ce;
142 unsigned long SiS_P3c2;
143 unsigned long SiS_P3ca;
144 unsigned long SiS_P3c6;
145 unsigned long SiS_P3c7;
146 unsigned long SiS_P3c8;
147 unsigned long SiS_P3c9;
148 unsigned long SiS_P3cb;
149 unsigned long SiS_P3cc;
150 unsigned long SiS_P3cd;
151 unsigned long SiS_P3da;
152 unsigned long SiS_Part1Port;
153
154 unsigned char SiS_MyCR63;
155 unsigned short SiS_CRT1Mode;
156 unsigned short SiS_ModeType;
157 unsigned short SiS_SetFlag;
158
159 const struct SiS_StandTable *SiS_StandTable;
160 const struct SiS_St *SiS_SModeIDTable;
161 const struct SiS_Ext *SiS_EModeIDTable;
162 const struct SiS_Ext2 *SiS_RefIndex;
163 const struct SiS_CRT1Table *SiS_CRT1Table;
164 struct SiS_VCLKData *SiS_VCLKData;
165 const struct SiS_ModeResInfo *SiS_ModeResInfo;
166};
167
168#endif
169
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index faa74436de52..03fb70ef2eb3 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -3,8 +3,8 @@
3/* 3/*
4 * uss720.c -- USS720 USB Parport Cable. 4 * uss720.c -- USS720 USB Parport Cable.
5 * 5 *
6 * Copyright (C) 1999 6 * Copyright (C) 1999, 2005
7 * Thomas Sailer (sailer@ife.ee.ethz.ch) 7 * Thomas Sailer (t.sailer@alumni.ethz.ch)
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
@@ -23,103 +23,240 @@
23 * Based on parport_pc.c 23 * Based on parport_pc.c
24 * 24 *
25 * History: 25 * History:
26 * 0.1 04.08.99 Created 26 * 0.1 04.08.1999 Created
27 * 0.2 07.08.99 Some fixes mainly suggested by Tim Waugh 27 * 0.2 07.08.1999 Some fixes mainly suggested by Tim Waugh
28 * Interrupt handling currently disabled because 28 * Interrupt handling currently disabled because
29 * usb_request_irq crashes somewhere within ohci.c 29 * usb_request_irq crashes somewhere within ohci.c
30 * for no apparent reason (that is for me, anyway) 30 * for no apparent reason (that is for me, anyway)
31 * ECP currently untested 31 * ECP currently untested
32 * 0.3 10.08.99 fixing merge errors 32 * 0.3 10.08.1999 fixing merge errors
33 * 0.4 13.08.99 Added Vendor/Product ID of Brad Hard's cable 33 * 0.4 13.08.1999 Added Vendor/Product ID of Brad Hard's cable
34 * 0.5 20.09.99 usb_control_msg wrapper used 34 * 0.5 20.09.1999 usb_control_msg wrapper used
35 * Nov01.00 usb_device_table support by Adam J. Richter 35 * Nov01.2000 usb_device_table support by Adam J. Richter
36 * 08.04.01 Identify version on module load. gb 36 * 08.04.2001 Identify version on module load. gb
37 * 0.6 02.09.2005 Fix "scheduling in interrupt" problem by making save/restore
38 * context asynchronous
37 * 39 *
38 */ 40 */
39 41
40/*****************************************************************************/ 42/*****************************************************************************/
41 43
44#define DEBUG
45
42#include <linux/module.h> 46#include <linux/module.h>
43#include <linux/socket.h> 47#include <linux/socket.h>
44#include <linux/parport.h> 48#include <linux/parport.h>
45#include <linux/init.h> 49#include <linux/init.h>
46#include <linux/usb.h> 50#include <linux/usb.h>
47#include <linux/delay.h> 51#include <linux/delay.h>
52#include <linux/completion.h>
53#include <linux/kref.h>
48 54
49/* 55/*
50 * Version Information 56 * Version Information
51 */ 57 */
52#define DRIVER_VERSION "v0.5" 58#define DRIVER_VERSION "v0.6"
53#define DRIVER_AUTHOR "Thomas M. Sailer, sailer@ife.ee.ethz.ch" 59#define DRIVER_AUTHOR "Thomas M. Sailer, t.sailer@alumni.ethz.ch"
54#define DRIVER_DESC "USB Parport Cable driver for Cables using the Lucent Technologies USS720 Chip" 60#define DRIVER_DESC "USB Parport Cable driver for Cables using the Lucent Technologies USS720 Chip"
55 61
56/* --------------------------------------------------------------------- */ 62/* --------------------------------------------------------------------- */
57 63
58struct parport_uss720_private { 64struct parport_uss720_private {
59 struct usb_device *usbdev; 65 struct usb_device *usbdev;
60 void *irqhandle; 66 struct parport *pp;
61 unsigned int irqpipe; 67 struct kref ref_count;
62 unsigned char reg[7]; /* USB registers */ 68 __u8 reg[7]; /* USB registers */
69 struct list_head asynclist;
70 spinlock_t asynclock;
71};
72
73struct uss720_async_request {
74 struct parport_uss720_private *priv;
75 struct kref ref_count;
76 struct list_head asynclist;
77 struct completion compl;
78 struct urb *urb;
79 struct usb_ctrlrequest dr;
80 __u8 reg[7];
63}; 81};
64 82
65/* --------------------------------------------------------------------- */ 83/* --------------------------------------------------------------------- */
66 84
67static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val) 85static void destroy_priv(struct kref *kref)
68{ 86{
69 struct parport_uss720_private *priv = pp->private_data; 87 struct parport_uss720_private *priv = container_of(kref, struct parport_uss720_private, ref_count);
70 struct usb_device *usbdev = priv->usbdev;
71 static const unsigned char regindex[9] = {
72 4, 0, 1, 5, 5, 0, 2, 3, 6
73 };
74 int ret;
75 88
76 if (!usbdev) 89 usb_put_dev(priv->usbdev);
77 return -1; 90 kfree(priv);
78 ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev,0), 3, 0xc0, ((unsigned int)reg) << 8, 0, priv->reg, 7, 1000); 91 dbg("destroying priv datastructure");
79 if (ret != 7) { 92}
80 printk(KERN_DEBUG "uss720: get_1284_register(%d) failed, status 0x%x expected 7\n", 93
81 (unsigned int)reg, ret); 94static void destroy_async(struct kref *kref)
82 ret = -1; 95{
83 } else { 96 struct uss720_async_request *rq = container_of(kref, struct uss720_async_request, ref_count);
97 struct parport_uss720_private *priv = rq->priv;
98 unsigned long flags;
99
100 if (likely(rq->urb))
101 usb_free_urb(rq->urb);
102 spin_lock_irqsave(&priv->asynclock, flags);
103 list_del_init(&rq->asynclist);
104 spin_unlock_irqrestore(&priv->asynclock, flags);
105 kfree(rq);
106 kref_put(&priv->ref_count, destroy_priv);
107}
108
109/* --------------------------------------------------------------------- */
110
111static void async_complete(struct urb *urb, struct pt_regs *ptregs)
112{
113 struct uss720_async_request *rq;
114 struct parport *pp;
115 struct parport_uss720_private *priv;
116
117 rq = urb->context;
118 priv = rq->priv;
119 pp = priv->pp;
120 if (urb->status) {
121 err("async_complete: urb error %d", urb->status);
122 } else if (rq->dr.bRequest == 3) {
123 memcpy(priv->reg, rq->reg, sizeof(priv->reg));
84#if 0 124#if 0
85 printk(KERN_DEBUG "uss720: get_1284_register(%d) return %02x %02x %02x %02x %02x %02x %02x\n", 125 dbg("async_complete regs %02x %02x %02x %02x %02x %02x %02x",
86 (unsigned int)reg, (unsigned int)priv->reg[0], (unsigned int)priv->reg[1], 126 (unsigned int)priv->reg[0], (unsigned int)priv->reg[1], (unsigned int)priv->reg[2],
87 (unsigned int)priv->reg[2], (unsigned int)priv->reg[3], (unsigned int)priv->reg[4], 127 (unsigned int)priv->reg[3], (unsigned int)priv->reg[4], (unsigned int)priv->reg[5],
88 (unsigned int)priv->reg[5], (unsigned int)priv->reg[6]); 128 (unsigned int)priv->reg[6]);
89#endif 129#endif
90 /* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */ 130 /* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
91 if (priv->reg[2] & priv->reg[1] & 0x10) 131 if (rq->reg[2] & rq->reg[1] & 0x10 && pp)
92 parport_generic_irq(0, pp, NULL); 132 parport_generic_irq(0, pp, NULL);
93 ret = 0;
94 } 133 }
95 if (val) 134 complete(&rq->compl);
96 *val = priv->reg[(reg >= 9) ? 0 : regindex[reg]]; 135 kref_put(&rq->ref_count, destroy_async);
97 return ret;
98} 136}
99 137
100static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val) 138static struct uss720_async_request *submit_async_request(struct parport_uss720_private *priv,
139 __u8 request, __u8 requesttype, __u16 value, __u16 index,
140 unsigned int mem_flags)
101{ 141{
102 struct parport_uss720_private *priv = pp->private_data; 142 struct usb_device *usbdev;
103 struct usb_device *usbdev = priv->usbdev; 143 struct uss720_async_request *rq;
144 unsigned long flags;
104 int ret; 145 int ret;
105 146
147 if (!priv)
148 return NULL;
149 usbdev = priv->usbdev;
106 if (!usbdev) 150 if (!usbdev)
107 return -1; 151 return NULL;
108 ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev,0), 4, 0x40, (((unsigned int)reg) << 8) | val, 0, NULL, 0, 1000); 152 rq = kmalloc(sizeof(struct uss720_async_request), mem_flags);
109 if (ret) { 153 if (!rq) {
110 printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x) failed, status 0x%x\n", 154 err("submit_async_request out of memory");
111 (unsigned int)reg, (unsigned int)val, ret); 155 return NULL;
112 } else { 156 }
113#if 0 157 kref_init(&rq->ref_count);
114 printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x)\n", 158 INIT_LIST_HEAD(&rq->asynclist);
115 (unsigned int)reg, (unsigned int)val); 159 init_completion(&rq->compl);
116#endif 160 kref_get(&priv->ref_count);
161 rq->priv = priv;
162 rq->urb = usb_alloc_urb(0, mem_flags);
163 if (!rq->urb) {
164 kref_put(&rq->ref_count, destroy_async);
165 err("submit_async_request out of memory");
166 return NULL;
167 }
168 rq->dr.bRequestType = requesttype;
169 rq->dr.bRequest = request;
170 rq->dr.wValue = cpu_to_le16(value);
171 rq->dr.wIndex = cpu_to_le16(index);
172 rq->dr.wLength = cpu_to_le16((request == 3) ? sizeof(rq->reg) : 0);
173 usb_fill_control_urb(rq->urb, usbdev, (requesttype & 0x80) ? usb_rcvctrlpipe(usbdev, 0) : usb_sndctrlpipe(usbdev, 0),
174 (unsigned char *)&rq->dr,
175 (request == 3) ? rq->reg : NULL, (request == 3) ? sizeof(rq->reg) : 0, async_complete, rq);
176 /* rq->urb->transfer_flags |= URB_ASYNC_UNLINK; */
177 spin_lock_irqsave(&priv->asynclock, flags);
178 list_add_tail(&rq->asynclist, &priv->asynclist);
179 spin_unlock_irqrestore(&priv->asynclock, flags);
180 ret = usb_submit_urb(rq->urb, mem_flags);
181 if (!ret) {
182 kref_get(&rq->ref_count);
183 return rq;
117 } 184 }
185 kref_put(&rq->ref_count, destroy_async);
186 err("submit_async_request submit_urb failed with %d", ret);
187 return NULL;
188}
189
190static unsigned int kill_all_async_requests_priv(struct parport_uss720_private *priv)
191{
192 struct uss720_async_request *rq;
193 unsigned long flags;
194 unsigned int ret = 0;
195
196 spin_lock_irqsave(&priv->asynclock, flags);
197 list_for_each_entry(rq, &priv->asynclist, asynclist) {
198 usb_unlink_urb(rq->urb);
199 ret++;
200 }
201 spin_unlock_irqrestore(&priv->asynclock, flags);
118 return ret; 202 return ret;
119} 203}
120 204
121/* --------------------------------------------------------------------- */ 205/* --------------------------------------------------------------------- */
122 206
207static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val, unsigned int mem_flags)
208{
209 struct parport_uss720_private *priv;
210 struct uss720_async_request *rq;
211 static const unsigned char regindex[9] = {
212 4, 0, 1, 5, 5, 0, 2, 3, 6
213 };
214 int ret;
215
216 if (!pp)
217 return -EIO;
218 priv = pp->private_data;
219 rq = submit_async_request(priv, 3, 0xc0, ((unsigned int)reg) << 8, 0, mem_flags);
220 if (!rq) {
221 err("get_1284_register(%u) failed", (unsigned int)reg);
222 return -EIO;
223 }
224 if (!val) {
225 kref_put(&rq->ref_count, destroy_async);
226 return 0;
227 }
228 if (wait_for_completion_timeout(&rq->compl, HZ)) {
229 ret = rq->urb->status;
230 *val = priv->reg[(reg >= 9) ? 0 : regindex[reg]];
231 if (ret)
232 warn("get_1284_register: usb error %d", ret);
233 kref_put(&rq->ref_count, destroy_async);
234 return ret;
235 }
236 warn("get_1284_register timeout");
237 kill_all_async_requests_priv(priv);
238 return -EIO;
239}
240
241static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val, unsigned int mem_flags)
242{
243 struct parport_uss720_private *priv;
244 struct uss720_async_request *rq;
245
246 if (!pp)
247 return -EIO;
248 priv = pp->private_data;
249 rq = submit_async_request(priv, 4, 0x40, (((unsigned int)reg) << 8) | val, 0, mem_flags);
250 if (!rq) {
251 err("set_1284_register(%u,%u) failed", (unsigned int)reg, (unsigned int)val);
252 return -EIO;
253 }
254 kref_put(&rq->ref_count, destroy_async);
255 return 0;
256}
257
258/* --------------------------------------------------------------------- */
259
123/* ECR modes */ 260/* ECR modes */
124#define ECR_SPP 00 261#define ECR_SPP 00
125#define ECR_PS2 01 262#define ECR_PS2 01
@@ -132,8 +269,9 @@ static int change_mode(struct parport *pp, int m)
132{ 269{
133 struct parport_uss720_private *priv = pp->private_data; 270 struct parport_uss720_private *priv = pp->private_data;
134 int mode; 271 int mode;
272 __u8 reg;
135 273
136 if (get_1284_register(pp, 6, NULL)) 274 if (get_1284_register(pp, 6, &reg, GFP_KERNEL))
137 return -EIO; 275 return -EIO;
138 /* Bits <7:5> contain the mode. */ 276 /* Bits <7:5> contain the mode. */
139 mode = (priv->reg[2] >> 5) & 0x7; 277 mode = (priv->reg[2] >> 5) & 0x7;
@@ -153,7 +291,7 @@ static int change_mode(struct parport *pp, int m)
153 case ECR_ECP: /* ECP Parallel Port mode */ 291 case ECR_ECP: /* ECP Parallel Port mode */
154 /* Poll slowly. */ 292 /* Poll slowly. */
155 for (;;) { 293 for (;;) {
156 if (get_1284_register(pp, 6, NULL)) 294 if (get_1284_register(pp, 6, &reg, GFP_KERNEL))
157 return -EIO; 295 return -EIO;
158 if (priv->reg[2] & 0x01) 296 if (priv->reg[2] & 0x01)
159 break; 297 break;
@@ -167,7 +305,9 @@ static int change_mode(struct parport *pp, int m)
167 } 305 }
168 } 306 }
169 /* Set the mode. */ 307 /* Set the mode. */
170 if (set_1284_register(pp, 6, m << 5)) 308 if (set_1284_register(pp, 6, m << 5, GFP_KERNEL))
309 return -EIO;
310 if (get_1284_register(pp, 6, &reg, GFP_KERNEL))
171 return -EIO; 311 return -EIO;
172 return 0; 312 return 0;
173} 313}
@@ -179,7 +319,7 @@ static int clear_epp_timeout(struct parport *pp)
179{ 319{
180 unsigned char stat; 320 unsigned char stat;
181 321
182 if (get_1284_register(pp, 1, &stat)) 322 if (get_1284_register(pp, 1, &stat, GFP_KERNEL))
183 return 1; 323 return 1;
184 return stat & 1; 324 return stat & 1;
185} 325}
@@ -205,14 +345,14 @@ static int uss720_irq(int usbstatus, void *buffer, int len, void *dev_id)
205 345
206static void parport_uss720_write_data(struct parport *pp, unsigned char d) 346static void parport_uss720_write_data(struct parport *pp, unsigned char d)
207{ 347{
208 set_1284_register(pp, 0, d); 348 set_1284_register(pp, 0, d, GFP_KERNEL);
209} 349}
210 350
211static unsigned char parport_uss720_read_data(struct parport *pp) 351static unsigned char parport_uss720_read_data(struct parport *pp)
212{ 352{
213 unsigned char ret; 353 unsigned char ret;
214 354
215 if (get_1284_register(pp, 0, &ret)) 355 if (get_1284_register(pp, 0, &ret, GFP_KERNEL))
216 return 0; 356 return 0;
217 return ret; 357 return ret;
218} 358}
@@ -222,7 +362,7 @@ static void parport_uss720_write_control(struct parport *pp, unsigned char d)
222 struct parport_uss720_private *priv = pp->private_data; 362 struct parport_uss720_private *priv = pp->private_data;
223 363
224 d = (d & 0xf) | (priv->reg[1] & 0xf0); 364 d = (d & 0xf) | (priv->reg[1] & 0xf0);
225 if (set_1284_register(pp, 2, d)) 365 if (set_1284_register(pp, 2, d, GFP_KERNEL))
226 return; 366 return;
227 priv->reg[1] = d; 367 priv->reg[1] = d;
228} 368}
@@ -241,7 +381,7 @@ static unsigned char parport_uss720_frob_control(struct parport *pp, unsigned ch
241 mask &= 0x0f; 381 mask &= 0x0f;
242 val &= 0x0f; 382 val &= 0x0f;
243 d = (priv->reg[1] & (~mask)) ^ val; 383 d = (priv->reg[1] & (~mask)) ^ val;
244 if (set_1284_register(pp, 2, d)) 384 if (set_1284_register(pp, 2, d, GFP_KERNEL))
245 return 0; 385 return 0;
246 priv->reg[1] = d; 386 priv->reg[1] = d;
247 return d & 0xf; 387 return d & 0xf;
@@ -251,7 +391,7 @@ static unsigned char parport_uss720_read_status(struct parport *pp)
251{ 391{
252 unsigned char ret; 392 unsigned char ret;
253 393
254 if (get_1284_register(pp, 1, &ret)) 394 if (get_1284_register(pp, 1, &ret, GFP_KERNEL))
255 return 0; 395 return 0;
256 return ret & 0xf8; 396 return ret & 0xf8;
257} 397}
@@ -262,7 +402,7 @@ static void parport_uss720_disable_irq(struct parport *pp)
262 unsigned char d; 402 unsigned char d;
263 403
264 d = priv->reg[1] & ~0x10; 404 d = priv->reg[1] & ~0x10;
265 if (set_1284_register(pp, 2, d)) 405 if (set_1284_register(pp, 2, d, GFP_KERNEL))
266 return; 406 return;
267 priv->reg[1] = d; 407 priv->reg[1] = d;
268} 408}
@@ -273,7 +413,7 @@ static void parport_uss720_enable_irq(struct parport *pp)
273 unsigned char d; 413 unsigned char d;
274 414
275 d = priv->reg[1] | 0x10; 415 d = priv->reg[1] | 0x10;
276 if (set_1284_register(pp, 2, d)) 416 if (set_1284_register(pp, 2, d, GFP_KERNEL))
277 return; 417 return;
278 priv->reg[1] = d; 418 priv->reg[1] = d;
279} 419}
@@ -284,7 +424,7 @@ static void parport_uss720_data_forward (struct parport *pp)
284 unsigned char d; 424 unsigned char d;
285 425
286 d = priv->reg[1] & ~0x20; 426 d = priv->reg[1] & ~0x20;
287 if (set_1284_register(pp, 2, d)) 427 if (set_1284_register(pp, 2, d, GFP_KERNEL))
288 return; 428 return;
289 priv->reg[1] = d; 429 priv->reg[1] = d;
290} 430}
@@ -295,7 +435,7 @@ static void parport_uss720_data_reverse (struct parport *pp)
295 unsigned char d; 435 unsigned char d;
296 436
297 d = priv->reg[1] | 0x20; 437 d = priv->reg[1] | 0x20;
298 if (set_1284_register(pp, 2, d)) 438 if (set_1284_register(pp, 2, d, GFP_KERNEL))
299 return; 439 return;
300 priv->reg[1] = d; 440 priv->reg[1] = d;
301} 441}
@@ -310,17 +450,23 @@ static void parport_uss720_save_state(struct parport *pp, struct parport_state *
310{ 450{
311 struct parport_uss720_private *priv = pp->private_data; 451 struct parport_uss720_private *priv = pp->private_data;
312 452
313 if (get_1284_register(pp, 2, NULL)) 453#if 0
454 if (get_1284_register(pp, 2, NULL, GFP_ATOMIC))
314 return; 455 return;
456#endif
315 s->u.pc.ctr = priv->reg[1]; 457 s->u.pc.ctr = priv->reg[1];
316 s->u.pc.ecr = priv->reg[2]; 458 s->u.pc.ecr = priv->reg[2];
317} 459}
318 460
319static void parport_uss720_restore_state(struct parport *pp, struct parport_state *s) 461static void parport_uss720_restore_state(struct parport *pp, struct parport_state *s)
320{ 462{
321 set_1284_register(pp, 2, s->u.pc.ctr); 463 struct parport_uss720_private *priv = pp->private_data;
322 set_1284_register(pp, 6, s->u.pc.ecr); 464
323 get_1284_register(pp, 2, NULL); 465 set_1284_register(pp, 2, s->u.pc.ctr, GFP_ATOMIC);
466 set_1284_register(pp, 6, s->u.pc.ecr, GFP_ATOMIC);
467 get_1284_register(pp, 2, NULL, GFP_ATOMIC);
468 priv->reg[1] = s->u.pc.ctr;
469 priv->reg[2] = s->u.pc.ecr;
324} 470}
325 471
326static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t length, int flags) 472static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t length, int flags)
@@ -331,7 +477,7 @@ static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t
331 if (change_mode(pp, ECR_EPP)) 477 if (change_mode(pp, ECR_EPP))
332 return 0; 478 return 0;
333 for (; got < length; got++) { 479 for (; got < length; got++) {
334 if (get_1284_register(pp, 4, (char *)buf)) 480 if (get_1284_register(pp, 4, (char *)buf, GFP_KERNEL))
335 break; 481 break;
336 buf++; 482 buf++;
337 if (priv->reg[0] & 0x01) { 483 if (priv->reg[0] & 0x01) {
@@ -352,10 +498,10 @@ static size_t parport_uss720_epp_write_data(struct parport *pp, const void *buf,
352 if (change_mode(pp, ECR_EPP)) 498 if (change_mode(pp, ECR_EPP))
353 return 0; 499 return 0;
354 for (; written < length; written++) { 500 for (; written < length; written++) {
355 if (set_1284_register(pp, 4, (char *)buf)) 501 if (set_1284_register(pp, 4, (char *)buf, GFP_KERNEL))
356 break; 502 break;
357 ((char*)buf)++; 503 ((char*)buf)++;
358 if (get_1284_register(pp, 1, NULL)) 504 if (get_1284_register(pp, 1, NULL, GFP_KERNEL))
359 break; 505 break;
360 if (priv->reg[0] & 0x01) { 506 if (priv->reg[0] & 0x01) {
361 clear_epp_timeout(pp); 507 clear_epp_timeout(pp);
@@ -390,7 +536,7 @@ static size_t parport_uss720_epp_read_addr(struct parport *pp, void *buf, size_t
390 if (change_mode(pp, ECR_EPP)) 536 if (change_mode(pp, ECR_EPP))
391 return 0; 537 return 0;
392 for (; got < length; got++) { 538 for (; got < length; got++) {
393 if (get_1284_register(pp, 3, (char *)buf)) 539 if (get_1284_register(pp, 3, (char *)buf, GFP_KERNEL))
394 break; 540 break;
395 buf++; 541 buf++;
396 if (priv->reg[0] & 0x01) { 542 if (priv->reg[0] & 0x01) {
@@ -410,10 +556,10 @@ static size_t parport_uss720_epp_write_addr(struct parport *pp, const void *buf,
410 if (change_mode(pp, ECR_EPP)) 556 if (change_mode(pp, ECR_EPP))
411 return 0; 557 return 0;
412 for (; written < length; written++) { 558 for (; written < length; written++) {
413 if (set_1284_register(pp, 3, *(char *)buf)) 559 if (set_1284_register(pp, 3, *(char *)buf, GFP_KERNEL))
414 break; 560 break;
415 buf++; 561 buf++;
416 if (get_1284_register(pp, 1, NULL)) 562 if (get_1284_register(pp, 1, NULL, GFP_KERNEL))
417 break; 563 break;
418 if (priv->reg[0] & 0x01) { 564 if (priv->reg[0] & 0x01) {
419 clear_epp_timeout(pp); 565 clear_epp_timeout(pp);
@@ -467,7 +613,7 @@ static size_t parport_uss720_ecp_write_addr(struct parport *pp, const void *buff
467 if (change_mode(pp, ECR_ECP)) 613 if (change_mode(pp, ECR_ECP))
468 return 0; 614 return 0;
469 for (; written < len; written++) { 615 for (; written < len; written++) {
470 if (set_1284_register(pp, 5, *(char *)buffer)) 616 if (set_1284_register(pp, 5, *(char *)buffer, GFP_KERNEL))
471 break; 617 break;
472 buffer++; 618 buffer++;
473 } 619 }
@@ -536,93 +682,91 @@ static struct parport_operations parport_uss720_ops =
536static int uss720_probe(struct usb_interface *intf, 682static int uss720_probe(struct usb_interface *intf,
537 const struct usb_device_id *id) 683 const struct usb_device_id *id)
538{ 684{
539 struct usb_device *usbdev = interface_to_usbdev(intf); 685 struct usb_device *usbdev = usb_get_dev(interface_to_usbdev(intf));
540 struct usb_host_interface *interface; 686 struct usb_host_interface *interface;
541 struct usb_host_endpoint *endpoint; 687 struct usb_host_endpoint *endpoint;
542 struct parport_uss720_private *priv; 688 struct parport_uss720_private *priv;
543 struct parport *pp; 689 struct parport *pp;
690 unsigned char reg;
544 int i; 691 int i;
545 692
546 printk(KERN_DEBUG "uss720: probe: vendor id 0x%x, device id 0x%x\n", 693 dbg("probe: vendor id 0x%x, device id 0x%x\n",
547 le16_to_cpu(usbdev->descriptor.idVendor), 694 le16_to_cpu(usbdev->descriptor.idVendor),
548 le16_to_cpu(usbdev->descriptor.idProduct)); 695 le16_to_cpu(usbdev->descriptor.idProduct));
549 696
550 /* our known interfaces have 3 alternate settings */ 697 /* our known interfaces have 3 alternate settings */
551 if (intf->num_altsetting != 3) 698 if (intf->num_altsetting != 3) {
699 usb_put_dev(usbdev);
552 return -ENODEV; 700 return -ENODEV;
553 701 }
554 i = usb_set_interface(usbdev, intf->altsetting->desc.bInterfaceNumber, 2); 702 i = usb_set_interface(usbdev, intf->altsetting->desc.bInterfaceNumber, 2);
555 printk(KERN_DEBUG "uss720: set inteface result %d\n", i); 703 dbg("set inteface result %d", i);
556 704
557 interface = intf->cur_altsetting; 705 interface = intf->cur_altsetting;
558 706
559 /* 707 /*
560 * Allocate parport interface 708 * Allocate parport interface
561 */ 709 */
562 printk(KERN_INFO "uss720: (C) 1999 by Thomas Sailer, <sailer@ife.ee.ethz.ch>\n"); 710 if (!(priv = kcalloc(sizeof(struct parport_uss720_private), 1, GFP_KERNEL))) {
563 711 usb_put_dev(usbdev);
564 if (!(priv = kmalloc(sizeof(struct parport_uss720_private), GFP_KERNEL)))
565 return -ENOMEM; 712 return -ENOMEM;
713 }
714 priv->pp = NULL;
715 priv->usbdev = usbdev;
716 kref_init(&priv->ref_count);
717 spin_lock_init(&priv->asynclock);
718 INIT_LIST_HEAD(&priv->asynclist);
566 if (!(pp = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &parport_uss720_ops))) { 719 if (!(pp = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &parport_uss720_ops))) {
567 printk(KERN_WARNING "usb-uss720: could not register parport\n"); 720 warn("could not register parport");
568 goto probe_abort; 721 goto probe_abort;
569 } 722 }
570 723
724 priv->pp = pp;
571 pp->private_data = priv; 725 pp->private_data = priv;
572 priv->usbdev = usbdev;
573 pp->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP | PARPORT_MODE_ECP | PARPORT_MODE_COMPAT; 726 pp->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP | PARPORT_MODE_ECP | PARPORT_MODE_COMPAT;
574 727
575 /* set the USS720 control register to manual mode, no ECP compression, enable all ints */ 728 /* set the USS720 control register to manual mode, no ECP compression, enable all ints */
576 set_1284_register(pp, 7, 0x00); 729 set_1284_register(pp, 7, 0x00, GFP_KERNEL);
577 set_1284_register(pp, 6, 0x30); /* PS/2 mode */ 730 set_1284_register(pp, 6, 0x30, GFP_KERNEL); /* PS/2 mode */
578 set_1284_register(pp, 2, 0x0c); 731 set_1284_register(pp, 2, 0x0c, GFP_KERNEL);
579 /* debugging */ 732 /* debugging */
580 get_1284_register(pp, 0, NULL); 733 get_1284_register(pp, 0, &reg, GFP_KERNEL);
581 printk("uss720: reg: %02x %02x %02x %02x %02x %02x %02x\n", 734 dbg("reg: %02x %02x %02x %02x %02x %02x %02x",
582 priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]); 735 priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]);
583 736
584 endpoint = &interface->endpoint[2]; 737 endpoint = &interface->endpoint[2];
585 printk(KERN_DEBUG "uss720: epaddr %d interval %d\n", endpoint->desc.bEndpointAddress, endpoint->desc.bInterval); 738 dbg("epaddr %d interval %d", endpoint->desc.bEndpointAddress, endpoint->desc.bInterval);
586#if 0
587 priv->irqpipe = usb_rcvctrlpipe(usbdev, endpoint->bEndpointAddress);
588 i = usb_request_irq(usbdev, priv->irqpipe,
589 uss720_irq, endpoint->bInterval,
590 pp, &priv->irqhandle);
591 if (i) {
592 printk (KERN_WARNING "usb-uss720: usb_request_irq failed (0x%x)\n", i);
593 goto probe_abort_port;
594 }
595#endif
596 parport_announce_port(pp); 739 parport_announce_port(pp);
597 740
598 usb_set_intfdata (intf, pp); 741 usb_set_intfdata(intf, pp);
599 return 0; 742 return 0;
600 743
601#if 0
602probe_abort_port:
603 parport_put_port(pp);
604#endif
605probe_abort: 744probe_abort:
606 kfree(priv); 745 kill_all_async_requests_priv(priv);
746 kref_put(&priv->ref_count, destroy_priv);
607 return -ENODEV; 747 return -ENODEV;
608} 748}
609 749
610static void uss720_disconnect(struct usb_interface *intf) 750static void uss720_disconnect(struct usb_interface *intf)
611{ 751{
612 struct parport *pp = usb_get_intfdata (intf); 752 struct parport *pp = usb_get_intfdata(intf);
613 struct parport_uss720_private *priv; 753 struct parport_uss720_private *priv;
754 struct usb_device *usbdev;
614 755
615 usb_set_intfdata (intf, NULL); 756 dbg("disconnect");
757 usb_set_intfdata(intf, NULL);
616 if (pp) { 758 if (pp) {
617 priv = pp->private_data; 759 priv = pp->private_data;
618 parport_remove_port(pp); 760 usbdev = priv->usbdev;
619#if 0
620 usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe);
621#endif
622 priv->usbdev = NULL; 761 priv->usbdev = NULL;
762 priv->pp = NULL;
763 dbg("parport_remove_port");
764 parport_remove_port(pp);
623 parport_put_port(pp); 765 parport_put_port(pp);
624 kfree(priv); 766 kill_all_async_requests_priv(priv);
767 kref_put(&priv->ref_count, destroy_priv);
625 } 768 }
769 dbg("disconnect done");
626} 770}
627 771
628/* table of cables that work through this driver */ 772/* table of cables that work through this driver */
@@ -647,8 +791,8 @@ static struct usb_driver uss720_driver = {
647 791
648/* --------------------------------------------------------------------- */ 792/* --------------------------------------------------------------------- */
649 793
650MODULE_AUTHOR( DRIVER_AUTHOR ); 794MODULE_AUTHOR(DRIVER_AUTHOR);
651MODULE_DESCRIPTION( DRIVER_DESC ); 795MODULE_DESCRIPTION(DRIVER_DESC);
652MODULE_LICENSE("GPL"); 796MODULE_LICENSE("GPL");
653 797
654static int __init uss720_init(void) 798static int __init uss720_init(void)
@@ -659,6 +803,9 @@ static int __init uss720_init(void)
659 goto out; 803 goto out;
660 804
661 info(DRIVER_VERSION ":" DRIVER_DESC); 805 info(DRIVER_VERSION ":" DRIVER_DESC);
806 info("NOTE: this is a special purpose driver to allow nonstandard");
807 info("protocols (eg. bitbang) over USS720 usb to parallel cables");
808 info("If you just want to connect to a printer, use usblp instead");
662out: 809out:
663 return retval; 810 return retval;
664} 811}
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index 417464dea9f6..17d0190ef64e 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -79,7 +79,7 @@ static inline char mon_text_get_setup(struct mon_event_text *ep,
79 return '-'; 79 return '-';
80 80
81 if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP) 81 if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)
82 return 'D'; 82 return mon_dmapeek(ep->setup, urb->setup_dma, SETUP_MAX);
83 if (urb->setup_packet == NULL) 83 if (urb->setup_packet == NULL)
84 return 'Z'; /* '0' would be not as pretty. */ 84 return 'Z'; /* '0' would be not as pretty. */
85 85
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index 4ace9964fc6b..97c78c21e8d1 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -32,7 +32,7 @@
32/* 32/*
33 * Version Information 33 * Version Information
34 */ 34 */
35#define DRIVER_VERSION "v0.04" 35#define DRIVER_VERSION "v0.05"
36#define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver" 36#define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver"
37 37
38/* 38/*
@@ -54,8 +54,11 @@ static void cp2101_shutdown(struct usb_serial*);
54static int debug; 54static int debug;
55 55
56static struct usb_device_id id_table [] = { 56static struct usb_device_id id_table [] = {
57 { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
57 { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ 58 { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
58 { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ 59 { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
60 { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */
61 { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
59 { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ 62 { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
60 { } /* Terminating Entry */ 63 { } /* Terminating Entry */
61}; 64};
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 05c44ae3ed32..9ee1aaff2fcd 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -610,8 +610,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
610 timeout = max((HZ*2560)/bps,HZ/10); 610 timeout = max((HZ*2560)/bps,HZ/10);
611 else 611 else
612 timeout = 2*HZ; 612 timeout = 2*HZ;
613 set_current_state(TASK_INTERRUPTIBLE); 613 schedule_timeout_interruptible(timeout);
614 schedule_timeout(timeout);
615 614
616 dbg("%s - stopping urbs", __FUNCTION__); 615 dbg("%s - stopping urbs", __FUNCTION__);
617 usb_kill_urb (port->interrupt_in_urb); 616 usb_kill_urb (port->interrupt_in_urb);
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 0a6e8b474b1f..4e434cb10bb1 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -914,7 +914,7 @@ static void ftdi_determine_type(struct usb_serial_port *port)
914 unsigned interfaces; 914 unsigned interfaces;
915 915
916 /* Assume it is not the original SIO device for now. */ 916 /* Assume it is not the original SIO device for now. */
917 priv->baud_base = 48000000 / 16; 917 priv->baud_base = 48000000 / 2;
918 priv->write_offset = 0; 918 priv->write_offset = 0;
919 919
920 version = le16_to_cpu(udev->descriptor.bcdDevice); 920 version = le16_to_cpu(udev->descriptor.bcdDevice);
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 461474176cfb..3cf245bdda54 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -95,6 +95,7 @@ static struct usb_device_id id_table [] = {
95 { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) }, 95 { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) },
96 { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) }, 96 { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) },
97 { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) }, 97 { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) },
98 { USB_DEVICE( NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID ) },
98 { } /* Terminating entry */ 99 { } /* Terminating entry */
99}; 100};
100 101
@@ -652,8 +653,7 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp)
652 timeout = max((HZ*2560)/bps,HZ/10); 653 timeout = max((HZ*2560)/bps,HZ/10);
653 else 654 else
654 timeout = 2*HZ; 655 timeout = 2*HZ;
655 set_current_state(TASK_INTERRUPTIBLE); 656 schedule_timeout_interruptible(timeout);
656 schedule_timeout(timeout);
657 657
658 /* shutdown our urbs */ 658 /* shutdown our urbs */
659 dbg("%s - shutting down urbs", __FUNCTION__); 659 dbg("%s - shutting down urbs", __FUNCTION__);
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index b734c4003c5a..7be9644f5a03 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -58,3 +58,7 @@
58 58
59#define SYNTECH_VENDOR_ID 0x0745 59#define SYNTECH_VENDOR_ID 0x0745
60#define SYNTECH_PRODUCT_ID 0x0001 60#define SYNTECH_PRODUCT_ID 0x0001
61
62/* Nokia CA-42 Cable */
63#define NOKIA_CA42_VENDOR_ID 0x078b
64#define NOKIA_CA42_PRODUCT_ID 0x1234
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index d34dc9f417f0..4837524eada7 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -227,42 +227,42 @@ static int queuecommand(struct scsi_cmnd *srb,
227 ***********************************************************************/ 227 ***********************************************************************/
228 228
229/* Command timeout and abort */ 229/* Command timeout and abort */
230/* This is always called with scsi_lock(host) held */
231static int command_abort(struct scsi_cmnd *srb) 230static int command_abort(struct scsi_cmnd *srb)
232{ 231{
233 struct us_data *us = host_to_us(srb->device->host); 232 struct us_data *us = host_to_us(srb->device->host);
234 233
235 US_DEBUGP("%s called\n", __FUNCTION__); 234 US_DEBUGP("%s called\n", __FUNCTION__);
236 235
236 /* us->srb together with the TIMED_OUT, RESETTING, and ABORTING
237 * bits are protected by the host lock. */
238 scsi_lock(us_to_host(us));
239
237 /* Is this command still active? */ 240 /* Is this command still active? */
238 if (us->srb != srb) { 241 if (us->srb != srb) {
242 scsi_unlock(us_to_host(us));
239 US_DEBUGP ("-- nothing to abort\n"); 243 US_DEBUGP ("-- nothing to abort\n");
240 return FAILED; 244 return FAILED;
241 } 245 }
242 246
243 /* Set the TIMED_OUT bit. Also set the ABORTING bit, but only if 247 /* Set the TIMED_OUT bit. Also set the ABORTING bit, but only if
244 * a device reset isn't already in progress (to avoid interfering 248 * a device reset isn't already in progress (to avoid interfering
245 * with the reset). To prevent races with auto-reset, we must 249 * with the reset). Note that we must retain the host lock while
246 * stop any ongoing USB transfers while still holding the host 250 * calling usb_stor_stop_transport(); otherwise it might interfere
247 * lock. */ 251 * with an auto-reset that begins as soon as we release the lock. */
248 set_bit(US_FLIDX_TIMED_OUT, &us->flags); 252 set_bit(US_FLIDX_TIMED_OUT, &us->flags);
249 if (!test_bit(US_FLIDX_RESETTING, &us->flags)) { 253 if (!test_bit(US_FLIDX_RESETTING, &us->flags)) {
250 set_bit(US_FLIDX_ABORTING, &us->flags); 254 set_bit(US_FLIDX_ABORTING, &us->flags);
251 usb_stor_stop_transport(us); 255 usb_stor_stop_transport(us);
252 } 256 }
257 scsi_unlock(us_to_host(us));
253 258
254 /* Wait for the aborted command to finish */ 259 /* Wait for the aborted command to finish */
255 wait_for_completion(&us->notify); 260 wait_for_completion(&us->notify);
256
257 /* Reacquire the lock and allow USB transfers to resume */
258 clear_bit(US_FLIDX_ABORTING, &us->flags);
259 clear_bit(US_FLIDX_TIMED_OUT, &us->flags);
260 return SUCCESS; 261 return SUCCESS;
261} 262}
262 263
263/* This invokes the transport reset mechanism to reset the state of the 264/* This invokes the transport reset mechanism to reset the state of the
264 * device */ 265 * device */
265/* This is always called with scsi_lock(host) held */
266static int device_reset(struct scsi_cmnd *srb) 266static int device_reset(struct scsi_cmnd *srb)
267{ 267{
268 struct us_data *us = host_to_us(srb->device->host); 268 struct us_data *us = host_to_us(srb->device->host);
@@ -279,7 +279,6 @@ static int device_reset(struct scsi_cmnd *srb)
279} 279}
280 280
281/* Simulate a SCSI bus reset by resetting the device's USB port. */ 281/* Simulate a SCSI bus reset by resetting the device's USB port. */
282/* This is always called with scsi_lock(host) held */
283static int bus_reset(struct scsi_cmnd *srb) 282static int bus_reset(struct scsi_cmnd *srb)
284{ 283{
285 struct us_data *us = host_to_us(srb->device->host); 284 struct us_data *us = host_to_us(srb->device->host);
@@ -291,7 +290,6 @@ static int bus_reset(struct scsi_cmnd *srb)
291 result = usb_stor_port_reset(us); 290 result = usb_stor_port_reset(us);
292 up(&(us->dev_semaphore)); 291 up(&(us->dev_semaphore));
293 292
294 /* lock the host for the return */
295 return result < 0 ? FAILED : SUCCESS; 293 return result < 0 ? FAILED : SUCCESS;
296} 294}
297 295
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index ad0cfd7a782f..b79dad1b598c 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -86,6 +86,16 @@ UNUSUAL_DEV( 0x040d, 0x6205, 0x0003, 0x0003,
86 US_SC_DEVICE, US_PR_DEVICE, NULL, 86 US_SC_DEVICE, US_PR_DEVICE, NULL,
87 US_FL_IGNORE_RESIDUE ), 87 US_FL_IGNORE_RESIDUE ),
88 88
89/* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net>
90 * and Olaf Hering <olh@suse.de> (different bcd's, same vendor/product)
91 * for USB floppies that need the SINGLE_LUN enforcement.
92 */
93UNUSUAL_DEV( 0x0409, 0x0040, 0x0000, 0x9999,
94 "NEC",
95 "NEC USB UF000x",
96 US_SC_DEVICE, US_PR_DEVICE, NULL,
97 US_FL_SINGLE_LUN ),
98
89/* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au> 99/* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
90 * Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message 100 * Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message
91 * always fails and confuses drive. 101 * always fails and confuses drive.
@@ -96,6 +106,13 @@ UNUSUAL_DEV( 0x0411, 0x001c, 0x0113, 0x0113,
96 US_SC_DEVICE, US_PR_DEVICE, NULL, 106 US_SC_DEVICE, US_PR_DEVICE, NULL,
97 US_FL_FIX_INQUIRY ), 107 US_FL_FIX_INQUIRY ),
98 108
109/* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */
110UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210,
111 "SMSC",
112 "FDC GOLD-2.30",
113 US_SC_DEVICE, US_PR_DEVICE, NULL,
114 US_FL_SINGLE_LUN ),
115
99#ifdef CONFIG_USB_STORAGE_DPCM 116#ifdef CONFIG_USB_STORAGE_DPCM
100UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, 117UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100,
101 "Microtech", 118 "Microtech",
@@ -103,6 +120,24 @@ UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100,
103 US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), 120 US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ),
104#endif 121#endif
105 122
123/*
124 * Pete Zaitcev <zaitcev@yahoo.com>, from Patrick C. F. Ernzer, bz#162559.
125 * The key does not actually break, but it returns zero sense which
126 * makes our SCSI stack to print confusing messages.
127 */
128UNUSUAL_DEV( 0x0457, 0x0150, 0x0100, 0x0100,
129 "USBest Technology", /* sold by Transcend */
130 "USB Mass Storage Device",
131 US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
132
133/* Patch submitted by Daniel Drake <dsd@gentoo.org>
134 * Device reports nonsense bInterfaceProtocol 6 when connected over USB2 */
135UNUSUAL_DEV( 0x0451, 0x5416, 0x0100, 0x0100,
136 "Neuros Audio",
137 "USB 2.0 HD 2.5",
138 US_SC_DEVICE, US_PR_BULK, NULL,
139 US_FL_NEED_OVERRIDE ),
140
106/* Patch submitted by Philipp Friedrich <philipp@void.at> */ 141/* Patch submitted by Philipp Friedrich <philipp@void.at> */
107UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100, 142UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100,
108 "Kyocera", 143 "Kyocera",
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index cb4c770baf32..f9a9bfa1aef5 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -392,11 +392,16 @@ SkipForAbort:
392 /* If an abort request was received we need to signal that 392 /* If an abort request was received we need to signal that
393 * the abort has finished. The proper test for this is 393 * the abort has finished. The proper test for this is
394 * the TIMED_OUT flag, not srb->result == DID_ABORT, because 394 * the TIMED_OUT flag, not srb->result == DID_ABORT, because
395 * a timeout/abort request might be received after all the 395 * the timeout might have occurred after the command had
396 * USB processing was complete. */ 396 * already completed with a different result code. */
397 if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) 397 if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
398 complete(&(us->notify)); 398 complete(&(us->notify));
399 399
400 /* Allow USB transfers to resume */
401 clear_bit(US_FLIDX_ABORTING, &us->flags);
402 clear_bit(US_FLIDX_TIMED_OUT, &us->flags);
403 }
404
400 /* finished working on this command */ 405 /* finished working on this command */
401 us->srb = NULL; 406 us->srb = NULL;
402 scsi_unlock(host); 407 scsi_unlock(host);
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 5fe182d6e4ab..eb83a7874c71 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -137,7 +137,7 @@ config FONT_8x8
137 137
138config FONT_8x16 138config FONT_8x16
139 bool "VGA 8x16 font" if FONTS 139 bool "VGA 8x16 font" if FONTS
140 depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y 140 depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y || USB_SISUSBVGA_CON
141 default y if !SPARC32 && !SPARC64 && !FONTS 141 default y if !SPARC32 && !SPARC64 && !FONTS
142 help 142 help
143 This is the "high resolution" font for the VGA frame buffer (the one 143 This is the "high resolution" font for the VGA frame buffer (the one
diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
index b562f6bb9d31..42c7b8dcd220 100644
--- a/drivers/video/console/Makefile
+++ b/drivers/video/console/Makefile
@@ -33,6 +33,10 @@ endif
33 33
34obj-$(CONFIG_FB_STI) += sticore.o font.o 34obj-$(CONFIG_FB_STI) += sticore.o font.o
35 35
36ifeq ($(CONFIG_USB_SISUSBVGA_CON),y)
37obj-$(CONFIG_USB_SISUSBVGA) += font.o
38endif
39
36# Targets that kbuild needs to know about 40# Targets that kbuild needs to know about
37targets := promcon_tbl.c 41targets := promcon_tbl.c
38 42
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index 7018ffffcbc4..0dbc9ddb6766 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -95,18 +95,18 @@ static struct pci_driver i810fb_driver = {
95static char *mode_option __devinitdata = NULL; 95static char *mode_option __devinitdata = NULL;
96static int vram __devinitdata = 4; 96static int vram __devinitdata = 4;
97static int bpp __devinitdata = 8; 97static int bpp __devinitdata = 8;
98static int mtrr __devinitdata = 0; 98static int mtrr __devinitdata;
99static int accel __devinitdata = 0; 99static int accel __devinitdata;
100static int hsync1 __devinitdata = 0; 100static int hsync1 __devinitdata;
101static int hsync2 __devinitdata = 0; 101static int hsync2 __devinitdata;
102static int vsync1 __devinitdata = 0; 102static int vsync1 __devinitdata;
103static int vsync2 __devinitdata = 0; 103static int vsync2 __devinitdata;
104static int xres __devinitdata = 640; 104static int xres __devinitdata;
105static int yres __devinitdata = 480; 105static int yres __devinitdata;
106static int vyres __devinitdata = 0; 106static int vyres __devinitdata;
107static int sync __devinitdata = 0; 107static int sync __devinitdata;
108static int ext_vga __devinitdata = 0; 108static int extvga __devinitdata;
109static int dcolor __devinitdata = 0; 109static int dcolor __devinitdata;
110 110
111/*------------------------------------------------------------*/ 111/*------------------------------------------------------------*/
112 112
@@ -950,7 +950,7 @@ static int i810_check_params(struct fb_var_screeninfo *var,
950 struct fb_info *info) 950 struct fb_info *info)
951{ 951{
952 struct i810fb_par *par = (struct i810fb_par *) info->par; 952 struct i810fb_par *par = (struct i810fb_par *) info->par;
953 int line_length, vidmem, mode_valid = 0; 953 int line_length, vidmem, mode_valid = 0, retval = 0;
954 u32 vyres = var->yres_virtual, vxres = var->xres_virtual; 954 u32 vyres = var->yres_virtual, vxres = var->xres_virtual;
955 /* 955 /*
956 * Memory limit 956 * Memory limit
@@ -1026,10 +1026,11 @@ static int i810_check_params(struct fb_var_screeninfo *var,
1026 printk("i810fb: invalid video mode%s\n", 1026 printk("i810fb: invalid video mode%s\n",
1027 default_sync ? "" : ". Specifying " 1027 default_sync ? "" : ". Specifying "
1028 "vsyncN/hsyncN parameters may help"); 1028 "vsyncN/hsyncN parameters may help");
1029 retval = -EINVAL;
1029 } 1030 }
1030 } 1031 }
1031 1032
1032 return 0; 1033 return retval;
1033} 1034}
1034 1035
1035/** 1036/**
@@ -1724,12 +1725,21 @@ static void __devinit i810_init_defaults(struct i810fb_par *par,
1724 if (bpp < 8) 1725 if (bpp < 8)
1725 bpp = 8; 1726 bpp = 8;
1726 1727
1728 par->i810fb_ops = i810fb_ops;
1729
1730 if (xres)
1731 info->var.xres = xres;
1732 else
1733 info->var.xres = 640;
1734
1735 if (yres)
1736 info->var.yres = yres;
1737 else
1738 info->var.yres = 480;
1739
1727 if (!vyres) 1740 if (!vyres)
1728 vyres = (vram << 20)/(xres*bpp >> 3); 1741 vyres = (vram << 20)/(info->var.xres*bpp >> 3);
1729 1742
1730 par->i810fb_ops = i810fb_ops;
1731 info->var.xres = xres;
1732 info->var.yres = yres;
1733 info->var.yres_virtual = vyres; 1743 info->var.yres_virtual = vyres;
1734 info->var.bits_per_pixel = bpp; 1744 info->var.bits_per_pixel = bpp;
1735 1745
@@ -1756,7 +1766,7 @@ static void __devinit i810_init_device(struct i810fb_par *par)
1756 i810_init_cursor(par); 1766 i810_init_cursor(par);
1757 1767
1758 /* mvo: enable external vga-connector (for laptops) */ 1768 /* mvo: enable external vga-connector (for laptops) */
1759 if (ext_vga) { 1769 if (extvga) {
1760 i810_writel(HVSYNC, mmio, 0); 1770 i810_writel(HVSYNC, mmio, 0);
1761 i810_writel(PWR_CLKC, mmio, 3); 1771 i810_writel(PWR_CLKC, mmio, 3);
1762 } 1772 }
@@ -1830,7 +1840,7 @@ static void __devinit i810fb_find_init_mode(struct fb_info *info)
1830{ 1840{
1831 struct fb_videomode mode; 1841 struct fb_videomode mode;
1832 struct fb_var_screeninfo var; 1842 struct fb_var_screeninfo var;
1833 struct fb_monspecs *specs = NULL; 1843 struct fb_monspecs *specs = &info->monspecs;
1834 int found = 0; 1844 int found = 0;
1835#ifdef CONFIG_FB_I810_I2C 1845#ifdef CONFIG_FB_I810_I2C
1836 int i; 1846 int i;
@@ -1853,16 +1863,24 @@ static void __devinit i810fb_find_init_mode(struct fb_info *info)
1853 if (!err) 1863 if (!err)
1854 printk("i810fb_init_pci: DDC probe successful\n"); 1864 printk("i810fb_init_pci: DDC probe successful\n");
1855 1865
1856 fb_edid_to_monspecs(par->edid, &info->monspecs); 1866 fb_edid_to_monspecs(par->edid, specs);
1857 1867
1858 if (info->monspecs.modedb == NULL) 1868 if (specs->modedb == NULL)
1859 printk("i810fb_init_pci: Unable to get Mode Database\n"); 1869 printk("i810fb_init_pci: Unable to get Mode Database\n");
1860 1870
1861 specs = &info->monspecs;
1862 fb_videomode_to_modelist(specs->modedb, specs->modedb_len, 1871 fb_videomode_to_modelist(specs->modedb, specs->modedb_len,
1863 &info->modelist); 1872 &info->modelist);
1864 if (specs->modedb != NULL) { 1873 if (specs->modedb != NULL) {
1865 if (specs->misc & FB_MISC_1ST_DETAIL) { 1874 if (xres && yres) {
1875 struct fb_videomode *m;
1876
1877 if ((m = fb_find_best_mode(&var, &info->modelist))) {
1878 mode = *m;
1879 found = 1;
1880 }
1881 }
1882
1883 if (!found && specs->misc & FB_MISC_1ST_DETAIL) {
1866 for (i = 0; i < specs->modedb_len; i++) { 1884 for (i = 0; i < specs->modedb_len; i++) {
1867 if (specs->modedb[i].flag & FB_MODE_IS_FIRST) { 1885 if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
1868 mode = specs->modedb[i]; 1886 mode = specs->modedb[i];
@@ -1903,8 +1921,8 @@ static int __devinit i810fb_setup(char *options)
1903 mtrr = 1; 1921 mtrr = 1;
1904 else if (!strncmp(this_opt, "accel", 5)) 1922 else if (!strncmp(this_opt, "accel", 5))
1905 accel = 1; 1923 accel = 1;
1906 else if (!strncmp(this_opt, "ext_vga", 7)) 1924 else if (!strncmp(this_opt, "extvga", 6))
1907 ext_vga = 1; 1925 extvga = 1;
1908 else if (!strncmp(this_opt, "sync", 4)) 1926 else if (!strncmp(this_opt, "sync", 4))
1909 sync = 1; 1927 sync = 1;
1910 else if (!strncmp(this_opt, "vram:", 5)) 1928 else if (!strncmp(this_opt, "vram:", 5))
@@ -2133,8 +2151,8 @@ module_param(accel, bool, 0);
2133MODULE_PARM_DESC(accel, "Use Acceleration (BLIT) engine (default = 0)"); 2151MODULE_PARM_DESC(accel, "Use Acceleration (BLIT) engine (default = 0)");
2134module_param(mtrr, bool, 0); 2152module_param(mtrr, bool, 0);
2135MODULE_PARM_DESC(mtrr, "Use MTRR (default = 0)"); 2153MODULE_PARM_DESC(mtrr, "Use MTRR (default = 0)");
2136module_param(ext_vga, bool, 0); 2154module_param(extvga, bool, 0);
2137MODULE_PARM_DESC(ext_vga, "Enable external VGA connector (default = 0)"); 2155MODULE_PARM_DESC(extvga, "Enable external VGA connector (default = 0)");
2138module_param(sync, bool, 0); 2156module_param(sync, bool, 0);
2139MODULE_PARM_DESC(sync, "wait for accel engine to finish drawing" 2157MODULE_PARM_DESC(sync, "wait for accel engine to finish drawing"
2140 " (default = 0)"); 2158 " (default = 0)");
diff --git a/drivers/w1/w1_ds2433.c b/drivers/w1/w1_ds2433.c
index b7c24b34d270..279e0e0363d6 100644
--- a/drivers/w1/w1_ds2433.c
+++ b/drivers/w1/w1_ds2433.c
@@ -15,6 +15,10 @@
15#include <linux/delay.h> 15#include <linux/delay.h>
16#ifdef CONFIG_W1_F23_CRC 16#ifdef CONFIG_W1_F23_CRC
17#include <linux/crc16.h> 17#include <linux/crc16.h>
18
19#define CRC16_INIT 0
20#define CRC16_VALID 0xb001
21
18#endif 22#endif
19 23
20#include "w1.h" 24#include "w1.h"
@@ -214,7 +218,7 @@ static ssize_t w1_f23_write_bin(struct kobject *kobj, char *buf, loff_t off,
214#ifdef CONFIG_W1_F23_CRC 218#ifdef CONFIG_W1_F23_CRC
215 /* can only write full blocks in cached mode */ 219 /* can only write full blocks in cached mode */
216 if ((off & W1_PAGE_MASK) || (count & W1_PAGE_MASK)) { 220 if ((off & W1_PAGE_MASK) || (count & W1_PAGE_MASK)) {
217 dev_err(&sl->dev, "invalid offset/count off=%d cnt=%d\n", 221 dev_err(&sl->dev, "invalid offset/count off=%d cnt=%zd\n",
218 (int)off, count); 222 (int)off, count);
219 return -EINVAL; 223 return -EINVAL;
220 } 224 }