Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
361d16e2
Commit
361d16e2
authored
Dec 28, 2003
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge nuts.ninka.net:/disk1/davem/BK/sparcwork-2.5
into nuts.ninka.net:/disk1/davem/BK/sparc-2.5
parents
e2990ed5
e241138a
Changes
40
Hide whitespace changes
Inline
Side-by-side
Showing
40 changed files
with
1693 additions
and
801 deletions
+1693
-801
Documentation/kernel-parameters.txt
Documentation/kernel-parameters.txt
+2
-1
arch/i386/kernel/irq.c
arch/i386/kernel/irq.c
+14
-0
arch/i386/lib/usercopy.c
arch/i386/lib/usercopy.c
+3
-1
arch/i386/pci/irq.c
arch/i386/pci/irq.c
+1
-9
drivers/block/ll_rw_blk.c
drivers/block/ll_rw_blk.c
+1
-1
drivers/char/keyboard.c
drivers/char/keyboard.c
+21
-14
drivers/char/watchdog/Kconfig
drivers/char/watchdog/Kconfig
+2
-2
drivers/input/input.c
drivers/input/input.c
+8
-6
drivers/input/joydev.c
drivers/input/joydev.c
+10
-4
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/atkbd.c
+162
-88
drivers/input/mouse/Kconfig
drivers/input/mouse/Kconfig
+7
-16
drivers/input/mouse/logips2pp.c
drivers/input/mouse/logips2pp.c
+21
-1
drivers/input/mouse/logips2pp.h
drivers/input/mouse/logips2pp.h
+1
-1
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/psmouse-base.c
+180
-155
drivers/input/mouse/psmouse.h
drivers/input/mouse/psmouse.h
+13
-0
drivers/input/mouse/synaptics.c
drivers/input/mouse/synaptics.c
+121
-111
drivers/input/mouse/synaptics.h
drivers/input/mouse/synaptics.h
+1
-5
drivers/input/serio/i8042.c
drivers/input/serio/i8042.c
+331
-204
drivers/input/serio/serio.c
drivers/input/serio/serio.c
+83
-23
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_main.c
+2
-1
drivers/net/pcmcia/3c574_cs.c
drivers/net/pcmcia/3c574_cs.c
+9
-6
drivers/net/tokenring/Kconfig
drivers/net/tokenring/Kconfig
+5
-5
drivers/net/typhoon.c
drivers/net/typhoon.c
+78
-19
drivers/net/wireless/atmel.c
drivers/net/wireless/atmel.c
+4
-2
drivers/scsi/ata_piix.c
drivers/scsi/ata_piix.c
+1
-0
drivers/scsi/libata-core.c
drivers/scsi/libata-core.c
+17
-19
drivers/scsi/libata-scsi.c
drivers/scsi/libata-scsi.c
+33
-10
drivers/scsi/libata.h
drivers/scsi/libata.h
+7
-7
drivers/scsi/sata_promise.c
drivers/scsi/sata_promise.c
+513
-61
drivers/scsi/sata_sil.c
drivers/scsi/sata_sil.c
+1
-0
drivers/scsi/sata_svw.c
drivers/scsi/sata_svw.c
+1
-0
drivers/scsi/sata_via.c
drivers/scsi/sata_via.c
+1
-0
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-hcd.c
+3
-0
drivers/usb/input/hid-core.c
drivers/usb/input/hid-core.c
+4
-0
include/asm-i386/irq.h
include/asm-i386/irq.h
+1
-0
include/linux/input.h
include/linux/input.h
+1
-0
include/linux/keyboard.h
include/linux/keyboard.h
+1
-2
include/linux/libata.h
include/linux/libata.h
+8
-5
include/linux/serio.h
include/linux/serio.h
+6
-2
kernel/sched.c
kernel/sched.c
+15
-20
No files found.
Documentation/kernel-parameters.txt
View file @
361d16e2
...
...
@@ -790,7 +790,8 @@ running once the system is up.
before loading.
See Documentation/ramdisk.txt.
psmouse_noext [HW,MOUSE] Disable probing for PS2 mouse protocol extensions
psmouse_proto= [HW,MOUSE] Highest PS2 mouse protocol extension to
probe for (bare|imps|exps).
psmouse_resetafter=
[HW,MOUSE] Try to reset Synaptics Touchpad after so many
...
...
arch/i386/kernel/irq.c
View file @
361d16e2
...
...
@@ -505,6 +505,20 @@ asmlinkage unsigned int do_IRQ(struct pt_regs regs)
return
1
;
}
int
can_request_irq
(
unsigned
int
irq
,
unsigned
long
irqflags
)
{
struct
irqaction
*
action
;
if
(
irq
>=
NR_IRQS
)
return
0
;
action
=
irq_desc
[
irq
].
action
;
if
(
action
)
{
if
(
irqflags
&
action
->
flags
&
SA_SHIRQ
)
action
=
NULL
;
}
return
!
action
;
}
/**
* request_irq - allocate an interrupt line
* @irq: Interrupt line to allocate
...
...
arch/i386/lib/usercopy.c
View file @
361d16e2
...
...
@@ -541,8 +541,10 @@ unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned long
goto
survive
;
}
if
(
retval
!=
1
)
if
(
retval
!=
1
)
{
up_read
(
&
current
->
mm
->
mmap_sem
);
break
;
}
maddr
=
kmap_atomic
(
pg
,
KM_USER0
);
memcpy
(
maddr
+
offset
,
from
,
len
);
...
...
arch/i386/pci/irq.c
View file @
361d16e2
...
...
@@ -695,11 +695,6 @@ static struct irq_info *pirq_get_info(struct pci_dev *dev)
return
NULL
;
}
static
irqreturn_t
pcibios_test_irq_handler
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
return
IRQ_NONE
;
}
static
int
pcibios_lookup_irq
(
struct
pci_dev
*
dev
,
int
assign
)
{
u8
pin
;
...
...
@@ -761,11 +756,8 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
for
(
i
=
0
;
i
<
16
;
i
++
)
{
if
(
!
(
mask
&
(
1
<<
i
)))
continue
;
if
(
pirq_penalty
[
i
]
<
pirq_penalty
[
newirq
]
&&
!
request_irq
(
i
,
pcibios_test_irq_handler
,
SA_SHIRQ
,
"pci-test"
,
dev
))
{
free_irq
(
i
,
dev
);
if
(
pirq_penalty
[
i
]
<
pirq_penalty
[
newirq
]
&&
can_request_irq
(
i
,
SA_SHIRQ
))
newirq
=
i
;
}
}
}
DBG
(
" -> newirq=%d"
,
newirq
);
...
...
drivers/block/ll_rw_blk.c
View file @
361d16e2
...
...
@@ -2460,7 +2460,7 @@ static int __end_that_request_first(struct request *req, int uptodate,
if
(
!
uptodate
)
{
error
=
-
EIO
;
if
(
!
(
req
->
flags
&
REQ_QUIET
))
if
(
blk_fs_request
(
req
)
&&
!
(
req
->
flags
&
REQ_QUIET
))
printk
(
"end_request: I/O error, dev %s, sector %llu
\n
"
,
req
->
rq_disk
?
req
->
rq_disk
->
disk_name
:
"?"
,
(
unsigned
long
long
)
req
->
sector
);
...
...
drivers/char/keyboard.c
View file @
361d16e2
...
...
@@ -941,16 +941,16 @@ static unsigned short x86_keycodes[256] =
32
,
33
,
34
,
35
,
36
,
37
,
38
,
39
,
40
,
41
,
42
,
43
,
44
,
45
,
46
,
47
,
48
,
49
,
50
,
51
,
52
,
53
,
54
,
55
,
56
,
57
,
58
,
59
,
60
,
61
,
62
,
63
,
64
,
65
,
66
,
67
,
68
,
69
,
70
,
71
,
72
,
73
,
74
,
75
,
76
,
77
,
78
,
79
,
80
,
81
,
82
,
83
,
43
,
85
,
86
,
87
,
88
,
115
,
119
,
120
,
121
,
375
,
123
,
90
,
284
,
285
,
309
,
298
,
312
,
91
,
327
,
328
,
329
,
331
,
333
,
335
,
336
,
337
,
338
,
339
,
367
,
288
,
302
,
304
,
350
,
92
,
334
,
512
,
116
,
377
,
109
,
111
,
373
,
347
,
348
,
349
,
360
,
93
,
94
,
95
,
98
,
376
,
100
,
101
,
321
,
316
,
354
,
286
,
289
,
102
,
351
,
355
,
80
,
81
,
82
,
83
,
84
,
93
,
86
,
87
,
88
,
94
,
95
,
85
,
259
,
375
,
260
,
90
,
284
,
285
,
309
,
311
,
312
,
91
,
327
,
328
,
329
,
331
,
333
,
335
,
336
,
337
,
338
,
339
,
367
,
288
,
302
,
304
,
350
,
89
,
334
,
326
,
116
,
377
,
109
,
111
,
126
,
347
,
348
,
349
,
360
,
261
,
262
,
263
,
298
,
376
,
100
,
101
,
321
,
316
,
373
,
286
,
289
,
102
,
351
,
355
,
103
,
104
,
105
,
275
,
287
,
279
,
306
,
106
,
274
,
107
,
294
,
364
,
358
,
363
,
362
,
361
,
291
,
108
,
381
,
281
,
290
,
272
,
292
,
305
,
280
,
99
,
112
,
257
,
258
,
359
,
270
,
114
,
118
,
117
,
125
,
374
,
379
,
115
,
112
,
125
,
121
,
123
,
264
,
265
,
266
,
267
,
268
,
269
,
271
,
273
,
276
,
277
,
278
,
282
,
283
,
295
,
296
,
297
,
299
,
300
,
301
,
293
,
303
,
307
,
308
,
310
,
313
,
314
,
315
,
317
,
318
,
319
,
320
,
357
,
322
,
323
,
324
,
325
,
32
6
,
330
,
332
,
340
,
365
,
342
,
343
,
344
,
345
,
346
,
356
,
113
,
341
,
368
,
369
,
370
,
371
,
372
};
291
,
108
,
381
,
281
,
290
,
272
,
292
,
305
,
280
,
99
,
112
,
257
,
258
,
359
,
113
,
114
,
264
,
117
,
271
,
374
,
379
,
115
,
125
,
273
,
121
,
123
,
92
,
265
,
266
,
267
,
268
,
269
,
120
,
119
,
118
,
277
,
278
,
282
,
283
,
295
,
296
,
297
,
299
,
300
,
301
,
293
,
303
,
307
,
308
,
310
,
313
,
314
,
315
,
317
,
318
,
319
,
320
,
357
,
322
,
323
,
324
,
325
,
27
6
,
330
,
332
,
340
,
365
,
342
,
343
,
344
,
345
,
346
,
356
,
270
,
341
,
368
,
369
,
370
,
371
,
372
};
#ifdef CONFIG_MAC_EMUMOUSEBTN
extern
int
mac_hid_mouse_emulate_buttons
(
int
,
int
,
int
);
...
...
@@ -972,11 +972,18 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode,
if
(
keycode
>
255
||
!
x86_keycodes
[
keycode
])
return
-
1
;
if
(
keycode
==
KEY_PAUSE
)
{
put_queue
(
vc
,
0xe1
);
put_queue
(
vc
,
0x1d
|
up_flag
);
put_queue
(
vc
,
0x45
|
up_flag
);
return
0
;
switch
(
keycode
)
{
case
KEY_PAUSE
:
put_queue
(
vc
,
0xe1
);
put_queue
(
vc
,
0x1d
|
up_flag
);
put_queue
(
vc
,
0x45
|
up_flag
);
return
0
;
case
KEY_LANG1
:
if
(
!
up_flag
)
put_queue
(
vc
,
0xf1
);
return
0
;
case
KEY_LANG2
:
if
(
!
up_flag
)
put_queue
(
vc
,
0xf2
);
return
0
;
}
if
(
keycode
==
KEY_SYSRQ
&&
sysrq_alt
)
{
...
...
drivers/char/watchdog/Kconfig
View file @
361d16e2
...
...
@@ -17,7 +17,7 @@ config WATCHDOG
implementation entirely in software (which can sometimes fail to
reboot the machine) and a driver for hardware watchdog boards, which
are more robust and can also keep track of the temperature inside
your computer. For details, read <file:Documentation/watchdog.txt>
your computer. For details, read <file:Documentation/watchdog
/watchdog
.txt>
in the kernel source.
The watchdog is usually used together with the watchdog daemon
...
...
@@ -114,7 +114,7 @@ config PCWATCHDOG
This card simply watches your kernel to make sure it doesn't freeze,
and if it does, it reboots your computer after a certain amount of
time. This driver is like the WDT501 driver but for different
hardware. Please read <file:Documentation/pcwd-watchdog.txt>. The PC
hardware. Please read <file:Documentation/
watchdog/
pcwd-watchdog.txt>. The PC
watchdog cards can be ordered from <http://www.berkprod.com/>.
To compile this driver as a module, choose M here: the
...
...
drivers/input/input.c
View file @
361d16e2
...
...
@@ -447,9 +447,10 @@ void input_register_device(struct input_dev *dev)
list_add_tail
(
&
dev
->
node
,
&
input_dev_list
);
list_for_each_entry
(
handler
,
&
input_handler_list
,
node
)
if
((
id
=
input_match_device
(
handler
->
id_table
,
dev
)))
if
((
handle
=
handler
->
connect
(
handler
,
dev
,
id
)))
input_link_handle
(
handle
);
if
(
!
handler
->
blacklist
||
!
input_match_device
(
handler
->
blacklist
,
dev
))
if
((
id
=
input_match_device
(
handler
->
id_table
,
dev
)))
if
((
handle
=
handler
->
connect
(
handler
,
dev
,
id
)))
input_link_handle
(
handle
);
#ifdef CONFIG_HOTPLUG
input_call_hotplug
(
"add"
,
dev
);
...
...
@@ -507,9 +508,10 @@ void input_register_handler(struct input_handler *handler)
list_add_tail
(
&
handler
->
node
,
&
input_handler_list
);
list_for_each_entry
(
dev
,
&
input_dev_list
,
node
)
if
((
id
=
input_match_device
(
handler
->
id_table
,
dev
)))
if
((
handle
=
handler
->
connect
(
handler
,
dev
,
id
)))
input_link_handle
(
handle
);
if
(
!
handler
->
blacklist
||
!
input_match_device
(
handler
->
blacklist
,
dev
))
if
((
id
=
input_match_device
(
handler
->
id_table
,
dev
)))
if
((
handle
=
handler
->
connect
(
handler
,
dev
,
id
)))
input_link_handle
(
handle
);
#ifdef CONFIG_PROC_FS
input_devices_state
++
;
...
...
drivers/input/joydev.c
View file @
361d16e2
...
...
@@ -380,10 +380,6 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
struct
joydev
*
joydev
;
int
i
,
j
,
t
,
minor
;
/* Avoid tablets */
if
(
test_bit
(
EV_KEY
,
dev
->
evbit
)
&&
test_bit
(
BTN_TOUCH
,
dev
->
keybit
))
return
NULL
;
for
(
minor
=
0
;
minor
<
JOYDEV_MINORS
&&
joydev_table
[
minor
];
minor
++
);
if
(
minor
==
JOYDEV_MINORS
)
{
printk
(
KERN_ERR
"joydev: no more free joydev devices
\n
"
);
...
...
@@ -464,6 +460,15 @@ static void joydev_disconnect(struct input_handle *handle)
joydev_free
(
joydev
);
}
static
struct
input_device_id
joydev_blacklist
[]
=
{
{
.
flags
=
INPUT_DEVICE_ID_MATCH_EVBIT
|
INPUT_DEVICE_ID_MATCH_KEYBIT
,
.
evbit
=
{
BIT
(
EV_KEY
)
},
.
keybit
=
{
[
LONG
(
BTN_TOUCH
)]
=
BIT
(
BTN_TOUCH
)
},
},
/* Avoid itouchpads, touchscreens and tablets */
{
},
/* Terminating entry */
};
static
struct
input_device_id
joydev_ids
[]
=
{
{
.
flags
=
INPUT_DEVICE_ID_MATCH_EVBIT
|
INPUT_DEVICE_ID_MATCH_ABSBIT
,
...
...
@@ -493,6 +498,7 @@ static struct input_handler joydev_handler = {
.
minor
=
JOYDEV_MINOR_BASE
,
.
name
=
"joydev"
,
.
id_table
=
joydev_ids
,
.
blacklist
=
joydev_blacklist
,
};
static
int
__init
joydev_init
(
void
)
...
...
drivers/input/keyboard/atkbd.c
View file @
361d16e2
...
...
@@ -48,33 +48,30 @@ static int atkbd_softrepeat;
*/
static
unsigned
char
atkbd_set2_keycode
[
512
]
=
{
0
,
67
,
65
,
63
,
61
,
59
,
60
,
88
,
0
,
68
,
66
,
64
,
62
,
15
,
41
,
85
,
0
,
56
,
42
,
182
,
29
,
16
,
2
,
89
,
0
,
0
,
44
,
31
,
30
,
17
,
3
,
90
,
0
,
46
,
45
,
32
,
18
,
5
,
4
,
91
,
90
,
57
,
47
,
33
,
20
,
19
,
6
,
0
,
91
,
49
,
48
,
35
,
34
,
21
,
7
,
0
,
0
,
0
,
50
,
36
,
22
,
8
,
9
,
0
,
0
,
67
,
65
,
63
,
61
,
59
,
60
,
88
,
0
,
68
,
66
,
64
,
62
,
15
,
41
,
117
,
0
,
56
,
42
,
182
,
29
,
16
,
2
,
0
,
0
,
0
,
44
,
31
,
30
,
17
,
3
,
0
,
0
,
46
,
45
,
32
,
18
,
5
,
4
,
186
,
0
,
57
,
47
,
33
,
20
,
19
,
6
,
85
,
0
,
49
,
48
,
35
,
34
,
21
,
7
,
89
,
0
,
0
,
50
,
36
,
22
,
8
,
9
,
90
,
0
,
51
,
37
,
23
,
24
,
11
,
10
,
0
,
0
,
52
,
53
,
38
,
39
,
25
,
12
,
0
,
122
,
89
,
40
,
120
,
26
,
13
,
0
,
0
,
58
,
54
,
28
,
27
,
0
,
43
,
0
,
0
,
85
,
86
,
90
,
91
,
92
,
93
,
14
,
94
,
95
,
79
,
183
,
75
,
71
,
121
,
0
,
123
,
0
,
181
,
40
,
0
,
26
,
13
,
0
,
0
,
58
,
54
,
28
,
27
,
0
,
43
,
0
,
194
,
0
,
86
,
193
,
192
,
184
,
0
,
14
,
185
,
0
,
79
,
182
,
75
,
71
,
124
,
0
,
0
,
82
,
83
,
80
,
76
,
77
,
72
,
1
,
69
,
87
,
78
,
81
,
74
,
55
,
73
,
70
,
99
,
0
,
0
,
0
,
65
,
99
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
25
5
,
0
,
0
,
92
,
90
,
85
,
0
,
137
,
0
,
0
,
0
,
0
,
91
,
89
,
144
,
115
,
0
,
217
,
100
,
255
,
0
,
97
,
165
,
164
,
0
,
156
,
0
,
0
,
140
,
115
,
0
,
0
,
125
,
1
73
,
114
,
0
,
113
,
152
,
163
,
151
,
126
,
128
,
166
,
0
,
140
,
0
,
147
,
0
,
127
,
159
,
167
,
115
,
160
,
164
,
0
,
0
,
116
,
158
,
0
,
150
,
166
,
0
,
0
,
0
,
142
,
157
,
0
,
114
,
166
,
168
,
0
,
0
,
213
,
155
,
0
,
98
,
113
,
0
,
163
,
0
,
138
,
226
,
0
,
0
,
0
,
0
,
0
,
153
,
140
,
0
,
255
,
96
,
0
,
0
,
0
,
143
,
0
,
133
,
0
,
116
,
0
,
143
,
0
,
174
,
133
,
0
,
107
,
0
,
105
,
102
,
0
,
0
,
112
,
110
,
111
,
108
,
112
,
106
,
103
,
0
,
119
,
0
,
118
,
109
,
0
,
99
,
104
,
119
217
,
100
,
255
,
0
,
97
,
165
,
0
,
0
,
156
,
0
,
0
,
0
,
0
,
0
,
0
,
12
5
,
173
,
114
,
0
,
113
,
0
,
0
,
0
,
126
,
128
,
0
,
0
,
140
,
0
,
0
,
0
,
127
,
159
,
0
,
115
,
0
,
164
,
0
,
0
,
116
,
158
,
0
,
150
,
166
,
0
,
0
,
0
,
142
,
1
57
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
155
,
0
,
98
,
0
,
0
,
163
,
0
,
0
,
226
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
255
,
96
,
0
,
0
,
0
,
143
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
107
,
0
,
105
,
102
,
0
,
0
,
112
,
110
,
111
,
108
,
112
,
106
,
103
,
0
,
119
,
0
,
118
,
109
,
0
,
99
,
104
,
119
,
0
,
0
,
0
,
0
,
65
,
99
,
};
static
unsigned
char
atkbd_set3_keycode
[
512
]
=
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
59
,
1
,
138
,
128
,
129
,
130
,
15
,
41
,
60
,
131
,
29
,
42
,
86
,
58
,
16
,
2
,
61
,
133
,
56
,
44
,
31
,
30
,
17
,
3
,
62
,
134
,
46
,
45
,
32
,
18
,
5
,
4
,
63
,
135
,
57
,
47
,
33
,
20
,
19
,
6
,
64
,
...
...
@@ -83,25 +80,21 @@ static unsigned char atkbd_set3_keycode[512] = {
113
,
114
,
40
,
84
,
26
,
13
,
87
,
99
,
97
,
54
,
28
,
27
,
43
,
84
,
88
,
70
,
108
,
105
,
119
,
103
,
111
,
107
,
14
,
110
,
0
,
79
,
106
,
75
,
71
,
109
,
102
,
104
,
82
,
83
,
80
,
76
,
77
,
72
,
69
,
98
,
0
,
96
,
81
,
0
,
78
,
73
,
55
,
85
,
89
,
90
,
91
,
92
,
74
,
185
,
184
,
182
,
0
,
0
,
0
,
125
,
126
,
127
,
112
,
0
,
0
,
139
,
150
,
163
,
165
,
115
,
152
,
150
,
166
,
140
,
160
,
154
,
113
,
114
,
167
,
168
,
148
,
149
,
147
,
140
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
255
148
,
149
,
147
,
140
};
static
unsigned
char
atkbd_unxlate_table
[
128
]
=
{
0
,
118
,
22
,
30
,
38
,
37
,
46
,
54
,
61
,
62
,
70
,
69
,
78
,
85
,
102
,
13
,
21
,
29
,
36
,
45
,
44
,
53
,
60
,
67
,
68
,
77
,
84
,
91
,
90
,
20
,
28
,
27
,
35
,
43
,
52
,
51
,
59
,
66
,
75
,
76
,
82
,
14
,
18
,
93
,
26
,
34
,
33
,
42
,
50
,
49
,
58
,
65
,
73
,
74
,
89
,
124
,
17
,
41
,
88
,
5
,
6
,
4
,
12
,
3
,
11
,
2
,
10
,
1
,
9
,
119
,
126
,
108
,
117
,
125
,
123
,
107
,
115
,
116
,
121
,
105
,
114
,
122
,
112
,
113
,
127
,
96
,
97
,
120
,
7
,
15
,
23
,
31
,
39
,
47
,
55
,
63
,
71
,
79
,
86
,
94
,
8
,
16
,
24
,
32
,
40
,
48
,
56
,
64
,
72
,
80
,
87
,
111
,
19
,
25
,
57
,
81
,
83
,
92
,
95
,
98
,
99
,
100
,
101
,
103
,
104
,
106
,
109
,
110
0
,
118
,
22
,
30
,
38
,
37
,
46
,
54
,
61
,
62
,
70
,
69
,
78
,
85
,
102
,
13
,
21
,
29
,
36
,
45
,
44
,
53
,
60
,
67
,
68
,
77
,
84
,
91
,
90
,
20
,
28
,
27
,
35
,
43
,
52
,
51
,
59
,
66
,
75
,
76
,
82
,
14
,
18
,
93
,
26
,
34
,
33
,
42
,
50
,
49
,
58
,
65
,
73
,
74
,
89
,
124
,
17
,
41
,
88
,
5
,
6
,
4
,
12
,
3
,
11
,
2
,
10
,
1
,
9
,
119
,
126
,
108
,
117
,
125
,
123
,
107
,
115
,
116
,
121
,
105
,
114
,
122
,
112
,
113
,
127
,
96
,
97
,
120
,
7
,
15
,
23
,
31
,
39
,
47
,
55
,
63
,
71
,
79
,
86
,
94
,
8
,
16
,
24
,
32
,
40
,
48
,
56
,
64
,
72
,
80
,
87
,
111
,
19
,
25
,
57
,
81
,
83
,
92
,
95
,
98
,
99
,
100
,
101
,
103
,
104
,
106
,
109
,
110
};
#define ATKBD_CMD_SETLEDS 0x10ed
...
...
@@ -125,6 +118,9 @@ static unsigned char atkbd_unxlate_table[128] = {
#define ATKBD_RET_EMULX 0x80
#define ATKBD_RET_EMUL1 0xe1
#define ATKBD_RET_RELEASE 0xf0
#define ATKBD_RET_HANGUEL 0xf1
#define ATKBD_RET_HANJA 0xf2
#define ATKBD_RET_ERR 0xff
#define ATKBD_KEY_UNKNOWN 0
#define ATKBD_KEY_NULL 255
...
...
@@ -156,6 +152,17 @@ struct atkbd {
unsigned
long
time
;
};
static
void
atkbd_report_key
(
struct
input_dev
*
dev
,
struct
pt_regs
*
regs
,
int
code
,
int
value
)
{
input_regs
(
dev
,
regs
);
if
(
value
==
3
)
{
input_report_key
(
dev
,
code
,
1
);
input_report_key
(
dev
,
code
,
0
);
}
else
input_event
(
dev
,
EV_KEY
,
code
,
value
);
input_sync
(
dev
);
}
/*
* atkbd_interrupt(). Here takes place processing of data received from
* the keyboard into events.
...
...
@@ -184,47 +191,37 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
atkbd
->
resend
=
0
;
#endif
switch
(
code
)
{
case
ATKBD_RET_ACK
:
atkbd
->
ack
=
1
;
goto
out
;
case
ATKBD_RET_NAK
:
atkbd
->
ack
=
-
1
;
goto
out
;
}
if
(
atkbd
->
translated
)
do
{
if
(
atkbd
->
emul
!=
1
)
{
if
(
code
==
ATKBD_RET_EMUL0
||
code
==
ATKBD_RET_EMUL1
)
break
;
if
(
code
==
ATKBD_RET_BAT
)
{
if
(
!
atkbd
->
bat_xl
)
break
;
atkbd
->
bat_xl
=
0
;
}
if
(
code
==
(
ATKBD_RET_BAT
&
0x7f
))
atkbd
->
bat_xl
=
1
;
if
(
!
atkbd
->
ack
)
switch
(
code
)
{
case
ATKBD_RET_ACK
:
atkbd
->
ack
=
1
;
goto
out
;
case
ATKBD_RET_NAK
:
atkbd
->
ack
=
-
1
;
goto
out
;
}
if
(
code
<
0x80
)
{
code
=
atkbd_unxlate_table
[
code
];
break
;
}
if
(
atkbd
->
cmdcnt
)
break
;
code
=
atkbd_unxlate_table
[
code
&
0x7f
];
atkbd
->
release
=
1
;
}
while
(
0
);
if
(
atkbd
->
cmdcnt
)
{
atkbd
->
cmdbuf
[
--
atkbd
->
cmdcnt
]
=
code
;
goto
out
;
}
if
(
atkbd
->
translated
)
{
if
(
atkbd
->
emul
||
!
(
code
==
ATKBD_RET_EMUL0
||
code
==
ATKBD_RET_EMUL1
||
code
==
ATKBD_RET_HANGUEL
||
code
==
ATKBD_RET_HANJA
||
code
==
ATKBD_RET_ERR
||
(
code
==
ATKBD_RET_BAT
&&
!
atkbd
->
bat_xl
)))
{
atkbd
->
release
=
code
>>
7
;
code
&=
0x7f
;
}
if
(
!
atkbd
->
emul
&&
(
code
&
0x7f
)
==
(
ATKBD_RET_BAT
&
0x7f
))
atkbd
->
bat_xl
=
!
atkbd
->
release
;
}
switch
(
code
)
{
case
ATKBD_RET_BAT
:
serio_rescan
(
atkbd
->
serio
);
...
...
@@ -238,22 +235,33 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
case
ATKBD_RET_RELEASE
:
atkbd
->
release
=
1
;
goto
out
;
case
ATKBD_RET_HANGUEL
:
atkbd_report_key
(
&
atkbd
->
dev
,
regs
,
KEY_LANG1
,
3
);
goto
out
;
case
ATKBD_RET_HANJA
:
atkbd_report_key
(
&
atkbd
->
dev
,
regs
,
KEY_LANG2
,
3
);
goto
out
;
case
ATKBD_RET_ERR
:
printk
(
KERN_WARNING
"atkbd.c: Keyboard on %s reports too many keys pressed.
\n
"
,
serio
->
phys
);
goto
out
;
}
if
(
atkbd
->
set
!=
3
)
code
=
(
code
&
0x7f
)
|
((
code
&
0x80
)
<<
1
);
if
(
atkbd
->
emul
)
{
if
(
--
atkbd
->
emul
)
goto
out
;
code
|=
0x100
;
code
|=
(
atkbd
->
set
!=
3
)
?
0x80
:
0x100
;
}
switch
(
atkbd
->
keycode
[
code
])
{
case
ATKBD_KEY_NULL
:
break
;
case
ATKBD_KEY_UNKNOWN
:
printk
(
KERN_WARNING
"atkbd.c: Unknown key %s (%s set %d, code %#x
, data %#x,
on %s).
\n
"
,
printk
(
KERN_WARNING
"atkbd.c: Unknown key %s (%s set %d, code %#x on %s).
\n
"
,
atkbd
->
release
?
"released"
:
"pressed"
,
atkbd
->
translated
?
"translated"
:
"raw"
,
atkbd
->
set
,
code
,
data
,
serio
->
phys
);
atkbd
->
set
,
code
,
serio
->
phys
);
break
;
default:
value
=
atkbd
->
release
?
0
:
...
...
@@ -273,9 +281,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
break
;
}
input_regs
(
&
atkbd
->
dev
,
regs
);
input_event
(
&
atkbd
->
dev
,
EV_KEY
,
atkbd
->
keycode
[
code
],
value
);
input_sync
(
&
atkbd
->
dev
);
atkbd_report_key
(
&
atkbd
->
dev
,
regs
,
atkbd
->
keycode
[
code
],
value
);
}
atkbd
->
release
=
0
;
...
...
@@ -369,10 +375,11 @@ static int atkbd_command(struct atkbd *atkbd, unsigned char *param, int command)
static
int
atkbd_event
(
struct
input_dev
*
dev
,
unsigned
int
type
,
unsigned
int
code
,
int
value
)
{
struct
atkbd
*
atkbd
=
dev
->
private
;
struct
{
int
p
;
u8
v
;
}
period
[]
=
{
{
30
,
0x00
},
{
25
,
0x02
},
{
20
,
0x04
},
{
15
,
0x08
},
{
10
,
0x0c
},
{
7
,
0x10
},
{
5
,
0x14
},
{
0
,
0x14
}
};
struct
{
int
d
;
u8
v
;
}
delay
[]
=
{
{
1000
,
0x60
},
{
750
,
0x40
},
{
500
,
0x20
},
{
250
,
0x00
},
{
0
,
0x00
}
};
const
short
period
[
32
]
=
{
33
,
37
,
42
,
46
,
50
,
54
,
58
,
63
,
67
,
75
,
83
,
92
,
100
,
109
,
116
,
125
,
133
,
149
,
167
,
182
,
200
,
217
,
232
,
250
,
270
,
303
,
333
,
370
,
400
,
435
,
470
,
500
};
const
short
delay
[
4
]
=
{
250
,
500
,
750
,
1000
};
char
param
[
2
];
int
i
,
j
;
...
...
@@ -406,11 +413,11 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
if
(
atkbd_softrepeat
)
return
0
;
i
=
j
=
0
;
while
(
period
[
i
].
p
>
dev
->
rep
[
REP_PERIOD
])
i
++
;
while
(
delay
[
j
].
d
>
dev
->
rep
[
REP_DELAY
])
j
++
;
dev
->
rep
[
REP_PERIOD
]
=
period
[
i
]
.
p
;
dev
->
rep
[
REP_DELAY
]
=
delay
[
j
]
.
d
;
param
[
0
]
=
period
[
i
].
v
|
delay
[
j
].
v
;
while
(
i
<
32
&&
period
[
i
]
<
dev
->
rep
[
REP_PERIOD
])
i
++
;
while
(
j
<
4
&&
delay
[
j
]
<
dev
->
rep
[
REP_DELAY
])
j
++
;
dev
->
rep
[
REP_PERIOD
]
=
period
[
i
];
dev
->
rep
[
REP_DELAY
]
=
delay
[
j
];
param
[
0
]
=
i
|
(
j
<<
5
)
;
atkbd_command
(
atkbd
,
param
,
ATKBD_CMD_SETREP
);
return
0
;
...
...
@@ -623,6 +630,7 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
atkbd
->
dev
.
rep
[
REP_PERIOD
]
=
33
;
}
atkbd
->
ack
=
1
;
atkbd
->
serio
=
serio
;
init_input_dev
(
&
atkbd
->
dev
);
...
...
@@ -665,16 +673,22 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
sprintf
(
atkbd
->
phys
,
"%s/input0"
,
serio
->
phys
);
if
(
atkbd
->
set
==
3
)
memcpy
(
atkbd
->
keycode
,
atkbd_set3_keycode
,
sizeof
(
atkbd
->
keycode
));
else
if
(
atkbd
->
translated
)
{
for
(
i
=
0
;
i
<
128
;
i
++
)
{
atkbd
->
keycode
[
i
]
=
atkbd_set2_keycode
[
atkbd_unxlate_table
[
i
]];
atkbd
->
keycode
[
i
|
0x80
]
=
atkbd_set2_keycode
[
atkbd_unxlate_table
[
i
]
|
0x80
];
}
}
else
if
(
atkbd
->
set
==
2
)
{
memcpy
(
atkbd
->
keycode
,
atkbd_set2_keycode
,
sizeof
(
atkbd
->
keycode
));
}
else
{
memcpy
(
atkbd
->
keycode
,
atkbd_set3_keycode
,
sizeof
(
atkbd
->
keycode
));
}
atkbd
->
dev
.
name
=
atkbd
->
name
;
atkbd
->
dev
.
phys
=
atkbd
->
phys
;
atkbd
->
dev
.
id
.
bustype
=
BUS_I8042
;
atkbd
->
dev
.
id
.
vendor
=
0x0001
;
atkbd
->
dev
.
id
.
product
=
atkbd
->
set
;
atkbd
->
dev
.
id
.
product
=
atkbd
->
translated
?
1
:
atkbd
->
set
;
atkbd
->
dev
.
id
.
version
=
atkbd
->
id
;
for
(
i
=
0
;
i
<
512
;
i
++
)
...
...
@@ -686,10 +700,62 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
printk
(
KERN_INFO
"input: %s on %s
\n
"
,
atkbd
->
name
,
serio
->
phys
);
}
/*
* atkbd_reconnect() tries to restore keyboard into a sane state and is
* most likely called on resume.
*/
static
int
atkbd_reconnect
(
struct
serio
*
serio
)
{
struct
atkbd
*
atkbd
=
serio
->
private
;
struct
serio_dev
*
dev
=
serio
->
dev
;
int
i
;
if
(
!
dev
)
{
printk
(
KERN_DEBUG
"atkbd: reconnect request, but serio is disconnected, ignoring...
\n
"
);
return
-
1
;
}
if
(
atkbd
->
write
)
{
if
(
atkbd_probe
(
atkbd
))
return
-
1
;
atkbd
->
set
=
atkbd_set_3
(
atkbd
);
atkbd_enable
(
atkbd
);
}
else
{
atkbd
->
set
=
2
;
atkbd
->
id
=
0xab00
;
}
/*
* Here we probably should check if the keyboard has the same set that
* it had before and bail out if it's different. But this will most likely
* cause new keyboard device be created... and for the user it will look
* like keyboard is lost
*/
if
(
atkbd
->
translated
)
{
for
(
i
=
0
;
i
<
128
;
i
++
)
{
atkbd
->
keycode
[
i
]
=
atkbd_set2_keycode
[
atkbd_unxlate_table
[
i
]];
atkbd
->
keycode
[
i
|
0x80
]
=
atkbd_set2_keycode
[
atkbd_unxlate_table
[
i
]
|
0x80
];
}
}
else
if
(
atkbd
->
set
==
2
)
{
memcpy
(
atkbd
->
keycode
,
atkbd_set2_keycode
,
sizeof
(
atkbd
->
keycode
));
}
else
{
memcpy
(
atkbd
->
keycode
,
atkbd_set3_keycode
,
sizeof
(
atkbd
->
keycode
));
}
for
(
i
=
0
;
i
<
512
;
i
++
)
if
(
atkbd
->
keycode
[
i
]
&&
atkbd
->
keycode
[
i
]
<
255
)
set_bit
(
atkbd
->
keycode
[
i
],
atkbd
->
dev
.
keybit
);
return
0
;
}
static
struct
serio_dev
atkbd_dev
=
{
.
interrupt
=
atkbd_interrupt
,
.
connect
=
atkbd_connect
,
.
reconnect
=
atkbd_reconnect
,
.
disconnect
=
atkbd_disconnect
,
.
cleanup
=
atkbd_cleanup
,
};
...
...
@@ -709,9 +775,17 @@ static int __init atkbd_setup_reset(char *str)
if
(
ints
[
0
]
>
0
)
atkbd_reset
=
ints
[
1
];
return
1
;
}
static
int
__init
atkbd_setup_softrepeat
(
char
*
str
)
{
int
ints
[
4
];
str
=
get_options
(
str
,
ARRAY_SIZE
(
ints
),
ints
);
if
(
ints
[
0
]
>
0
)
atkbd_softrepeat
=
ints
[
1
];
return
1
;
}
__setup
(
"atkbd_set="
,
atkbd_setup_set
);
__setup
(
"atkbd_reset"
,
atkbd_setup_reset
);
__setup
(
"atkbd_softrepeat="
,
atkbd_setup_softrepeat
);
#endif
int
__init
atkbd_init
(
void
)
...
...
drivers/input/mouse/Kconfig
View file @
361d16e2
...
...
@@ -23,27 +23,18 @@ config MOUSE_PS2
mice with wheels and extra buttons, Microsoft, Logitech or Genius
compatible.
Synaptics TouchPad users might be interested in a specialized
XFree86 driver at:
http://w1.894.telia.com/~u89404340/touchpad/index.html
and a new verion of GPM at:
http://www.geocities.com/dt_or/gpm/gpm.html
to take advantage of the advanced features of the touchpad.
If unsure, say Y.
To compile this driver as a module, choose M here: the
module will be called psmouse.
config MOUSE_PS2_SYNAPTICS
bool "Synaptics TouchPad"
default n
depends on INPUT && INPUT_MOUSE && MOUSE_PS2
---help---
Say Y here if you have a Synaptics TouchPad connected to your system.
This touchpad is found on many modern laptop computers.
Note that you also need a user space driver to interpret the data
generated by the kernel. A compatible driver for XFree86 is available
from http://w1.894.telia.com/~u89404340/touchpad/index.html
The gpm program is not yet able to interpret the data from this
driver, so if you need to use the touchpad in the console, you have to
say N for now.
config MOUSE_SERIAL
tristate "Serial mouse"
depends on INPUT && INPUT_MOUSE
...
...
drivers/input/mouse/logips2pp.c
View file @
361d16e2
...
...
@@ -10,6 +10,7 @@
*/
#include <linux/input.h>
#include <linux/serio.h>
#include "psmouse.h"
#include "logips2pp.h"
...
...
@@ -142,7 +143,7 @@ void ps2pp_set_800dpi(struct psmouse *psmouse)
* touchpad.
*/
int
ps2pp_detect_model
(
struct
psmouse
*
psmouse
,
unsigned
char
*
param
)
static
int
ps2pp_detect_model
(
struct
psmouse
*
psmouse
,
unsigned
char
*
param
)
{
int
i
;
static
int
logitech_4btn
[]
=
{
12
,
40
,
41
,
42
,
43
,
52
,
73
,
80
,
-
1
};
...
...
@@ -226,3 +227,22 @@ int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param)
return
0
;
}
/*
* Logitech magic init.
*/
int
ps2pp_detect
(
struct
psmouse
*
psmouse
)
{
unsigned
char
param
[
4
];
param
[
0
]
=
0
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
param
[
1
]
=
0
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETINFO
);
return
param
[
1
]
!=
0
?
ps2pp_detect_model
(
psmouse
,
param
)
:
0
;
}
drivers/input/mouse/logips2pp.h
View file @
361d16e2
...
...
@@ -13,5 +13,5 @@
struct
psmouse
;
void
ps2pp_process_packet
(
struct
psmouse
*
psmouse
);
void
ps2pp_set_800dpi
(
struct
psmouse
*
psmouse
);
int
ps2pp_detect
_model
(
struct
psmouse
*
psmouse
,
unsigned
char
*
param
);
int
ps2pp_detect
(
struct
psmouse
*
psmouse
);
#endif
drivers/input/mouse/psmouse-base.c
View file @
361d16e2
...
...
@@ -12,35 +12,44 @@
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/init.h>
#include <linux/pm.h>
#include "psmouse.h"
#include "synaptics.h"
#include "logips2pp.h"
MODULE_AUTHOR
(
"Vojtech Pavlik <vojtech@suse.cz>"
);
MODULE_DESCRIPTION
(
"PS/2 mouse driver"
);
MODULE_PARM
(
psmouse_noext
,
"1i"
);
MODULE_PARM_DESC
(
psmouse_noext
,
"Disable any protocol extensions. Useful for KVM switches."
);
MODULE_PARM
(
psmouse_resolution
,
"i"
);
MODULE_PARM_DESC
(
psmouse_resolution
,
"Resolution, in dpi."
);
MODULE_PARM
(
psmouse_rate
,
"i"
);
MODULE_PARM_DESC
(
psmouse_rate
,
"Report rate, in reports per second."
);
MODULE_PARM
(
psmouse_smartscroll
,
"i"
);
MODULE_PARM_DESC
(
psmouse_smartscroll
,
"Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."
);
MODULE_PARM
(
psmouse_resetafter
,
"i"
);
MODULE_PARM_DESC
(
psmouse_resetafter
,
"Reset Synaptics Touchpad after so many bad packets (0 = never)."
);
MODULE_LICENSE
(
"GPL"
);
static
int
psmouse_noext
;
module_param
(
psmouse_noext
,
int
,
0
);
MODULE_PARM_DESC
(
psmouse_noext
,
"[DEPRECATED] Disable any protocol extensions. Useful for KVM switches."
);
static
char
*
psmouse_proto
;
static
unsigned
int
psmouse_max_proto
=
-
1UL
;
module_param
(
psmouse_proto
,
charp
,
0
);
MODULE_PARM_DESC
(
psmouse_proto
,
"Highest protocol extension to probe (bare, imps, exps). Useful for KVM switches."
);
int
psmouse_resolution
=
200
;
module_param
(
psmouse_resolution
,
uint
,
0
);
MODULE_PARM_DESC
(
psmouse_resolution
,
"Resolution, in dpi."
);
unsigned
int
psmouse_rate
=
100
;
module_param
(
psmouse_rate
,
uint
,
0
);
MODULE_PARM_DESC
(
psmouse_rate
,
"Report rate, in reports per second."
);
int
psmouse_smartscroll
=
1
;
module_param
(
psmouse_smartscroll
,
bool
,
0
);
MODULE_PARM_DESC
(
psmouse_smartscroll
,
"Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."
);
unsigned
int
psmouse_resetafter
;
module_param
(
psmouse_resetafter
,
uint
,
0
);
MODULE_PARM_DESC
(
psmouse_resetafter
,
"Reset Synaptics Touchpad after so many bad packets (0 = never)."
);
static
char
*
psmouse_protocols
[]
=
{
"None"
,
"PS/2"
,
"PS2++"
,
"PS2T++"
,
"GenPS/2"
,
"ImPS/2"
,
"ImExPS/2"
,
"SynPS/2"
};
...
...
@@ -139,7 +148,8 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
goto
out
;
}
if
(
psmouse
->
pktcnt
&&
time_after
(
jiffies
,
psmouse
->
last
+
HZ
/
2
))
{
if
(
psmouse
->
state
==
PSMOUSE_ACTIVATED
&&
psmouse
->
pktcnt
&&
time_after
(
jiffies
,
psmouse
->
last
+
HZ
/
2
))
{
printk
(
KERN_WARNING
"psmouse.c: %s at %s lost synchronization, throwing %d bytes away.
\n
"
,
psmouse
->
name
,
psmouse
->
phys
,
psmouse
->
pktcnt
);
psmouse
->
pktcnt
=
0
;
...
...
@@ -256,6 +266,59 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
return
0
;
}
/*
* Genius NetMouse magic init.
*/
static
int
genius_detect
(
struct
psmouse
*
psmouse
)
{
unsigned
char
param
[
4
];
param
[
0
]
=
3
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETINFO
);
return
param
[
0
]
==
0x00
&&
param
[
1
]
==
0x33
&&
param
[
2
]
==
0x55
;
}
/*
* IntelliMouse magic init.
*/
static
int
intellimouse_detect
(
struct
psmouse
*
psmouse
)
{
unsigned
char
param
[
2
];
param
[
0
]
=
200
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
param
[
0
]
=
100
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
param
[
0
]
=
80
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETID
);
return
param
[
0
]
==
3
;
}
/*
* Try IntelliMouse/Explorer magic init.
*/
static
int
im_explorer_detect
(
struct
psmouse
*
psmouse
)
{
unsigned
char
param
[
2
];
param
[
0
]
=
200
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
param
[
0
]
=
200
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
param
[
0
]
=
80
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETID
);
return
param
[
0
]
==
4
;
}
/*
* psmouse_extensions() probes for any extensions to the basic PS/2 protocol
* the mouse may have.
...
...
@@ -263,49 +326,33 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
static
int
psmouse_extensions
(
struct
psmouse
*
psmouse
)
{
unsigned
char
param
[
4
]
;
int
synaptics_hardware
=
0
;
param
[
0
]
=
0
;
psmouse
->
vendor
=
"Generic"
;
psmouse
->
name
=
"Mouse"
;
psmouse
->
model
=
0
;
if
(
psmouse_noext
)
return
PSMOUSE_PS2
;
/*
* Try Synaptics TouchPad
magic ID
* Try Synaptics TouchPad
*/
param
[
0
]
=
0
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETINFO
);
if
(
param
[
1
]
==
0x47
)
{
if
(
psmouse_max_proto
>
PSMOUSE_PS2
&&
synaptics_detect
(
psmouse
))
{
synaptics_hardware
=
1
;
psmouse
->
vendor
=
"Synaptics"
;
psmouse
->
name
=
"TouchPad"
;
if
(
!
synaptics_init
(
psmouse
))
return
PSMOUSE_SYNAPTICS
;
else
return
PSMOUSE_PS2
;
}
if
(
psmouse_max_proto
>
PSMOUSE_IMEX
)
{
if
(
synaptics_init
(
psmouse
)
==
0
)
return
PSMOUSE_SYNAPTICS
;
/*
* Try Genius NetMouse magic init.
* Some Synaptics touchpads can emulate extended protocols (like IMPS/2).
* Unfortunately Logitech/Genius probes confuse some firmware versions so
* we'll have to skip them.
*/
psmouse_max_proto
=
PSMOUSE_IMEX
;
}
}
param
[
0
]
=
3
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETINFO
);
if
(
param
[
0
]
==
0x00
&&
param
[
1
]
==
0x33
&&
param
[
2
]
==
0x55
)
{
if
(
psmouse_max_proto
>
PSMOUSE_IMEX
&&
genius_detect
(
psmouse
))
{
set_bit
(
BTN_EXTRA
,
psmouse
->
dev
.
keybit
);
set_bit
(
BTN_SIDE
,
psmouse
->
dev
.
keybit
);
set_bit
(
REL_WHEEL
,
psmouse
->
dev
.
relbit
);
...
...
@@ -315,54 +362,17 @@ static int psmouse_extensions(struct psmouse *psmouse)
return
PSMOUSE_GENPS
;
}
/*
* Try Logitech magic ID.
*/
param
[
0
]
=
0
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
param
[
1
]
=
0
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETINFO
);
if
(
param
[
1
])
{
int
type
=
ps2pp_detect_model
(
psmouse
,
param
);
if
(
psmouse_max_proto
>
PSMOUSE_IMEX
)
{
int
type
=
ps2pp_detect
(
psmouse
);
if
(
type
)
return
type
;
}
/*
* Try IntelliMouse magic init.
*/
param
[
0
]
=
200
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
param
[
0
]
=
100
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
param
[
0
]
=
80
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETID
);
if
(
param
[
0
]
==
3
)
{
if
(
psmouse_max_proto
>=
PSMOUSE_IMPS
&&
intellimouse_detect
(
psmouse
))
{
set_bit
(
REL_WHEEL
,
psmouse
->
dev
.
relbit
);
/*
* Try IntelliMouse/Explorer magic init.
*/
param
[
0
]
=
200
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
param
[
0
]
=
200
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
param
[
0
]
=
80
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRATE
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETID
);
if
(
param
[
0
]
==
4
)
{
if
(
psmouse_max_proto
>=
PSMOUSE_IMEX
&&
im_explorer_detect
(
psmouse
))
{
set_bit
(
BTN_SIDE
,
psmouse
->
dev
.
keybit
);
set_bit
(
BTN_EXTRA
,
psmouse
->
dev
.
keybit
);
...
...
@@ -378,6 +388,15 @@ static int psmouse_extensions(struct psmouse *psmouse)
* Okay, all failed, we have a standard mouse here. The number of the buttons
* is still a question, though. We assume 3.
*/
if
(
synaptics_hardware
)
{
/*
* We detected Synaptics hardware but it did not respond to IMPS/2 probes.
* We need to reset the touchpad because if there is a track point on the
* pass through port it could get disabled while probing for protocol
* extensions.
*/
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_RESET_DIS
);
}
return
PSMOUSE_PS2
;
}
...
...
@@ -468,7 +487,7 @@ static void psmouse_initialize(struct psmouse *psmouse)
* We set the mouse report rate, resolution and scaling.
*/
if
(
!
psmouse_noext
)
{
if
(
psmouse_max_proto
!=
PSMOUSE_PS2
)
{
psmouse_set_rate
(
psmouse
);
psmouse_set_resolution
(
psmouse
);
psmouse_command
(
psmouse
,
NULL
,
PSMOUSE_CMD_SETSCALE11
);
...
...
@@ -513,45 +532,30 @@ static void psmouse_disconnect(struct serio *serio)
struct
psmouse
*
psmouse
=
serio
->
private
;
psmouse
->
state
=
PSMOUSE_IGNORE
;
synaptics_disconnect
(
psmouse
);
input_unregister_device
(
&
psmouse
->
dev
);
serio_close
(
serio
);
kfree
(
psmouse
);
}
/*
* Reinitialize mouse hardware after software suspend.
*/
static
int
psmouse_pm_callback
(
struct
pm_dev
*
dev
,
pm_request_t
request
,
void
*
data
)
{
struct
psmouse
*
psmouse
=
dev
->
data
;
struct
serio_dev
*
ser_dev
=
psmouse
->
serio
->
dev
;
synaptics_disconnect
(
psmouse
);
/* We need to reopen the serio port to reinitialize the i8042 controller */
serio_close
(
psmouse
->
serio
);
serio_open
(
psmouse
->
serio
,
ser_dev
);
if
(
psmouse
->
ptport
)
{
if
(
psmouse
->
ptport
->
deactivate
)
psmouse
->
ptport
->
deactivate
(
psmouse
);
__serio_unregister_port
(
&
psmouse
->
ptport
->
serio
);
/* we have serio_sem */
kfree
(
psmouse
->
ptport
);
psmouse
->
ptport
=
NULL
;
}
/* Probe and re-initialize the mouse */
psmouse_probe
(
psmouse
);
psmouse_initialize
(
psmouse
);
synaptics_pt_init
(
psmouse
);
psmouse_activate
(
psmouse
);
if
(
psmouse
->
disconnect
)
psmouse
->
disconnect
(
psmouse
);
return
0
;
input_unregister_device
(
&
psmouse
->
dev
);
serio_close
(
serio
);
kfree
(
psmouse
);
}
/*
* psmouse_connect() is a callback from the serio module when
* an unhandled serio port is found.
*/
static
void
psmouse_connect
(
struct
serio
*
serio
,
struct
serio_dev
*
dev
)
{
struct
psmouse
*
psmouse
;
struct
pm_dev
*
pmdev
;
if
((
serio
->
type
&
SERIO_TYPE
)
!=
SERIO_8042
&&
(
serio
->
type
&
SERIO_TYPE
)
!=
SERIO_PS_PSTHRU
)
...
...
@@ -572,7 +576,6 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
psmouse
->
dev
.
private
=
psmouse
;
serio
->
private
=
psmouse
;
if
(
serio_open
(
serio
,
dev
))
{
kfree
(
psmouse
);
return
;
...
...
@@ -584,12 +587,6 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
return
;
}
pmdev
=
pm_register
(
PM_SYS_DEV
,
PM_SYS_UNKNOWN
,
psmouse_pm_callback
);
if
(
pmdev
)
{
psmouse
->
dev
.
pm_dev
=
pmdev
;
pmdev
->
data
=
psmouse
;
}
sprintf
(
psmouse
->
devname
,
"%s %s %s"
,
psmouse_protocols
[
psmouse
->
type
],
psmouse
->
vendor
,
psmouse
->
name
);
sprintf
(
psmouse
->
phys
,
"%s/input0"
,
...
...
@@ -608,59 +605,87 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
psmouse_initialize
(
psmouse
);
synaptics_pt_init
(
psmouse
);
if
(
psmouse
->
ptport
)
{
printk
(
KERN_INFO
"serio: %s port at %s
\n
"
,
psmouse
->
ptport
->
serio
.
name
,
psmouse
->
phys
);
__serio_register_port
(
&
psmouse
->
ptport
->
serio
);
/* we have serio_sem */
if
(
psmouse
->
ptport
->
activate
)
psmouse
->
ptport
->
activate
(
psmouse
);
}
psmouse_activate
(
psmouse
);
}
static
int
psmouse_reconnect
(
struct
serio
*
serio
)
{
struct
psmouse
*
psmouse
=
serio
->
private
;
struct
serio_dev
*
dev
=
serio
->
dev
;
int
old_type
=
psmouse
->
type
;
if
(
!
dev
)
{
printk
(
KERN_DEBUG
"psmouse: reconnect request, but serio is disconnected, ignoring...
\n
"
);
return
-
1
;
}
psmouse
->
state
=
PSMOUSE_NEW_DEVICE
;
psmouse
->
type
=
psmouse
->
acking
=
psmouse
->
cmdcnt
=
psmouse
->
pktcnt
=
0
;
if
(
psmouse
->
reconnect
)
{
if
(
psmouse
->
reconnect
(
psmouse
))
return
-
1
;
}
else
if
(
psmouse_probe
(
psmouse
)
!=
old_type
)
return
-
1
;
/* ok, the device type (and capabilities) match the old one,
* we can continue using it, complete intialization
*/
psmouse
->
type
=
old_type
;
psmouse_initialize
(
psmouse
);
if
(
psmouse
->
ptport
)
{
if
(
psmouse_reconnect
(
&
psmouse
->
ptport
->
serio
))
{
__serio_unregister_port
(
&
psmouse
->
ptport
->
serio
);
__serio_register_port
(
&
psmouse
->
ptport
->
serio
);
if
(
psmouse
->
ptport
->
activate
)
psmouse
->
ptport
->
activate
(
psmouse
);
}
}
psmouse_activate
(
psmouse
);
return
0
;
}
static
struct
serio_dev
psmouse_dev
=
{
.
interrupt
=
psmouse_interrupt
,
.
connect
=
psmouse_connect
,
.
reconnect
=
psmouse_reconnect
,
.
disconnect
=
psmouse_disconnect
,
.
cleanup
=
psmouse_cleanup
,
};
#ifndef MODULE
static
int
__init
psmouse_noext_setup
(
char
*
str
)
{
psmouse_noext
=
1
;
return
1
;
}
static
int
__init
psmouse_resolution_setup
(
char
*
str
)
{
get_option
(
&
str
,
&
psmouse_resolution
);
return
1
;
}
static
int
__init
psmouse_smartscroll_setup
(
char
*
str
)
static
inline
void
psmouse_parse_proto
(
void
)
{
get_option
(
&
str
,
&
psmouse_smartscroll
);
return
1
;
}
static
int
__init
psmouse_resetafter_setup
(
char
*
str
)
{
get_option
(
&
str
,
&
psmouse_resetafter
);
return
1
;
}
if
(
psmouse_noext
)
{
printk
(
KERN_WARNING
"psmouse: 'psmouse_noext' option is deprecated, please use 'psmouse_proto'
\n
"
);
psmouse_max_proto
=
PSMOUSE_PS2
;
}
static
int
__init
psmouse_rate_setup
(
char
*
str
)
{
get_option
(
&
str
,
&
psmouse_rate
);
return
1
;
/* even is psmouse_noext is present psmouse_proto overrides it */
if
(
psmouse_proto
)
{
if
(
!
strcmp
(
psmouse_proto
,
"bare"
))
psmouse_max_proto
=
PSMOUSE_PS2
;
else
if
(
!
strcmp
(
psmouse_proto
,
"imps"
))
psmouse_max_proto
=
PSMOUSE_IMPS
;
else
if
(
!
strcmp
(
psmouse_proto
,
"exps"
))
psmouse_max_proto
=
PSMOUSE_IMEX
;
else
printk
(
KERN_ERR
"psmouse: unknown protocol type '%s'
\n
"
,
psmouse_proto
);
}
}
__setup
(
"psmouse_noext"
,
psmouse_noext_setup
);
__setup
(
"psmouse_resolution="
,
psmouse_resolution_setup
);
__setup
(
"psmouse_smartscroll="
,
psmouse_smartscroll_setup
);
__setup
(
"psmouse_resetafter="
,
psmouse_resetafter_setup
);
__setup
(
"psmouse_rate="
,
psmouse_rate_setup
);
#endif
int
__init
psmouse_init
(
void
)
{
psmouse_parse_proto
();
serio_register_device
(
&
psmouse_dev
);
return
0
;
}
...
...
drivers/input/mouse/psmouse.h
View file @
361d16e2
...
...
@@ -22,10 +22,20 @@
#define PSMOUSE_ACTIVATED 1
#define PSMOUSE_IGNORE 2
struct
psmouse
;
struct
psmouse_ptport
{
struct
serio
serio
;
void
(
*
activate
)(
struct
psmouse
*
parent
);
void
(
*
deactivate
)(
struct
psmouse
*
parent
);
};
struct
psmouse
{
void
*
private
;
struct
input_dev
dev
;
struct
serio
*
serio
;
struct
psmouse_ptport
*
ptport
;
char
*
vendor
;
char
*
name
;
unsigned
char
cmdbuf
[
8
];
...
...
@@ -41,6 +51,9 @@ struct psmouse {
char
error
;
char
devname
[
64
];
char
phys
[
32
];
int
(
*
reconnect
)(
struct
psmouse
*
psmouse
);
void
(
*
disconnect
)(
struct
psmouse
*
psmouse
);
};
#define PSMOUSE_PS2 1
...
...
drivers/input/mouse/synaptics.c
View file @
361d16e2
...
...
@@ -2,7 +2,8 @@
* Synaptics TouchPad PS/2 mouse driver
*
* 2003 Dmitry Torokhov <dtor@mail.ru>
* Added support for pass-through port
* Added support for pass-through port. Special thanks to Peter Berg Larsen
* for explaining various Synaptics quirks.
*
* 2003 Peter Osterlund <petero2@telia.com>
* Ported to 2.5 input device infrastructure.
...
...
@@ -194,9 +195,7 @@ static void print_ident(struct synaptics_data *priv)
static
int
synaptics_query_hardware
(
struct
psmouse
*
psmouse
)
{
struct
synaptics_data
*
priv
=
psmouse
->
private
;
int
retries
=
0
;
int
mode
;
while
((
retries
++
<
3
)
&&
synaptics_reset
(
psmouse
))
printk
(
KERN_ERR
"synaptics reset failed
\n
"
);
...
...
@@ -208,7 +207,14 @@ static int synaptics_query_hardware(struct psmouse *psmouse)
if
(
synaptics_capability
(
psmouse
))
return
-
1
;
mode
=
SYN_BIT_ABSOLUTE_MODE
|
SYN_BIT_HIGH_RATE
;
return
0
;
}
static
int
synaptics_set_mode
(
struct
psmouse
*
psmouse
,
int
mode
)
{
struct
synaptics_data
*
priv
=
psmouse
->
private
;
mode
|=
SYN_BIT_ABSOLUTE_MODE
|
SYN_BIT_HIGH_RATE
;
if
(
SYN_ID_MAJOR
(
priv
->
identity
)
>=
4
)
mode
|=
SYN_BIT_DISABLE_GESTURE
;
if
(
SYN_CAP_EXTENDED
(
priv
->
capabilities
))
...
...
@@ -265,49 +271,38 @@ static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet
}
}
int
synaptics_pt_init
(
struct
psmouse
*
psmouse
)
static
void
synaptics_pt_activate
(
struct
psmouse
*
psmouse
)
{
struct
synaptics_data
*
priv
=
psmouse
->
private
;
struct
serio
*
port
;
struct
psmouse
*
child
;
struct
psmouse
*
child
=
psmouse
->
ptport
->
serio
.
private
;
if
(
psmouse
->
type
!=
PSMOUSE_SYNAPTICS
)
return
-
1
;
if
(
!
SYN_CAP_EXTENDED
(
priv
->
capabilities
))
return
-
1
;
if
(
!
SYN_CAP_PASS_THROUGH
(
priv
->
capabilities
))
return
-
1
;
/* adjust the touchpad to child's choice of protocol */
if
(
child
&&
child
->
type
>=
PSMOUSE_GENPS
)
{
if
(
synaptics_set_mode
(
psmouse
,
SYN_BIT_FOUR_BYTE_CLIENT
))
printk
(
KERN_INFO
"synaptics: failed to enable 4-byte guest protocol
\n
"
);
}
}
static
void
synaptics_pt_create
(
struct
psmouse
*
psmouse
)
{
struct
psmouse_ptport
*
port
;
p
riv
->
ptport
=
port
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
p
smouse
->
ptport
=
port
=
kmalloc
(
sizeof
(
struct
psmouse_ptport
),
GFP_KERNEL
);
if
(
!
port
)
{
printk
(
KERN_ERR
"synaptics: not enough memory to allocate
serio
port
\n
"
);
return
-
1
;
printk
(
KERN_ERR
"synaptics: not enough memory to allocate
pass-through
port
\n
"
);
return
;
}
memset
(
port
,
0
,
sizeof
(
struct
serio
));
port
->
type
=
SERIO_PS_PSTHRU
;
port
->
name
=
"Synaptics pass-through"
;
port
->
phys
=
"synaptics-pt/serio0"
;
port
->
write
=
synaptics_pt_write
;
port
->
open
=
synaptics_pt_open
;
port
->
close
=
synaptics_pt_close
;
port
->
driver
=
psmouse
;
memset
(
port
,
0
,
sizeof
(
struct
psmouse_ptport
));
printk
(
KERN_INFO
"serio: %s port at %s
\n
"
,
port
->
name
,
psmouse
->
phys
);
serio_register_slave_port
(
port
);
port
->
serio
.
type
=
SERIO_PS_PSTHRU
;
port
->
serio
.
name
=
"Synaptics pass-through"
;
port
->
serio
.
phys
=
"synaptics-pt/serio0"
;
port
->
serio
.
write
=
synaptics_pt_write
;
port
->
serio
.
open
=
synaptics_pt_open
;
port
->
serio
.
close
=
synaptics_pt_close
;
port
->
serio
.
driver
=
psmouse
;
/* adjust the touchpad to child's choice of protocol */
child
=
port
->
private
;
if
(
child
&&
child
->
type
>=
PSMOUSE_GENPS
)
{
if
(
synaptics_mode_cmd
(
psmouse
,
(
SYN_BIT_ABSOLUTE_MODE
|
SYN_BIT_HIGH_RATE
|
SYN_BIT_DISABLE_GESTURE
|
SYN_BIT_FOUR_BYTE_CLIENT
|
SYN_BIT_W_MODE
)))
printk
(
KERN_INFO
"synaptics: failed to enable 4-byte guest protocol
\n
"
);
}
return
0
;
port
->
activate
=
synaptics_pt_activate
;
}
/*****************************************************************************
...
...
@@ -371,27 +366,82 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
clear_bit
(
REL_Y
,
dev
->
relbit
);
}
static
void
synaptics_disconnect
(
struct
psmouse
*
psmouse
)
{
synaptics_mode_cmd
(
psmouse
,
0
);
kfree
(
psmouse
->
private
);
}
static
int
synaptics_reconnect
(
struct
psmouse
*
psmouse
)
{
struct
synaptics_data
*
priv
=
psmouse
->
private
;
struct
synaptics_data
old_priv
=
*
priv
;
if
(
!
synaptics_detect
(
psmouse
))
return
-
1
;
if
(
synaptics_query_hardware
(
psmouse
))
{
printk
(
KERN_ERR
"Unable to query Synaptics hardware.
\n
"
);
return
-
1
;
}
if
(
old_priv
.
identity
!=
priv
->
identity
||
old_priv
.
model_id
!=
priv
->
model_id
||
old_priv
.
capabilities
!=
priv
->
capabilities
||
old_priv
.
ext_cap
!=
priv
->
ext_cap
)
return
-
1
;
if
(
synaptics_set_mode
(
psmouse
,
0
))
{
printk
(
KERN_ERR
"Unable to initialize Synaptics hardware.
\n
"
);
return
-
1
;
}
return
0
;
}
int
synaptics_detect
(
struct
psmouse
*
psmouse
)
{
unsigned
char
param
[
4
];
param
[
0
]
=
0
;
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_SETRES
);
psmouse_command
(
psmouse
,
param
,
PSMOUSE_CMD_GETINFO
);
return
param
[
1
]
==
0x47
;
}
int
synaptics_init
(
struct
psmouse
*
psmouse
)
{
struct
synaptics_data
*
priv
;
#ifndef CONFIG_MOUSE_PS2_SYNAPTICS
return
-
1
;
#endif
psmouse
->
private
=
priv
=
kmalloc
(
sizeof
(
struct
synaptics_data
),
GFP_KERNEL
);
if
(
!
priv
)
return
-
1
;
memset
(
priv
,
0
,
sizeof
(
struct
synaptics_data
));
if
(
synaptics_query_hardware
(
psmouse
))
{
printk
(
KERN_ERR
"Unable to query/initialize Synaptics hardware.
\n
"
);
printk
(
KERN_ERR
"Unable to query Synaptics hardware.
\n
"
);
goto
init_fail
;
}
if
(
synaptics_set_mode
(
psmouse
,
0
))
{
printk
(
KERN_ERR
"Unable to initialize Synaptics hardware.
\n
"
);
goto
init_fail
;
}
if
(
SYN_CAP_EXTENDED
(
priv
->
capabilities
)
&&
SYN_CAP_PASS_THROUGH
(
priv
->
capabilities
))
synaptics_pt_create
(
psmouse
);
print_ident
(
priv
);
set_input_params
(
&
psmouse
->
dev
,
priv
);
psmouse
->
disconnect
=
synaptics_disconnect
;
psmouse
->
reconnect
=
synaptics_reconnect
;
return
0
;
init_fail:
...
...
@@ -399,36 +449,13 @@ int synaptics_init(struct psmouse *psmouse)
return
-
1
;
}
void
synaptics_disconnect
(
struct
psmouse
*
psmouse
)
{
struct
synaptics_data
*
priv
=
psmouse
->
private
;
if
(
psmouse
->
type
==
PSMOUSE_SYNAPTICS
&&
priv
)
{
synaptics_mode_cmd
(
psmouse
,
0
);
if
(
priv
->
ptport
)
{
serio_unregister_slave_port
(
priv
->
ptport
);
kfree
(
priv
->
ptport
);
}
kfree
(
priv
);
}
}
/*****************************************************************************
* Functions to interpret the absolute mode packets
****************************************************************************/
static
void
synaptics_parse_hw_state
(
unsigned
char
buf
[],
struct
synaptics_data
*
priv
,
struct
synaptics_hw_state
*
hw
)
{
hw
->
up
=
0
;
hw
->
down
=
0
;
hw
->
b0
=
0
;
hw
->
b1
=
0
;
hw
->
b2
=
0
;
hw
->
b3
=
0
;
hw
->
b4
=
0
;
hw
->
b5
=
0
;
hw
->
b6
=
0
;
hw
->
b7
=
0
;
memset
(
hw
,
0
,
sizeof
(
struct
synaptics_hw_state
));
if
(
SYN_MODEL_NEWABS
(
priv
->
model_id
))
{
hw
->
x
=
(((
buf
[
3
]
&
0x10
)
<<
8
)
|
...
...
@@ -570,64 +597,47 @@ static void synaptics_process_packet(struct psmouse *psmouse)
input_sync
(
dev
);
}
static
int
synaptics_validate_byte
(
struct
psmouse
*
psmouse
)
{
static
unsigned
char
newabs_mask
[]
=
{
0xC0
,
0x00
,
0x00
,
0xC0
,
0x00
};
static
unsigned
char
newabs_rslt
[]
=
{
0x80
,
0x00
,
0x00
,
0xC0
,
0x00
};
static
unsigned
char
oldabs_mask
[]
=
{
0xC0
,
0x60
,
0x00
,
0xC0
,
0x60
};
static
unsigned
char
oldabs_rslt
[]
=
{
0xC0
,
0x00
,
0x00
,
0x80
,
0x00
};
struct
synaptics_data
*
priv
=
psmouse
->
private
;
int
idx
=
psmouse
->
pktcnt
-
1
;
if
(
SYN_MODEL_NEWABS
(
priv
->
model_id
))
return
(
psmouse
->
packet
[
idx
]
&
newabs_mask
[
idx
])
==
newabs_rslt
[
idx
];
else
return
(
psmouse
->
packet
[
idx
]
&
oldabs_mask
[
idx
])
==
oldabs_rslt
[
idx
];
}
void
synaptics_process_byte
(
struct
psmouse
*
psmouse
,
struct
pt_regs
*
regs
)
{
struct
input_dev
*
dev
=
&
psmouse
->
dev
;
struct
synaptics_data
*
priv
=
psmouse
->
private
;
unsigned
char
data
=
psmouse
->
packet
[
psmouse
->
pktcnt
-
1
];
int
newabs
=
SYN_MODEL_NEWABS
(
priv
->
model_id
);
input_regs
(
dev
,
regs
);
switch
(
psmouse
->
pktcnt
)
{
case
1
:
if
(
newabs
?
((
data
&
0xC8
)
!=
0x80
)
:
((
data
&
0xC0
)
!=
0xC0
))
{
printk
(
KERN_WARNING
"Synaptics driver lost sync at 1st byte
\n
"
);
goto
bad_sync
;
}
break
;
case
2
:
if
(
!
newabs
&&
((
data
&
0x60
)
!=
0x00
))
{
printk
(
KERN_WARNING
"Synaptics driver lost sync at 2nd byte
\n
"
);
goto
bad_sync
;
}
break
;
case
4
:
if
(
newabs
?
((
data
&
0xC8
)
!=
0xC0
)
:
((
data
&
0xC0
)
!=
0x80
))
{
printk
(
KERN_WARNING
"Synaptics driver lost sync at 4th byte
\n
"
);
goto
bad_sync
;
}
break
;
case
5
:
if
(
!
newabs
&&
((
data
&
0x60
)
!=
0x00
))
{
printk
(
KERN_WARNING
"Synaptics driver lost sync at 5th byte
\n
"
);
goto
bad_sync
;
}
break
;
default:
if
(
psmouse
->
pktcnt
<
6
)
break
;
/* Wait for full packet */
if
(
psmouse
->
pktcnt
>=
6
)
{
/* Full packet received */
if
(
priv
->
out_of_sync
)
{
priv
->
out_of_sync
=
0
;
printk
(
KERN_NOTICE
"Synaptics driver resynced.
\n
"
);
}
if
(
p
riv
->
ptport
&&
synaptics_is_pt_packet
(
psmouse
->
packet
))
synaptics_pass_pt_packet
(
priv
->
ptport
,
psmouse
->
packet
);
if
(
p
smouse
->
ptport
&&
psmouse
->
ptport
->
serio
.
dev
&&
synaptics_is_pt_packet
(
psmouse
->
packet
))
synaptics_pass_pt_packet
(
&
psmouse
->
ptport
->
serio
,
psmouse
->
packet
);
else
synaptics_process_packet
(
psmouse
);
psmouse
->
pktcnt
=
0
;
}
else
if
(
psmouse
->
pktcnt
&&
!
synaptics_validate_byte
(
psmouse
))
{
printk
(
KERN_WARNING
"Synaptics driver lost sync at byte %d
\n
"
,
psmouse
->
pktcnt
);
psmouse
->
pktcnt
=
0
;
break
;
}
return
;
bad_sync:
priv
->
out_of_sync
++
;
psmouse
->
pktcnt
=
0
;
if
(
psmouse_resetafter
>
0
&&
priv
->
out_of_sync
==
psmouse_resetafter
)
{
psmouse
->
state
=
PSMOUSE_IGNORE
;
serio_rescan
(
psmouse
->
serio
);
if
(
++
priv
->
out_of_sync
==
psmouse_resetafter
)
{
psmouse
->
state
=
PSMOUSE_IGNORE
;
printk
(
KERN_NOTICE
"synaptics: issuing reconnect request
\n
"
);
serio_reconnect
(
psmouse
->
serio
);
}
}
}
drivers/input/mouse/synaptics.h
View file @
361d16e2
...
...
@@ -9,11 +9,9 @@
#ifndef _SYNAPTICS_H
#define _SYNAPTICS_H
extern
void
synaptics_process_byte
(
struct
psmouse
*
psmouse
,
struct
pt_regs
*
regs
);
extern
int
synaptics_detect
(
struct
psmouse
*
psmouse
);
extern
int
synaptics_init
(
struct
psmouse
*
psmouse
);
extern
int
synaptics_pt_init
(
struct
psmouse
*
psmouse
);
extern
void
synaptics_disconnect
(
struct
psmouse
*
psmouse
);
/* synaptics queries */
#define SYN_QUE_IDENTIFY 0x00
...
...
@@ -105,8 +103,6 @@ struct synaptics_data {
/* Data for normal processing */
unsigned
int
out_of_sync
;
/* # of packets out of sync */
int
old_w
;
/* Previous w value */
struct
serio
*
ptport
;
/* pass-through port */
};
#endif
/* _SYNAPTICS_H */
drivers/input/serio/i8042.c
View file @
361d16e2
...
...
@@ -12,11 +12,14 @@
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/config.h>
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/sysdev.h>
#include <linux/pm.h>
#include <linux/serio.h>
#include <asm/io.h>
...
...
@@ -25,19 +28,23 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION
(
"i8042 keyboard and mouse controller driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM
(
i8042_noaux
,
"1i"
);
MODULE_PARM
(
i8042_nomux
,
"1i"
);
MODULE_PARM
(
i8042_unlock
,
"1i"
);
MODULE_PARM
(
i8042_reset
,
"1i"
);
MODULE_PARM
(
i8042_direct
,
"1i"
);
MODULE_PARM
(
i8042_dumbkbd
,
"1i"
);
static
unsigned
int
i8042_noaux
;
module_param
(
i8042_noaux
,
bool
,
0
);
static
int
i8042_reset
;
static
int
i8042_noaux
;
static
int
i8042_nomux
;
static
int
i8042_unlock
;
static
int
i8042_direct
;
static
int
i8042_dumbkbd
;
static
unsigned
int
i8042_nomux
;
module_param
(
i8042_nomux
,
bool
,
0
);
static
unsigned
int
i8042_unlock
;
module_param
(
i8042_unlock
,
bool
,
0
);
static
unsigned
int
i8042_reset
;
module_param
(
i8042_reset
,
bool
,
0
);
static
unsigned
int
i8042_direct
;
module_param
(
i8042_direct
,
bool
,
0
);
static
unsigned
int
i8042_dumbkbd
;
module_param
(
i8042_dumbkbd
,
bool
,
0
);
#undef DEBUG
#include "i8042.h"
...
...
@@ -59,6 +66,9 @@ static struct serio i8042_aux_port;
static
unsigned
char
i8042_initial_ctr
;
static
unsigned
char
i8042_ctr
;
static
unsigned
char
i8042_mux_open
;
static
unsigned
char
i8042_mux_present
;
static
unsigned
char
i8042_sysdev_initialized
;
static
struct
pm_dev
*
i8042_pm_dev
;
struct
timer_list
i8042_timer
;
/*
...
...
@@ -214,16 +224,41 @@ static int i8042_aux_write(struct serio *port, unsigned char c)
}
/*
* i8042_open() is called when a port is open by the higher layer.
* It allocates the interrupt and enables it in the chip.
* i8042_activate_port() enables port on a chip.
*/
static
int
i8042_
open
(
struct
serio
*
port
)
static
int
i8042_
activate_port
(
struct
serio
*
port
)
{
struct
i8042_values
*
values
=
port
->
driver
;
i8042_flush
();
/*
* Enable port again here because it is disabled if we are
* resuming (normally it is enabled already).
*/
i8042_ctr
&=
~
values
->
disable
;
i8042_ctr
|=
values
->
irqen
;
if
(
i8042_command
(
&
i8042_ctr
,
I8042_CMD_CTL_WCTR
))
{
i8042_ctr
&=
~
values
->
irqen
;
return
-
1
;
}
return
0
;
}
/*
* i8042_open() is called when a port is open by the higher layer.
* It allocates the interrupt and calls i8042_enable_port.
*/
static
int
i8042_open
(
struct
serio
*
port
)
{
struct
i8042_values
*
values
=
port
->
driver
;
if
(
values
->
mux
!=
-
1
)
if
(
i8042_mux_open
++
)
return
0
;
...
...
@@ -231,21 +266,26 @@ static int i8042_open(struct serio *port)
if
(
request_irq
(
values
->
irq
,
i8042_interrupt
,
SA_SHIRQ
,
"i8042"
,
i8042_request_irq_cookie
))
{
printk
(
KERN_ERR
"i8042.c: Can't get irq %d for %s, unregistering the port.
\n
"
,
values
->
irq
,
values
->
name
);
values
->
exists
=
0
;
serio_unregister_port
(
port
);
return
-
1
;
goto
irq_fail
;
}
i8042_ctr
|=
values
->
irqen
;
if
(
i8042_command
(
&
i8042_ctr
,
I8042_CMD_CTL_WCTR
))
{
printk
(
KERN_ERR
"i8042.c: Can't write CTR while opening %s.
\n
"
,
values
->
name
);
return
-
1
;
if
(
i8042_activate_port
(
port
))
{
printk
(
KERN_ERR
"i8042.c: Can't activate %s, unregistering the port
\n
"
,
values
->
name
);
goto
activate_fail
;
}
i8042_interrupt
(
0
,
NULL
,
NULL
);
return
0
;
activate_fail:
free_irq
(
values
->
irq
,
i8042_request_irq_cookie
);
irq_fail:
values
->
exists
=
0
;
serio_unregister_port_delayed
(
port
);
return
-
1
;
}
/*
...
...
@@ -393,145 +433,78 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
/*
* i8042_
controller init initializes the i8042 controller, and,
* m
ost importantly, sets it into non-xlated mode if that's
*
desired
.
* i8042_
enable_mux_mode checks whether the controller has an active
* m
ultiplexor and puts the chip into Multiplexed (as opposed to
*
Legacy) mode
.
*/
static
int
__init
i8042_controller_init
(
void
)
static
int
i8042_enable_mux_mode
(
struct
i8042_values
*
values
,
unsigned
char
*
mux_version
)
{
unsigned
char
param
;
/*
* Test the i8042. We need to know if it thinks it's working correctly
* before doing anything else.
* Get rid of bytes in the queue.
*/
i8042_flush
();
if
(
i8042_reset
)
{
unsigned
char
param
;
if
(
i8042_command
(
&
param
,
I8042_CMD_CTL_TEST
))
{
printk
(
KERN_ERR
"i8042.c: i8042 controller self test timeout.
\n
"
);
return
-
1
;
}
if
(
param
!=
I8042_RET_CTL_TEST
)
{
printk
(
KERN_ERR
"i8042.c: i8042 controller selftest failed. (%#x != %#x)
\n
"
,
param
,
I8042_RET_CTL_TEST
);
return
-
1
;
}
}
/*
* Save the CTR for restoral on unload / reboot.
* Internal loopback test - send three bytes, they should come back from the
* mouse interface, the last should be version. Note that we negate mouseport
* command responses for the i8042_check_aux() routine.
*/
if
(
i8042_command
(
&
i8042_ctr
,
I8042_CMD_CTL_RCTR
))
{
printk
(
KERN_ERR
"i8042.c: Can't read CTR while initializing i8042.
\n
"
);
param
=
0xf0
;
if
(
i8042_command
(
&
param
,
I8042_CMD_AUX_LOOP
)
||
param
!=
0x0f
)
return
-
1
;
}
i8042_initial_ctr
=
i8042_ctr
;
/*
* Disable the keyboard interface and interrupt.
*/
i8042_ctr
|=
I8042_CTR_KBDDIS
;
i8042_ctr
&=
~
I8042_CTR_KBDINT
;
/*
* Handle keylock.
*/
if
(
~
i8042_read_status
()
&
I8042_STR_KEYLOCK
)
{
if
(
i8042_unlock
)
i8042_ctr
|=
I8042_CTR_IGNKEYLOCK
;
else
printk
(
KERN_WARNING
"i8042.c: Warning: Keylock active.
\n
"
);
}
/*
* If the chip is configured into nontranslated mode by the BIOS, don't
* bother enabling translating and be happy.
*/
if
(
~
i8042_ctr
&
I8042_CTR_XLATE
)
i8042_direct
=
1
;
/*
* Set nontranslated mode for the kbd interface if requested by an option.
* After this the kbd interface becomes a simple serial in/out, like the aux
* interface is. We don't do this by default, since it can confuse notebook
* BIOSes.
*/
if
(
i8042_direct
)
{
i8042_ctr
&=
~
I8042_CTR_XLATE
;
i8042_kbd_port
.
type
=
SERIO_8042
;
}
/*
* Write CTR back.
*/
if
(
i8042_command
(
&
i8042_ctr
,
I8042_CMD_CTL_WCTR
))
{
printk
(
KERN_ERR
"i8042.c: Can't write CTR while initializing i8042.
\n
"
);
param
=
0x56
;
if
(
i8042_command
(
&
param
,
I8042_CMD_AUX_LOOP
)
||
param
!=
0xa9
)
return
-
1
;
param
=
0xa4
;
if
(
i8042_command
(
&
param
,
I8042_CMD_AUX_LOOP
)
||
param
==
0x5b
)
return
-
1
;
}
if
(
mux_version
)
*
mux_version
=
~
param
;
return
0
;
}
/*
*
Here we try to reset everything back to a state in which the BIOS will be
*
able to talk to the hardware when rebooting.
*
i8042_enable_mux_ports enables 4 individual AUX ports after
*
the controller has been switched into Multiplexed mode
*/
void
i8042_controller_cleanup
(
void
)
static
int
i8042_enable_mux_ports
(
struct
i8042_values
*
values
)
{
unsigned
char
param
;
int
i
;
i8042_flush
();
/*
* Reset anything that is connected to the ports.
*/
if
(
i8042_kbd_values
.
exists
)
serio_cleanup
(
&
i8042_kbd_port
);
if
(
i8042_aux_values
.
exists
)
serio_cleanup
(
&
i8042_aux_port
);
for
(
i
=
0
;
i
<
4
;
i
++
)
if
(
i8042_mux_values
[
i
].
exists
)
serio_cleanup
(
i8042_mux_port
+
i
);
/*
* Reset the controller.
* Disable all muxed ports by disabling AUX.
*/
i
f
(
i8042_reset
)
{
unsigned
char
param
;
i
8042_ctr
|=
I8042_CTR_AUXDIS
;
i8042_ctr
&=
~
I8042_CTR_AUXINT
;
if
(
i8042_command
(
&
param
,
I8042_CMD_CTL_TEST
))
printk
(
KERN_ERR
"i8042.c: i8042 controller reset timeout.
\n
"
);
if
(
i8042_command
(
&
i8042_ctr
,
I8042_CMD_CTL_WCTR
))
{
printk
(
KERN_ERR
"i8042.c: Failed to disable AUX port, can't use MUX.
\n
"
);
return
-
1
;
}
/*
*
Restore the original control register setting
.
*
Enable all muxed ports
.
*/
i8042_ctr
=
i8042_initial_ctr
;
if
(
i8042_command
(
&
i8042_ctr
,
I8042_CMD_CTL_WCTR
))
printk
(
KERN_WARNING
"i8042.c: Can't restore CTR.
\n
"
);
for
(
i
=
0
;
i
<
4
;
i
++
)
{
i8042_command
(
&
param
,
I8042_CMD_MUX_PFX
+
i
);
i8042_command
(
&
param
,
I8042_CMD_AUX_ENABLE
);
}
return
0
;
}
/*
* i8042_check_mux() checks whether the controller supports the PS/2 Active
* Multiplexing specification by Synaptics, Phoenix, Insyde and
...
...
@@ -540,66 +513,31 @@ void i8042_controller_cleanup(void)
static
int
__init
i8042_check_mux
(
struct
i8042_values
*
values
)
{
unsigned
char
param
;
static
int
i8042_check_mux_cookie
;
int
i
;
unsigned
char
mux_version
;
/*
* Check if AUX irq is available.
*/
if
(
request_irq
(
values
->
irq
,
i8042_interrupt
,
SA_SHIRQ
,
"i8042"
,
&
i8042_check_mux_cookie
))
return
-
1
;
free_irq
(
values
->
irq
,
&
i8042_check_mux_cookie
);
/*
* Get rid of bytes in the queue.
*/
i8042_flush
();
/*
* Internal loopback test - send three bytes, they should come back from the
* mouse interface, the last should be version. Note that we negate mouseport
* command responses for the i8042_check_aux() routine.
*/
param
=
0xf0
;
if
(
i8042_command
(
&
param
,
I8042_CMD_AUX_LOOP
)
||
param
!=
0x0f
)
return
-
1
;
param
=
0x56
;
if
(
i8042_command
(
&
param
,
I8042_CMD_AUX_LOOP
)
||
param
!=
0xa9
)
return
-
1
;
param
=
0xa4
;
if
(
i8042_command
(
&
param
,
I8042_CMD_AUX_LOOP
)
||
param
==
0x5b
)
if
(
i8042_enable_mux_mode
(
values
,
&
mux_version
))
return
-
1
;
printk
(
KERN_INFO
"i8042.c: Detected active multiplexing controller, rev %d.%d.
\n
"
,
(
~
param
>>
4
)
&
0xf
,
~
param
&
0xf
);
/*
* Disable all muxed ports by disabling AUX.
*/
i8042_ctr
|=
I8042_CTR_AUXDIS
;
i8042_ctr
&=
~
I8042_CTR_AUXINT
;
(
mux_version
>>
4
)
&
0xf
,
mux_version
&
0xf
);
if
(
i8042_
command
(
&
i8042_ctr
,
I8042_CMD_CTL_WCTR
))
if
(
i8042_
enable_mux_ports
(
values
))
return
-
1
;
/*
* Enable all muxed ports.
*/
for
(
i
=
0
;
i
<
4
;
i
++
)
{
i8042_command
(
&
param
,
I8042_CMD_MUX_PFX
+
i
);
i8042_command
(
&
param
,
I8042_CMD_AUX_ENABLE
);
}
i8042_mux_present
=
1
;
return
0
;
}
/*
* i8042_check_aux() applies as much paranoia as it can at detecting
* the presence of an AUX interface.
...
...
@@ -675,6 +613,7 @@ static int __init i8042_check_aux(struct i8042_values *values)
return
0
;
}
/*
* i8042_port_register() marks the device as existing,
* registers it, and reports to the user.
...
...
@@ -691,63 +630,205 @@ static int __init i8042_port_register(struct i8042_values *values, struct serio
return
-
1
;
}
serio_register_port
(
port
);
printk
(
KERN_INFO
"serio: i8042 %s port at %#lx,%#lx irq %d
\n
"
,
values
->
name
,
(
unsigned
long
)
I8042_DATA_REG
,
(
unsigned
long
)
I8042_COMMAND_REG
,
values
->
irq
);
serio_register_port
(
port
);
return
0
;
}
static
void
i8042_timer_func
(
unsigned
long
data
)
{
i8042_interrupt
(
0
,
NULL
,
NULL
);
mod_timer
(
&
i8042_timer
,
jiffies
+
I8042_POLL_PERIOD
);
}
#ifndef MODULE
static
int
__init
i8042_setup_reset
(
char
*
str
)
{
i8042_reset
=
1
;
return
1
;
}
static
int
__init
i8042_setup_noaux
(
char
*
str
)
{
i8042_noaux
=
1
;
i8042_nomux
=
1
;
return
1
;
}
static
int
__init
i8042_setup_nomux
(
char
*
str
)
{
i8042_nomux
=
1
;
return
1
;
}
static
int
__init
i8042_setup_unlock
(
char
*
str
)
/*
* i8042_controller init initializes the i8042 controller, and,
* most importantly, sets it into non-xlated mode if that's
* desired.
*/
static
int
i8042_controller_init
(
void
)
{
i8042_unlock
=
1
;
return
1
;
if
(
i8042_noaux
)
i8042_nomux
=
1
;
/*
* Test the i8042. We need to know if it thinks it's working correctly
* before doing anything else.
*/
i8042_flush
();
if
(
i8042_reset
)
{
unsigned
char
param
;
if
(
i8042_command
(
&
param
,
I8042_CMD_CTL_TEST
))
{
printk
(
KERN_ERR
"i8042.c: i8042 controller self test timeout.
\n
"
);
return
-
1
;
}
if
(
param
!=
I8042_RET_CTL_TEST
)
{
printk
(
KERN_ERR
"i8042.c: i8042 controller selftest failed. (%#x != %#x)
\n
"
,
param
,
I8042_RET_CTL_TEST
);
return
-
1
;
}
}
/*
* Save the CTR for restoral on unload / reboot.
*/
if
(
i8042_command
(
&
i8042_ctr
,
I8042_CMD_CTL_RCTR
))
{
printk
(
KERN_ERR
"i8042.c: Can't read CTR while initializing i8042.
\n
"
);
return
-
1
;
}
i8042_initial_ctr
=
i8042_ctr
;
/*
* Disable the keyboard interface and interrupt.
*/
i8042_ctr
|=
I8042_CTR_KBDDIS
;
i8042_ctr
&=
~
I8042_CTR_KBDINT
;
/*
* Handle keylock.
*/
if
(
~
i8042_read_status
()
&
I8042_STR_KEYLOCK
)
{
if
(
i8042_unlock
)
i8042_ctr
|=
I8042_CTR_IGNKEYLOCK
;
else
printk
(
KERN_WARNING
"i8042.c: Warning: Keylock active.
\n
"
);
}
/*
* If the chip is configured into nontranslated mode by the BIOS, don't
* bother enabling translating and be happy.
*/
if
(
~
i8042_ctr
&
I8042_CTR_XLATE
)
i8042_direct
=
1
;
/*
* Set nontranslated mode for the kbd interface if requested by an option.
* After this the kbd interface becomes a simple serial in/out, like the aux
* interface is. We don't do this by default, since it can confuse notebook
* BIOSes.
*/
if
(
i8042_direct
)
{
i8042_ctr
&=
~
I8042_CTR_XLATE
;
i8042_kbd_port
.
type
=
SERIO_8042
;
}
/*
* Write CTR back.
*/
if
(
i8042_command
(
&
i8042_ctr
,
I8042_CMD_CTL_WCTR
))
{
printk
(
KERN_ERR
"i8042.c: Can't write CTR while initializing i8042.
\n
"
);
return
-
1
;
}
return
0
;
}
static
int
__init
i8042_setup_direct
(
char
*
str
)
/*
* Here we try to reset everything back to a state in which the BIOS will be
* able to talk to the hardware when rebooting.
*/
void
i8042_controller_cleanup
(
void
)
{
i8042_direct
=
1
;
return
1
;
int
i
;
i8042_flush
();
/*
* Reset anything that is connected to the ports.
*/
if
(
i8042_kbd_values
.
exists
)
serio_cleanup
(
&
i8042_kbd_port
);
if
(
i8042_aux_values
.
exists
)
serio_cleanup
(
&
i8042_aux_port
);
for
(
i
=
0
;
i
<
4
;
i
++
)
if
(
i8042_mux_values
[
i
].
exists
)
serio_cleanup
(
i8042_mux_port
+
i
);
/*
* Reset the controller.
*/
if
(
i8042_reset
)
{
unsigned
char
param
;
if
(
i8042_command
(
&
param
,
I8042_CMD_CTL_TEST
))
printk
(
KERN_ERR
"i8042.c: i8042 controller reset timeout.
\n
"
);
}
/*
* Restore the original control register setting.
*/
i8042_ctr
=
i8042_initial_ctr
;
if
(
i8042_command
(
&
i8042_ctr
,
I8042_CMD_CTL_WCTR
))
printk
(
KERN_WARNING
"i8042.c: Can't restore CTR.
\n
"
);
}
static
int
__init
i8042_setup_dumbkbd
(
char
*
str
)
/*
* Here we try to reset everything back to a state in which suspended
*/
static
int
i8042_controller_resume
(
void
)
{
i8042_dumbkbd
=
1
;
return
1
;
int
i
;
if
(
i8042_controller_init
())
{
printk
(
KERN_ERR
"i8042: resume failed
\n
"
);
return
-
1
;
}
if
(
i8042_mux_present
)
if
(
i8042_enable_mux_mode
(
&
i8042_aux_values
,
NULL
)
||
i8042_enable_mux_ports
(
&
i8042_aux_values
))
{
printk
(
KERN_WARNING
"i8042: failed to resume active multiplexor, mouse won't wotk.
\n
"
);
}
/*
* Reconnect anything that was connected to the ports.
*/
if
(
i8042_kbd_values
.
exists
&&
i8042_activate_port
(
&
i8042_kbd_port
)
==
0
)
serio_reconnect
(
&
i8042_kbd_port
);
if
(
i8042_aux_values
.
exists
&&
i8042_activate_port
(
&
i8042_aux_port
)
==
0
)
serio_reconnect
(
&
i8042_aux_port
);
for
(
i
=
0
;
i
<
4
;
i
++
)
if
(
i8042_mux_values
[
i
].
exists
&&
i8042_activate_port
(
i8042_mux_port
+
i
)
==
0
)
serio_reconnect
(
i8042_mux_port
+
i
);
return
0
;
}
__setup
(
"i8042_reset"
,
i8042_setup_reset
);
__setup
(
"i8042_noaux"
,
i8042_setup_noaux
);
__setup
(
"i8042_nomux"
,
i8042_setup_nomux
);
__setup
(
"i8042_unlock"
,
i8042_setup_unlock
);
__setup
(
"i8042_direct"
,
i8042_setup_direct
);
__setup
(
"i8042_dumbkbd"
,
i8042_setup_dumbkbd
);
#endif
/*
* We need to reset the 8042 back to original mode on system shutdown,
...
...
@@ -769,6 +850,35 @@ static struct notifier_block i8042_notifier=
0
};
/*
* Resume handler for the new PM scheme (driver model)
*/
static
int
i8042_resume
(
struct
sys_device
*
dev
)
{
return
i8042_controller_resume
();
}
static
struct
sysdev_class
kbc_sysclass
=
{
set_kset_name
(
"i8042"
),
.
resume
=
i8042_resume
,
};
static
struct
sys_device
device_i8042
=
{
.
id
=
0
,
.
cls
=
&
kbc_sysclass
,
};
/*
* Resume handler for the old PM scheme (APM)
*/
static
int
i8042_pm_callback
(
struct
pm_dev
*
dev
,
pm_request_t
request
,
void
*
dummy
)
{
if
(
request
==
PM_RESUME
)
return
i8042_controller_resume
();
return
0
;
}
static
void
__init
i8042_init_mux_values
(
struct
i8042_values
*
values
,
struct
serio
*
port
,
int
index
)
{
memcpy
(
port
,
&
i8042_aux_port
,
sizeof
(
struct
serio
));
...
...
@@ -817,6 +927,15 @@ int __init i8042_init(void)
i8042_timer
.
function
=
i8042_timer_func
;
mod_timer
(
&
i8042_timer
,
jiffies
+
I8042_POLL_PERIOD
);
if
(
sysdev_class_register
(
&
kbc_sysclass
)
==
0
)
{
if
(
sys_device_register
(
&
device_i8042
)
==
0
)
i8042_sysdev_initialized
=
1
;
else
sysdev_class_unregister
(
&
kbc_sysclass
);
}
i8042_pm_dev
=
pm_register
(
PM_SYS_DEV
,
PM_SYS_UNKNOWN
,
i8042_pm_callback
);
register_reboot_notifier
(
&
i8042_notifier
);
return
0
;
...
...
@@ -828,6 +947,14 @@ void __exit i8042_exit(void)
unregister_reboot_notifier
(
&
i8042_notifier
);
if
(
i8042_pm_dev
)
pm_unregister
(
i8042_pm_dev
);
if
(
i8042_sysdev_initialized
)
{
sys_device_unregister
(
&
device_i8042
);
sysdev_class_unregister
(
&
kbc_sysclass
);
}
del_timer
(
&
i8042_timer
);
i8042_controller_cleanup
();
...
...
drivers/input/serio/serio.c
View file @
361d16e2
...
...
@@ -49,14 +49,17 @@ MODULE_LICENSE("GPL");
EXPORT_SYMBOL
(
serio_interrupt
);
EXPORT_SYMBOL
(
serio_register_port
);
EXPORT_SYMBOL
(
serio_register_slave_port
);
EXPORT_SYMBOL
(
serio_register_port_delayed
);
EXPORT_SYMBOL
(
__serio_register_port
);
EXPORT_SYMBOL
(
serio_unregister_port
);
EXPORT_SYMBOL
(
serio_unregister_slave_port
);
EXPORT_SYMBOL
(
serio_unregister_port_delayed
);
EXPORT_SYMBOL
(
__serio_unregister_port
);
EXPORT_SYMBOL
(
serio_register_device
);
EXPORT_SYMBOL
(
serio_unregister_device
);
EXPORT_SYMBOL
(
serio_open
);
EXPORT_SYMBOL
(
serio_close
);
EXPORT_SYMBOL
(
serio_rescan
);
EXPORT_SYMBOL
(
serio_reconnect
);
struct
serio_event
{
int
type
;
...
...
@@ -82,11 +85,23 @@ static void serio_find_dev(struct serio *serio)
}
}
#define SERIO_RESCAN 1
#define SERIO_RESCAN 1
#define SERIO_RECONNECT 2
#define SERIO_REGISTER_PORT 3
#define SERIO_UNREGISTER_PORT 4
static
DECLARE_WAIT_QUEUE_HEAD
(
serio_wait
);
static
DECLARE_COMPLETION
(
serio_exited
);
static
void
serio_invalidate_pending_events
(
struct
serio
*
serio
)
{
struct
serio_event
*
event
;
list_for_each_entry
(
event
,
&
serio_event_list
,
node
)
if
(
event
->
serio
==
serio
)
event
->
serio
=
NULL
;
}
void
serio_handle_events
(
void
)
{
struct
list_head
*
node
,
*
next
;
...
...
@@ -95,17 +110,35 @@ void serio_handle_events(void)
list_for_each_safe
(
node
,
next
,
&
serio_event_list
)
{
event
=
container_of
(
node
,
struct
serio_event
,
node
);
down
(
&
serio_sem
);
if
(
event
->
serio
==
NULL
)
goto
event_done
;
switch
(
event
->
type
)
{
case
SERIO_REGISTER_PORT
:
__serio_register_port
(
event
->
serio
);
break
;
case
SERIO_UNREGISTER_PORT
:
__serio_unregister_port
(
event
->
serio
);
break
;
case
SERIO_RECONNECT
:
if
(
event
->
serio
->
dev
&&
event
->
serio
->
dev
->
reconnect
)
if
(
event
->
serio
->
dev
->
reconnect
(
event
->
serio
)
==
0
)
break
;
/* reconnect failed - fall through to rescan */
case
SERIO_RESCAN
:
down
(
&
serio_sem
);
if
(
event
->
serio
->
dev
&&
event
->
serio
->
dev
->
disconnect
)
event
->
serio
->
dev
->
disconnect
(
event
->
serio
);
serio_find_dev
(
event
->
serio
);
up
(
&
serio_sem
);
break
;
default:
break
;
}
event_done:
up
(
&
serio_sem
);
list_del_init
(
node
);
kfree
(
event
);
}
...
...
@@ -130,18 +163,27 @@ static int serio_thread(void *nothing)
complete_and_exit
(
&
serio_exited
,
0
);
}
void
serio_rescan
(
struct
serio
*
serio
)
static
void
serio_queue_event
(
struct
serio
*
serio
,
int
event_type
)
{
struct
serio_event
*
event
;
if
(
!
(
event
=
kmalloc
(
sizeof
(
struct
serio_event
),
GFP_ATOMIC
)))
return
;
if
((
event
=
kmalloc
(
sizeof
(
struct
serio_event
),
GFP_ATOMIC
)))
{
event
->
type
=
event_type
;
event
->
serio
=
serio
;
list_add_tail
(
&
event
->
node
,
&
serio_event_list
);
wake_up
(
&
serio_wait
);
}
}
event
->
type
=
SERIO_RESCAN
;
event
->
serio
=
serio
;
void
serio_rescan
(
struct
serio
*
serio
)
{
serio_queue_event
(
serio
,
SERIO_RESCAN
);
}
list_add_tail
(
&
event
->
node
,
&
serio_event_list
);
wake_up
(
&
serio_wait
);
void
serio_reconnect
(
struct
serio
*
serio
)
{
serio_queue_event
(
serio
,
SERIO_RECONNECT
);
}
irqreturn_t
serio_interrupt
(
struct
serio
*
serio
,
...
...
@@ -163,17 +205,26 @@ irqreturn_t serio_interrupt(struct serio *serio,
void
serio_register_port
(
struct
serio
*
serio
)
{
down
(
&
serio_sem
);
list_add_tail
(
&
serio
->
node
,
&
serio_list
);
serio_find_dev
(
serio
);
__serio_register_port
(
serio
);
up
(
&
serio_sem
);
}
/*
* Same as serio_register_port but does not try to acquire serio_sem.
* Should be used when registering a serio from other input device's
* Submits register request to kseriod for subsequent execution.
* Can be used when it is not obvious whether the serio_sem is
* taken or not and when delayed execution is feasible.
*/
void
serio_register_port_delayed
(
struct
serio
*
serio
)
{
serio_queue_event
(
serio
,
SERIO_REGISTER_PORT
);
}
/*
* Should only be called directly if serio_sem has already been taken,
* for example when unregistering a serio from other input device's
* connect() function.
*/
void
serio_register_slave
_port
(
struct
serio
*
serio
)
void
__serio_register
_port
(
struct
serio
*
serio
)
{
list_add_tail
(
&
serio
->
node
,
&
serio_list
);
serio_find_dev
(
serio
);
...
...
@@ -182,19 +233,28 @@ void serio_register_slave_port(struct serio *serio)
void
serio_unregister_port
(
struct
serio
*
serio
)
{
down
(
&
serio_sem
);
list_del_init
(
&
serio
->
node
);
if
(
serio
->
dev
&&
serio
->
dev
->
disconnect
)
serio
->
dev
->
disconnect
(
serio
);
__serio_unregister_port
(
serio
);
up
(
&
serio_sem
);
}
/*
* Same as serio_unregister_port but does not try to acquire serio_sem.
* Should be used when unregistering a serio from other input device's
* Submits unregister request to kseriod for subsequent execution.
* Can be used when it is not obvious whether the serio_sem is
* taken or not and when delayed execution is feasible.
*/
void
serio_unregister_port_delayed
(
struct
serio
*
serio
)
{
serio_queue_event
(
serio
,
SERIO_UNREGISTER_PORT
);
}
/*
* Should only be called directly if serio_sem has already been taken,
* for example when unregistering a serio from other input device's
* disconnect() function.
*/
void
serio_unregister_slave
_port
(
struct
serio
*
serio
)
void
__serio_unregister
_port
(
struct
serio
*
serio
)
{
serio_invalidate_pending_events
(
serio
);
list_del_init
(
&
serio
->
node
);
if
(
serio
->
dev
&&
serio
->
dev
->
disconnect
)
serio
->
dev
->
disconnect
(
serio
);
...
...
drivers/net/bonding/bond_main.c
View file @
361d16e2
...
...
@@ -3910,7 +3910,6 @@ static void bond_free_all(void)
unregister_netdevice
(
dev
);
bond_deinit
(
dev
);
free_netdev
(
dev
);
}
#ifdef CONFIG_PROC_FS
...
...
@@ -4008,6 +4007,8 @@ static int __init bond_init(struct net_device *dev)
bond_create_proc_info
(
bond
);
#endif
dev
->
destructor
=
free_netdev
;
list_add_tail
(
&
bond
->
bond_list
,
&
bond_dev_list
);
return
0
;
...
...
drivers/net/pcmcia/3c574_cs.c
View file @
361d16e2
...
...
@@ -1092,8 +1092,12 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev)
{
struct
el3_private
*
lp
=
(
struct
el3_private
*
)
dev
->
priv
;
if
(
netif_device_present
(
dev
))
if
(
netif_device_present
(
dev
))
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
lp
->
window_lock
,
flags
);
update_stats
(
dev
);
spin_unlock_irqrestore
(
&
lp
->
window_lock
,
flags
);
}
return
&
lp
->
stats
;
}
...
...
@@ -1105,7 +1109,6 @@ static void update_stats(struct net_device *dev)
{
struct
el3_private
*
lp
=
(
struct
el3_private
*
)
dev
->
priv
;
ioaddr_t
ioaddr
=
dev
->
base_addr
;
unsigned
long
flags
;
u8
rx
,
tx
,
up
;
DEBUG
(
2
,
"%s: updating the statistics.
\n
"
,
dev
->
name
);
...
...
@@ -1113,8 +1116,6 @@ static void update_stats(struct net_device *dev)
if
(
inw
(
ioaddr
+
EL3_STATUS
)
==
0xffff
)
/* No card. */
return
;
spin_lock_irqsave
(
&
lp
->
window_lock
,
flags
);
/* Unlike the 3c509 we need not turn off stats updates while reading. */
/* Switch to the stats window, and read everything. */
EL3WINDOW
(
6
);
...
...
@@ -1139,7 +1140,6 @@ static void update_stats(struct net_device *dev)
lp
->
stats
.
tx_bytes
+=
tx
+
((
up
&
0xf0
)
<<
12
);
EL3WINDOW
(
1
);
spin_unlock_irqrestore
(
&
lp
->
window_lock
,
flags
);
}
static
int
el3_rx
(
struct
net_device
*
dev
,
int
worklimit
)
...
...
@@ -1281,6 +1281,8 @@ static int el3_close(struct net_device *dev)
DEBUG
(
2
,
"%s: shutting down ethercard.
\n
"
,
dev
->
name
);
if
(
DEV_OK
(
link
))
{
unsigned
long
flags
;
/* Turn off statistics ASAP. We update lp->stats below. */
outw
(
StatsDisable
,
ioaddr
+
EL3_CMD
);
...
...
@@ -1290,8 +1292,9 @@ static int el3_close(struct net_device *dev)
/* Note: Switching to window 0 may disable the IRQ. */
EL3WINDOW
(
0
);
spin_lock_irqsave
(
&
lp
->
window_lock
,
flags
);
update_stats
(
dev
);
spin_unlock_irqrestore
(
&
lp
->
window_lock
,
flags
);
}
link
->
open
--
;
...
...
drivers/net/tokenring/Kconfig
View file @
361d16e2
...
...
@@ -107,7 +107,7 @@ config TMS380TR
config TMSPCI
tristate "Generic TMS380 PCI support"
depends on TR && TMS380TR
!=n
&& PCI
depends on TR && TMS380TR && PCI
---help---
This tms380 module supports generic TMS380-based PCI cards.
...
...
@@ -122,7 +122,7 @@ config TMSPCI
config SKISA
tristate "SysKonnect TR4/16 ISA support"
depends on TR && TMS380TR
!=n
&& ISA
depends on TR && TMS380TR && ISA
help
This tms380 module supports SysKonnect TR4/16 ISA cards.
...
...
@@ -134,7 +134,7 @@ config SKISA
config PROTEON
tristate "Proteon ISA support"
depends on TR && TMS380TR
!=n
&& ISA
depends on TR && TMS380TR && ISA
help
This tms380 module supports Proteon ISA cards.
...
...
@@ -147,7 +147,7 @@ config PROTEON
config ABYSS
tristate "Madge Smart 16/4 PCI Mk2 support"
depends on TR && TMS380TR
!=n
&& PCI
depends on TR && TMS380TR && PCI
help
This tms380 module supports the Madge Smart 16/4 PCI Mk2
cards (51-02).
...
...
@@ -157,7 +157,7 @@ config ABYSS
config MADGEMC
tristate "Madge Smart 16/4 Ringnode MicroChannel"
depends on TR && TMS380TR
!=n
&& MCA
depends on TR && TMS380TR && MCA
help
This tms380 module supports the Madge Smart 16/4 MC16 and MC32
MicroChannel adapters.
...
...
drivers/net/typhoon.c
View file @
361d16e2
...
...
@@ -85,8 +85,8 @@ static const int multicast_filter_limit = 32;
#define PKT_BUF_SZ 1536
#define DRV_MODULE_NAME "typhoon"
#define DRV_MODULE_VERSION "1.5.
1
"
#define DRV_MODULE_RELDATE "03/
06/26
"
#define DRV_MODULE_VERSION "1.5.
2
"
#define DRV_MODULE_RELDATE "03/
11/25
"
#define PFX DRV_MODULE_NAME ": "
#define ERR_PFX KERN_ERR PFX
...
...
@@ -127,7 +127,7 @@ static const int multicast_filter_limit = 32;
static
char
version
[]
__devinitdata
=
"typhoon.c: version "
DRV_MODULE_VERSION
" ("
DRV_MODULE_RELDATE
")
\n
"
;
MODULE_AUTHOR
(
"David Dillow <d
illowd@y12.doe.gov
>"
);
MODULE_AUTHOR
(
"David Dillow <d
ave@thedillows.org
>"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_DESCRIPTION
(
"3Com Typhoon Family (3C990, 3CR990, and variants)"
);
MODULE_PARM
(
rx_copybreak
,
"i"
);
...
...
@@ -146,11 +146,12 @@ struct typhoon_card_info {
int
capabilities
;
};
#define TYPHOON_CRYPTO_NONE 0
#define TYPHOON_CRYPTO_DES 1
#define TYPHOON_CRYPTO_3DES 2
#define TYPHOON_CRYPTO_VARIABLE 4
#define TYPHOON_FIBER 8
#define TYPHOON_CRYPTO_NONE 0x00
#define TYPHOON_CRYPTO_DES 0x01
#define TYPHOON_CRYPTO_3DES 0x02
#define TYPHOON_CRYPTO_VARIABLE 0x04
#define TYPHOON_FIBER 0x08
#define TYPHOON_WAKEUP_NEEDS_RESET 0x10
enum
typhoon_cards
{
TYPHOON_TX
=
0
,
TYPHOON_TX95
,
TYPHOON_TX97
,
TYPHOON_SVR
,
...
...
@@ -307,7 +308,8 @@ enum state_values {
/* We'll wait up to six seconds for a reset, and half a second normally.
*/
#define TYPHOON_UDELAY 50
#define TYPHOON_RESET_TIMEOUT (6 * HZ)
#define TYPHOON_RESET_TIMEOUT_SLEEP (6 * HZ)
#define TYPHOON_RESET_TIMEOUT_NOSLEEP ((6 * 1000000) / TYPHOON_UDELAY)
#define TYPHOON_WAIT_TIMEOUT ((1000000 / 2) / TYPHOON_UDELAY)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 28)
...
...
@@ -375,10 +377,12 @@ static int
typhoon_reset
(
unsigned
long
ioaddr
,
int
wait_type
)
{
int
i
,
err
=
0
;
int
timeout
=
TYPHOON_RESET_TIMEOUT
;
int
timeout
;
if
(
wait_type
==
WaitNoSleep
)
timeout
=
(
timeout
*
1000000
)
/
(
HZ
*
TYPHOON_UDELAY
);
timeout
=
TYPHOON_RESET_TIMEOUT_NOSLEEP
;
else
timeout
=
TYPHOON_RESET_TIMEOUT_SLEEP
;
writel
(
TYPHOON_INTR_ALL
,
ioaddr
+
TYPHOON_REG_INTR_MASK
);
writel
(
TYPHOON_INTR_ALL
,
ioaddr
+
TYPHOON_REG_INTR_STATUS
);
...
...
@@ -1858,6 +1862,11 @@ typhoon_sleep(struct typhoon *tp, int state, u16 events)
if
(
typhoon_wait_status
(
ioaddr
,
TYPHOON_STATUS_SLEEPING
)
<
0
)
return
-
ETIMEDOUT
;
/* Since we cannot monitor the status of the link while sleeping,
* tell the world it went away.
*/
netif_carrier_off
(
tp
->
dev
);
pci_enable_wake
(
tp
->
pdev
,
state
,
1
);
pci_disable_device
(
pdev
);
return
pci_set_power_state
(
pdev
,
state
);
...
...
@@ -1872,8 +1881,13 @@ typhoon_wakeup(struct typhoon *tp, int wait_type)
pci_set_power_state
(
pdev
,
0
);
pci_restore_state
(
pdev
,
tp
->
pci_state
);
/* Post 2.x.x versions of the Sleep Image require a reset before
* we can download the Runtime Image. But let's not make users of
* the old firmware pay for the reset.
*/
writel
(
TYPHOON_BOOTCMD_WAKEUP
,
ioaddr
+
TYPHOON_REG_COMMAND
);
if
(
typhoon_wait_status
(
ioaddr
,
TYPHOON_STATUS_WAITING_FOR_HOST
)
<
0
)
if
(
typhoon_wait_status
(
ioaddr
,
TYPHOON_STATUS_WAITING_FOR_HOST
)
<
0
||
(
tp
->
capabilities
&
TYPHOON_WAKEUP_NEEDS_RESET
))
return
typhoon_reset
(
ioaddr
,
wait_type
);
return
0
;
...
...
@@ -2251,7 +2265,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
void
*
shared
;
dma_addr_t
shared_dma
;
struct
cmd_desc
xp_cmd
;
struct
resp_desc
xp_resp
;
struct
resp_desc
xp_resp
[
3
]
;
int
i
;
int
err
=
0
;
...
...
@@ -2380,15 +2394,15 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
INIT_COMMAND_WITH_RESPONSE
(
&
xp_cmd
,
TYPHOON_CMD_READ_MAC_ADDRESS
);
if
(
typhoon_issue_command
(
tp
,
1
,
&
xp_cmd
,
1
,
&
xp_resp
)
<
0
)
{
if
(
typhoon_issue_command
(
tp
,
1
,
&
xp_cmd
,
1
,
xp_resp
)
<
0
)
{
printk
(
ERR_PFX
"%s: cannot read MAC address
\n
"
,
pci_name
(
pdev
));
err
=
-
EIO
;
goto
error_out_reset
;
}
*
(
u16
*
)
&
dev
->
dev_addr
[
0
]
=
htons
(
le16_to_cpu
(
xp_resp
.
parm1
));
*
(
u32
*
)
&
dev
->
dev_addr
[
2
]
=
htonl
(
le32_to_cpu
(
xp_resp
.
parm2
));
*
(
u16
*
)
&
dev
->
dev_addr
[
0
]
=
htons
(
le16_to_cpu
(
xp_resp
[
0
]
.
parm1
));
*
(
u32
*
)
&
dev
->
dev_addr
[
2
]
=
htonl
(
le32_to_cpu
(
xp_resp
[
0
]
.
parm2
));
if
(
!
is_valid_ether_addr
(
dev
->
dev_addr
))
{
printk
(
ERR_PFX
"%s: Could not obtain valid ethernet address, "
...
...
@@ -2396,6 +2410,28 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto
error_out_reset
;
}
/* Read the Sleep Image version last, so the response is valid
* later when we print out the version reported.
*/
INIT_COMMAND_WITH_RESPONSE
(
&
xp_cmd
,
TYPHOON_CMD_READ_VERSIONS
);
if
(
typhoon_issue_command
(
tp
,
1
,
&
xp_cmd
,
3
,
xp_resp
)
<
0
)
{
printk
(
ERR_PFX
"%s: Could not get Sleep Image version
\n
"
,
pdev
->
slot_name
);
goto
error_out_reset
;
}
tp
->
capabilities
=
typhoon_card_info
[
card_id
].
capabilities
;
tp
->
xcvr_select
=
TYPHOON_XCVR_AUTONEG
;
/* Typhoon 1.0 Sleep Images return one response descriptor to the
* READ_VERSIONS command. Those versions are OK after waking up
* from sleep without needing a reset. Typhoon 1.1+ Sleep Images
* seem to need a little extra help to get started. Since we don't
* know how to nudge it along, just kick it.
*/
if
(
xp_resp
[
0
].
numDesc
!=
0
)
tp
->
capabilities
|=
TYPHOON_WAKEUP_NEEDS_RESET
;
if
(
typhoon_sleep
(
tp
,
3
,
0
)
<
0
)
{
printk
(
ERR_PFX
"%s: cannot put adapter to sleep
\n
"
,
pci_name
(
pdev
));
...
...
@@ -2403,9 +2439,6 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto
error_out_reset
;
}
tp
->
capabilities
=
typhoon_card_info
[
card_id
].
capabilities
;
tp
->
xcvr_select
=
TYPHOON_XCVR_AUTONEG
;
/* The chip-specific entries in the device structure. */
dev
->
open
=
typhoon_open
;
dev
->
hard_start_xmit
=
typhoon_start_tx
;
...
...
@@ -2442,6 +2475,32 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
printk
(
"%2.2x:"
,
dev
->
dev_addr
[
i
]);
printk
(
"%2.2x
\n
"
,
dev
->
dev_addr
[
i
]);
/* xp_resp still contains the response to the READ_VERSIONS command.
* For debugging, let the user know what version he has.
*/
if
(
xp_resp
[
0
].
numDesc
==
0
)
{
/* This is the Typhoon 1.0 type Sleep Image, last 16 bits
* of version is Month/Day of build.
*/
u16
monthday
=
le32_to_cpu
(
xp_resp
[
0
].
parm2
)
&
0xffff
;
printk
(
KERN_INFO
"%s: Typhoon 1.0 Sleep Image built "
"%02u/%02u/2000
\n
"
,
dev
->
name
,
monthday
>>
8
,
monthday
&
0xff
);
}
else
if
(
xp_resp
[
0
].
numDesc
==
2
)
{
/* This is the Typhoon 1.1+ type Sleep Image
*/
u32
sleep_ver
=
le32_to_cpu
(
xp_resp
[
0
].
parm2
);
u8
*
ver_string
=
(
u8
*
)
&
xp_resp
[
1
];
ver_string
[
25
]
=
0
;
printk
(
KERN_INFO
"%s: Typhoon 1.1+ Sleep Image version "
"%u.%u.%u.%u %s
\n
"
,
dev
->
name
,
HIPQUAD
(
sleep_ver
),
ver_string
);
}
else
{
printk
(
KERN_WARNING
"%s: Unknown Sleep Image version "
"(%u:%04x)
\n
"
,
dev
->
name
,
xp_resp
[
0
].
numDesc
,
le32_to_cpu
(
xp_resp
[
0
].
parm2
));
}
return
0
;
error_out_reset:
...
...
drivers/net/wireless/atmel.c
View file @
361d16e2
...
...
@@ -748,13 +748,13 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
if
(
priv
->
station_state
!=
STATION_STATE_READY
)
{
priv
->
stats
.
tx_errors
++
;
return
0
;
goto
done
;
}
if
(
priv
->
card
&&
priv
->
present_callback
&&
!
(
*
priv
->
present_callback
)(
priv
->
card
))
{
priv
->
stats
.
tx_errors
++
;
return
0
;
goto
done
;
}
/* first ensure the timer func cannot run */
...
...
@@ -804,6 +804,8 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
spin_unlock_irqrestore
(
&
priv
->
irqlock
,
flags
);
spin_unlock_bh
(
&
priv
->
timerlock
);
done:
dev_kfree_skb
(
skb
);
return
0
;
...
...
drivers/scsi/ata_piix.c
View file @
361d16e2
...
...
@@ -97,6 +97,7 @@ static Scsi_Host_Template piix_sht = {
.
proc_name
=
DRV_NAME
,
.
dma_boundary
=
ATA_DMA_BOUNDARY
,
.
slave_configure
=
ata_scsi_slave_config
,
.
bios_param
=
ata_std_bios_param
,
};
static
struct
ata_port_operations
piix_pata_ops
=
{
...
...
drivers/scsi/libata-core.c
View file @
361d16e2
...
...
@@ -1619,7 +1619,7 @@ static void ata_dev_set_pio(struct ata_port *ap, unsigned int device)
static
void
ata_sg_clean
(
struct
ata_queued_cmd
*
qc
)
{
struct
ata_port
*
ap
=
qc
->
ap
;
Scsi_C
mnd
*
cmd
=
qc
->
scsicmd
;
struct
scsi_c
mnd
*
cmd
=
qc
->
scsicmd
;
struct
scatterlist
*
sg
=
qc
->
sg
;
int
dir
=
scsi_to_pci_dma_dir
(
cmd
->
sc_data_direction
);
...
...
@@ -1635,8 +1635,8 @@ static void ata_sg_clean(struct ata_queued_cmd *qc)
if
(
cmd
->
use_sg
)
pci_unmap_sg
(
ap
->
host_set
->
pdev
,
sg
,
qc
->
n_elem
,
dir
);
else
pci_unmap_single
(
ap
->
host_set
->
pdev
,
sg
[
0
].
dma_address
,
sg
[
0
].
length
,
dir
);
pci_unmap_single
(
ap
->
host_set
->
pdev
,
sg
_dma_address
(
&
sg
[
0
])
,
sg
_dma_len
(
&
sg
[
0
])
,
dir
);
qc
->
flags
&=
~
ATA_QCFLAG_SG
;
qc
->
sg
=
NULL
;
...
...
@@ -1659,8 +1659,8 @@ void ata_fill_sg(struct ata_queued_cmd *qc)
assert
(
qc
->
n_elem
>
0
);
for
(
i
=
0
;
i
<
qc
->
n_elem
;
i
++
)
{
ap
->
prd
[
i
].
addr
=
cpu_to_le32
(
sg
[
i
].
dma_address
);
ap
->
prd
[
i
].
flags_len
=
cpu_to_le32
(
sg
[
i
].
length
);
ap
->
prd
[
i
].
addr
=
cpu_to_le32
(
sg
_dma_address
(
&
sg
[
i
])
);
ap
->
prd
[
i
].
flags_len
=
cpu_to_le32
(
sg
_dma_len
(
&
sg
[
i
])
);
VPRINTK
(
"PRD[%u] = (0x%X, 0x%X)
\n
"
,
i
,
le32_to_cpu
(
ap
->
prd
[
i
].
addr
),
le32_to_cpu
(
ap
->
prd
[
i
].
flags_len
));
}
...
...
@@ -1681,7 +1681,7 @@ void ata_fill_sg(struct ata_queued_cmd *qc)
static
int
ata_sg_setup_one
(
struct
ata_queued_cmd
*
qc
)
{
struct
ata_port
*
ap
=
qc
->
ap
;
Scsi_C
mnd
*
cmd
=
qc
->
scsicmd
;
struct
scsi_c
mnd
*
cmd
=
qc
->
scsicmd
;
int
dir
=
scsi_to_pci_dma_dir
(
cmd
->
sc_data_direction
);
struct
scatterlist
*
sg
=
qc
->
sg
;
unsigned
int
have_sg
=
(
qc
->
flags
&
ATA_QCFLAG_SG
);
...
...
@@ -1691,12 +1691,12 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
sg
->
page
=
virt_to_page
(
cmd
->
request_buffer
);
sg
->
offset
=
(
unsigned
long
)
cmd
->
request_buffer
&
~
PAGE_MASK
;
sg
->
length
=
cmd
->
request_bufflen
;
sg
_dma_len
(
sg
)
=
cmd
->
request_bufflen
;
if
(
!
have_sg
)
return
0
;
sg
->
dma_address
=
pci_map_single
(
ap
->
host_set
->
pdev
,
sg
_dma_address
(
sg
)
=
pci_map_single
(
ap
->
host_set
->
pdev
,
cmd
->
request_buffer
,
cmd
->
request_bufflen
,
dir
);
...
...
@@ -1720,7 +1720,7 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
static
int
ata_sg_setup
(
struct
ata_queued_cmd
*
qc
)
{
struct
ata_port
*
ap
=
qc
->
ap
;
Scsi_C
mnd
*
cmd
=
qc
->
scsicmd
;
struct
scsi_c
mnd
*
cmd
=
qc
->
scsicmd
;
struct
scatterlist
*
sg
;
int
n_elem
;
unsigned
int
have_sg
=
(
qc
->
flags
&
ATA_QCFLAG_SG
);
...
...
@@ -1872,7 +1872,7 @@ static void ata_pio_sector(struct ata_port *ap)
{
struct
ata_queued_cmd
*
qc
;
struct
scatterlist
*
sg
;
Scsi_C
mnd
*
cmd
;
struct
scsi_c
mnd
*
cmd
;
unsigned
char
*
buf
;
u8
status
;
...
...
@@ -1917,7 +1917,7 @@ static void ata_pio_sector(struct ata_port *ap)
qc
->
cursg_ofs
++
;
if
(
cmd
->
use_sg
)
if
((
qc
->
cursg_ofs
*
ATA_SECT_SIZE
)
==
sg
[
qc
->
cursg
].
length
)
{
if
((
qc
->
cursg_ofs
*
ATA_SECT_SIZE
)
==
sg
_dma_len
(
&
sg
[
qc
->
cursg
])
)
{
qc
->
cursg
++
;
qc
->
cursg_ofs
=
0
;
}
...
...
@@ -2092,7 +2092,7 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
void
ata_qc_complete
(
struct
ata_queued_cmd
*
qc
,
u8
drv_stat
,
unsigned
int
done_late
)
{
struct
ata_port
*
ap
=
qc
->
ap
;
Scsi_C
mnd
*
cmd
=
qc
->
scsicmd
;
struct
scsi_c
mnd
*
cmd
=
qc
->
scsicmd
;
unsigned
int
tag
,
do_clear
=
0
;
assert
(
qc
!=
NULL
);
/* ata_qc_from_tag _might_ return NULL */
...
...
@@ -2163,7 +2163,7 @@ static void ata_qc_push (struct ata_queued_cmd *qc, unsigned int append)
int
ata_qc_issue
(
struct
ata_queued_cmd
*
qc
)
{
struct
ata_port
*
ap
=
qc
->
ap
;
Scsi_C
mnd
*
cmd
=
qc
->
scsicmd
;
struct
scsi_c
mnd
*
cmd
=
qc
->
scsicmd
;
unsigned
int
dma
=
qc
->
flags
&
ATA_QCFLAG_DMA
;
ata_dev_select
(
ap
,
qc
->
dev
->
devno
,
1
,
0
);
...
...
@@ -2719,7 +2719,7 @@ static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister)
DPRINTK
(
"ENTER
\n
"
);
if
(
do_unregister
)
scsi_remove_host
(
sh
);
/* FIXME: check return val */
scsi_remove_host
(
sh
);
ata_thread_kill
(
ap
);
/* FIXME: check return val */
...
...
@@ -3204,7 +3204,6 @@ void ata_pci_remove_one (struct pci_dev *pdev)
for
(
i
=
0
;
i
<
host_set
->
n_ports
;
i
++
)
{
ap
=
host_set
->
ports
[
i
];
/* FIXME: check return val */
scsi_remove_host
(
ap
->
host
);
}
...
...
@@ -3215,13 +3214,10 @@ void ata_pci_remove_one (struct pci_dev *pdev)
host_set
->
ports
[
0
]
->
ops
->
host_stop
(
host_set
);
for
(
i
=
0
;
i
<
host_set
->
n_ports
;
i
++
)
{
Scsi_Host_Template
*
sht
;
ap
=
host_set
->
ports
[
i
];
sht
=
ap
->
host
->
hostt
;
ata_scsi_release
(
ap
->
host
);
scsi_host_put
(
ap
->
host
);
/* FIXME: check return val */
scsi_host_put
(
ap
->
host
);
}
pci_release_regions
(
pdev
);
...
...
@@ -3279,6 +3275,7 @@ int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits)
return
(
tmp
==
bits
->
val
)
?
1
:
0
;
}
/**
* ata_init -
*
...
...
@@ -3304,6 +3301,7 @@ module_init(ata_init);
*/
EXPORT_SYMBOL_GPL
(
pci_test_config_bits
);
EXPORT_SYMBOL_GPL
(
ata_std_bios_param
);
EXPORT_SYMBOL_GPL
(
ata_std_ports
);
EXPORT_SYMBOL_GPL
(
ata_device_add
);
EXPORT_SYMBOL_GPL
(
ata_qc_complete
);
...
...
drivers/scsi/libata-scsi.c
View file @
361d16e2
...
...
@@ -32,10 +32,33 @@
#include "libata.h"
/**
* ata_std_bios_param - generic bios head/sector/cylinder calculator
* used by sd. Most BIOSes nowadays expect a XXX/255/16 (CHS)
* mapping. Some situations may arise where the disk is not
* bootable if this is not used.
*
* LOCKING:
*
* RETURNS:
*
*/
int
ata_std_bios_param
(
struct
scsi_device
*
sdev
,
struct
block_device
*
bdev
,
sector_t
capacity
,
int
geom
[])
{
geom
[
0
]
=
255
;
geom
[
1
]
=
63
;
geom
[
2
]
=
capacity
/
(
geom
[
0
]
*
geom
[
1
]);
return
0
;
}
struct
ata_queued_cmd
*
ata_scsi_qc_new
(
struct
ata_port
*
ap
,
struct
ata_device
*
dev
,
Scsi_C
mnd
*
cmd
,
void
(
*
done
)(
Scsi_C
mnd
*
))
struct
scsi_c
mnd
*
cmd
,
void
(
*
done
)(
struct
scsi_c
mnd
*
))
{
struct
ata_queued_cmd
*
qc
;
...
...
@@ -69,7 +92,7 @@ struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap,
void
ata_to_sense_error
(
struct
ata_queued_cmd
*
qc
)
{
Scsi_C
mnd
*
cmd
=
qc
->
scsicmd
;
struct
scsi_c
mnd
*
cmd
=
qc
->
scsicmd
;
cmd
->
result
=
SAM_STAT_CHECK_CONDITION
;
...
...
@@ -282,7 +305,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd,
*/
void
ata_scsi_rw_queue
(
struct
ata_port
*
ap
,
struct
ata_device
*
dev
,
Scsi_Cmnd
*
cmd
,
void
(
*
done
)(
Scsi_C
mnd
*
),
struct
scsi_cmnd
*
cmd
,
void
(
*
done
)(
struct
scsi_c
mnd
*
),
unsigned
int
cmd_size
)
{
struct
ata_queued_cmd
*
qc
;
...
...
@@ -332,7 +355,7 @@ void ata_scsi_rw_queue(struct ata_port *ap, struct ata_device *dev,
* Length of response buffer.
*/
static
unsigned
int
ata_scsi_rbuf_get
(
Scsi_C
mnd
*
cmd
,
u8
**
buf_out
)
static
unsigned
int
ata_scsi_rbuf_get
(
struct
scsi_c
mnd
*
cmd
,
u8
**
buf_out
)
{
u8
*
buf
;
unsigned
int
buflen
;
...
...
@@ -363,7 +386,7 @@ static unsigned int ata_scsi_rbuf_get(Scsi_Cmnd *cmd, u8 **buf_out)
* spin_lock_irqsave(host_set lock)
*/
static
inline
void
ata_scsi_rbuf_put
(
Scsi_C
mnd
*
cmd
)
static
inline
void
ata_scsi_rbuf_put
(
struct
scsi_c
mnd
*
cmd
)
{
if
(
cmd
->
use_sg
)
{
struct
scatterlist
*
sg
;
...
...
@@ -394,7 +417,7 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
{
u8
*
rbuf
;
unsigned
int
buflen
,
rc
;
Scsi_C
mnd
*
cmd
=
args
->
cmd
;
struct
scsi_c
mnd
*
cmd
=
args
->
cmd
;
buflen
=
ata_scsi_rbuf_get
(
cmd
,
&
rbuf
);
rc
=
actor
(
args
,
rbuf
,
buflen
);
...
...
@@ -817,7 +840,7 @@ unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
* spin_lock_irqsave(host_set lock)
*/
void
ata_scsi_badcmd
(
Scsi_Cmnd
*
cmd
,
void
(
*
done
)(
Scsi_C
mnd
*
),
u8
asc
,
u8
ascq
)
void
ata_scsi_badcmd
(
struct
scsi_cmnd
*
cmd
,
void
(
*
done
)(
struct
scsi_c
mnd
*
),
u8
asc
,
u8
ascq
)
{
DPRINTK
(
"ENTER
\n
"
);
cmd
->
result
=
SAM_STAT_CHECK_CONDITION
;
...
...
@@ -847,7 +870,7 @@ void ata_scsi_badcmd(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *), u8 asc, u8 ascq)
*/
static
void
atapi_scsi_queuecmd
(
struct
ata_port
*
ap
,
struct
ata_device
*
dev
,
Scsi_Cmnd
*
cmd
,
void
(
*
done
)(
Scsi_C
mnd
*
))
struct
scsi_cmnd
*
cmd
,
void
(
*
done
)(
struct
scsi_c
mnd
*
))
{
struct
ata_queued_cmd
*
qc
;
u8
*
scsicmd
=
cmd
->
cmnd
,
status
;
...
...
@@ -958,7 +981,7 @@ static void atapi_scsi_queuecmd(struct ata_port *ap, struct ata_device *dev,
* Zero.
*/
int
ata_scsi_queuecmd
(
Scsi_Cmnd
*
cmd
,
void
(
*
done
)(
Scsi_C
mnd
*
))
int
ata_scsi_queuecmd
(
struct
scsi_cmnd
*
cmd
,
void
(
*
done
)(
struct
scsi_c
mnd
*
))
{
u8
*
scsicmd
=
cmd
->
cmnd
;
struct
ata_port
*
ap
;
...
...
drivers/scsi/libata.h
View file @
361d16e2
...
...
@@ -31,8 +31,8 @@
struct
ata_scsi_args
{
struct
ata_port
*
ap
;
struct
ata_device
*
dev
;
Scsi_C
mnd
*
cmd
;
void
(
*
done
)(
Scsi_C
mnd
*
);
struct
scsi_c
mnd
*
cmd
;
void
(
*
done
)(
struct
scsi_c
mnd
*
);
};
...
...
@@ -51,7 +51,7 @@ extern void ata_thread_wake(struct ata_port *ap, unsigned int thr_state);
/* libata-scsi.c */
extern
void
ata_to_sense_error
(
struct
ata_queued_cmd
*
qc
);
extern
void
ata_scsi_rw_queue
(
struct
ata_port
*
ap
,
struct
ata_device
*
dev
,
Scsi_Cmnd
*
cmd
,
void
(
*
done
)(
Scsi_C
mnd
*
),
struct
scsi_cmnd
*
cmd
,
void
(
*
done
)(
struct
scsi_c
mnd
*
),
unsigned
int
cmd_size
);
extern
int
ata_scsi_error
(
struct
Scsi_Host
*
host
);
extern
unsigned
int
ata_scsiop_inq_std
(
struct
ata_scsi_args
*
args
,
u8
*
rbuf
,
...
...
@@ -74,19 +74,19 @@ extern unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
unsigned
int
buflen
);
extern
unsigned
int
ata_scsiop_report_luns
(
struct
ata_scsi_args
*
args
,
u8
*
rbuf
,
unsigned
int
buflen
);
extern
void
ata_scsi_badcmd
(
Scsi_C
mnd
*
cmd
,
void
(
*
done
)(
Scsi_C
mnd
*
),
extern
void
ata_scsi_badcmd
(
struct
scsi_c
mnd
*
cmd
,
void
(
*
done
)(
struct
scsi_c
mnd
*
),
u8
asc
,
u8
ascq
);
extern
void
ata_scsi_rbuf_fill
(
struct
ata_scsi_args
*
args
,
unsigned
int
(
*
actor
)
(
struct
ata_scsi_args
*
args
,
u8
*
rbuf
,
unsigned
int
buflen
));
static
inline
void
ata_bad_scsiop
(
Scsi_Cmnd
*
cmd
,
void
(
*
done
)(
Scsi_C
mnd
*
))
static
inline
void
ata_bad_scsiop
(
struct
scsi_cmnd
*
cmd
,
void
(
*
done
)(
struct
scsi_c
mnd
*
))
{
ata_scsi_badcmd
(
cmd
,
done
,
0x20
,
0x00
);
}
static
inline
void
ata_bad_cdb
(
Scsi_Cmnd
*
cmd
,
void
(
*
done
)(
Scsi_C
mnd
*
))
static
inline
void
ata_bad_cdb
(
struct
scsi_cmnd
*
cmd
,
void
(
*
done
)(
struct
scsi_c
mnd
*
))
{
ata_scsi_badcmd
(
cmd
,
done
,
0x24
,
0x00
);
}
...
...
drivers/scsi/sata_promise.c
View file @
361d16e2
...
...
@@ -34,10 +34,8 @@
#include <linux/libata.h>
#include <asm/io.h>
#undef DIRECT_HDMA
#define DRV_NAME "sata_promise"
#define DRV_VERSION "0.8
6
"
#define DRV_VERSION "0.8
9
"
enum
{
...
...
@@ -82,6 +80,42 @@ enum {
PDC_FLAG_20621
=
(
1
<<
30
),
/* we have a 20621 */
PDC_HDMA_RESET
=
(
1
<<
11
),
/* HDMA reset */
PDC_MAX_HDMA
=
32
,
PDC_HDMA_Q_MASK
=
(
PDC_MAX_HDMA
-
1
),
PDC_DIMM0_SPD_DEV_ADDRESS
=
0x50
,
PDC_DIMM1_SPD_DEV_ADDRESS
=
0x51
,
PDC_MAX_DIMM_MODULE
=
0x02
,
PDC_I2C_CONTROL_OFFSET
=
0x48
,
PDC_I2C_ADDR_DATA_OFFSET
=
0x4C
,
PDC_DIMM0_CONTROL_OFFSET
=
0x80
,
PDC_DIMM1_CONTROL_OFFSET
=
0x84
,
PDC_SDRAM_CONTROL_OFFSET
=
0x88
,
PDC_I2C_WRITE
=
0x00000000
,
PDC_I2C_READ
=
0x00000040
,
PDC_I2C_START
=
0x00000080
,
PDC_I2C_MASK_INT
=
0x00000020
,
PDC_I2C_COMPLETE
=
0x00010000
,
PDC_I2C_NO_ACK
=
0x00100000
,
PDC_DIMM_SPD_SUBADDRESS_START
=
0x00
,
PDC_DIMM_SPD_SUBADDRESS_END
=
0x7F
,
PDC_DIMM_SPD_ROW_NUM
=
3
,
PDC_DIMM_SPD_COLUMN_NUM
=
4
,
PDC_DIMM_SPD_MODULE_ROW
=
5
,
PDC_DIMM_SPD_TYPE
=
11
,
PDC_DIMM_SPD_FRESH_RATE
=
12
,
PDC_DIMM_SPD_BANK_NUM
=
17
,
PDC_DIMM_SPD_CAS_LATENCY
=
18
,
PDC_DIMM_SPD_ATTRIBUTE
=
21
,
PDC_DIMM_SPD_ROW_PRE_CHARGE
=
27
,
PDC_DIMM_SPD_ROW_ACTIVE_DELAY
=
28
,
PDC_DIMM_SPD_RAS_CAS_DELAY
=
29
,
PDC_DIMM_SPD_ACTIVE_PRECHARGE
=
30
,
PDC_DIMM_SPD_SYSTEM_FREQ
=
126
,
PDC_CTL_STATUS
=
0x08
,
PDC_DIMM_WINDOW_CTLR
=
0x0C
,
PDC_GENERAL_CTLR
=
0x484
,
};
...
...
@@ -91,6 +125,19 @@ struct pdc_port_priv {
dma_addr_t
pkt_dma
;
};
struct
pdc_host_priv
{
void
*
dimm_mmio
;
unsigned
int
doing_hdma
;
unsigned
int
hdma_prod
;
unsigned
int
hdma_cons
;
struct
{
struct
ata_queued_cmd
*
qc
;
unsigned
int
seq
;
unsigned
long
pkt_ofs
;
}
hdma
[
32
];
};
static
u32
pdc_sata_scr_read
(
struct
ata_port
*
ap
,
unsigned
int
sc_reg
);
static
void
pdc_sata_scr_write
(
struct
ata_port
*
ap
,
unsigned
int
sc_reg
,
u32
val
);
...
...
@@ -114,6 +161,18 @@ static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
static
void
pdc20621_host_stop
(
struct
ata_host_set
*
host_set
);
static
inline
void
pdc_dma_complete
(
struct
ata_port
*
ap
,
struct
ata_queued_cmd
*
qc
);
static
unsigned
int
pdc20621_dimm_init
(
struct
ata_probe_ent
*
pe
);
static
int
pdc20621_detect_dimm
(
struct
ata_probe_ent
*
pe
);
static
unsigned
int
pdc20621_i2c_read
(
struct
ata_probe_ent
*
pe
,
u32
device
,
u32
subaddr
,
u32
*
pdata
);
static
int
pdc20621_prog_dimm0
(
struct
ata_probe_ent
*
pe
);
static
unsigned
int
pdc20621_prog_dimm_global
(
struct
ata_probe_ent
*
pe
);
#ifdef ATA_VERBOSE_DEBUG
static
void
pdc20621_get_from_dimm
(
struct
ata_probe_ent
*
pe
,
void
*
psource
,
u32
offset
,
u32
size
);
#endif
static
void
pdc20621_put_to_dimm
(
struct
ata_probe_ent
*
pe
,
void
*
psource
,
u32
offset
,
u32
size
);
static
Scsi_Host_Template
pdc_sata_sht
=
{
...
...
@@ -131,6 +190,7 @@ static Scsi_Host_Template pdc_sata_sht = {
.
proc_name
=
DRV_NAME
,
.
dma_boundary
=
ATA_DMA_BOUNDARY
,
.
slave_configure
=
ata_scsi_slave_config
,
.
bios_param
=
ata_std_bios_param
,
};
static
struct
ata_port_operations
pdc_sata_ops
=
{
...
...
@@ -235,10 +295,11 @@ static struct pci_driver pdc_sata_pci_driver = {
static
void
pdc20621_host_stop
(
struct
ata_host_set
*
host_set
)
{
void
*
mmio
=
host_set
->
private_data
;
struct
pdc_host_priv
*
hpriv
=
host_set
->
private_data
;
void
*
dimm_mmio
=
hpriv
->
dimm_mmio
;
assert
(
mmio
!=
NULL
);
iounmap
(
mmio
);
iounmap
(
dimm_mmio
);
kfree
(
hpriv
);
}
static
int
pdc_port_start
(
struct
ata_port
*
ap
)
...
...
@@ -256,6 +317,7 @@ static int pdc_port_start(struct ata_port *ap)
rc
=
-
ENOMEM
;
goto
err_out
;
}
memset
(
pp
,
0
,
sizeof
(
*
pp
));
pp
->
pkt
=
pci_alloc_consistent
(
pdev
,
128
,
&
pp
->
pkt_dma
);
if
(
!
pp
->
pkt
)
{
...
...
@@ -589,7 +651,8 @@ static void pdc20621_fill_sg(struct ata_queued_cmd *qc)
struct
ata_port
*
ap
=
qc
->
ap
;
struct
pdc_port_priv
*
pp
=
ap
->
private_data
;
void
*
mmio
=
ap
->
host_set
->
mmio_base
;
void
*
dimm_mmio
=
ap
->
host_set
->
private_data
;
struct
pdc_host_priv
*
hpriv
=
ap
->
host_set
->
private_data
;
void
*
dimm_mmio
=
hpriv
->
dimm_mmio
;
unsigned
int
portno
=
ap
->
port_no
;
unsigned
int
i
,
last
,
idx
,
total_len
=
0
,
sgt_len
;
u32
*
buf
=
(
u32
*
)
&
pp
->
dimm_buf
[
PDC_DIMM_HEADER_SZ
];
...
...
@@ -605,8 +668,8 @@ static void pdc20621_fill_sg(struct ata_queued_cmd *qc)
last
=
qc
->
n_elem
;
idx
=
0
;
for
(
i
=
0
;
i
<
last
;
i
++
)
{
buf
[
idx
++
]
=
cpu_to_le32
(
sg
[
i
].
dma_address
);
buf
[
idx
++
]
=
cpu_to_le32
(
sg
[
i
].
length
);
buf
[
idx
++
]
=
cpu_to_le32
(
sg
_dma_address
(
&
sg
[
i
])
);
buf
[
idx
++
]
=
cpu_to_le32
(
sg
_dma_len
(
&
sg
[
i
])
);
total_len
+=
sg
[
i
].
length
;
}
buf
[
idx
-
1
]
|=
cpu_to_le32
(
ATA_PRD_EOT
);
...
...
@@ -643,49 +706,68 @@ static void pdc20621_fill_sg(struct ata_queued_cmd *qc)
VPRINTK
(
"ata pkt buf ofs %u, prd size %u, mmio copied
\n
"
,
i
,
sgt_len
);
}
#ifdef DIRECT_HDMA
static
void
pdc20621_push_hdma
(
struct
ata_queued_cmd
*
qc
)
static
void
__pdc20621_push_hdma
(
struct
ata_queued_cmd
*
qc
,
unsigned
int
seq
,
u32
pkt_ofs
)
{
struct
ata_port
*
ap
=
qc
->
ap
;
struct
ata_host_set
*
host_set
=
ap
->
host_set
;
unsigned
int
port_no
=
ap
->
port_no
;
void
*
mmio
=
host_set
->
mmio_base
;
unsigned
int
rw
=
(
qc
->
flags
&
ATA_QCFLAG_WRITE
);
u32
tmp
;
unsigned
int
host_sg
=
PDC_20621_DIMM_BASE
+
(
PDC_DIMM_WINDOW_STEP
*
port_no
)
+
PDC_DIMM_HOST_PRD
;
unsigned
int
dimm_sg
=
PDC_20621_DIMM_BASE
+
(
PDC_DIMM_WINDOW_STEP
*
port_no
)
+
PDC_DIMM_HPKT_PRD
;
/* hard-code chip #0 */
mmio
+=
PDC_CHIP0_OFS
;
tmp
=
readl
(
mmio
+
PDC_HDMA_CTLSTAT
)
&
0xffffff00
;
tmp
|=
port_no
+
1
+
4
;
/* seq. ID */
if
(
!
rw
)
tmp
|=
(
1
<<
6
);
/* hdma data direction */
writel
(
tmp
,
mmio
+
PDC_HDMA_CTLSTAT
);
/* note: stops DMA, if active */
readl
(
mmio
+
PDC_HDMA_CTLSTAT
);
/* flush */
writel
(
0x00000001
,
mmio
+
PDC_20621_SEQCTL
+
(
seq
*
4
));
readl
(
mmio
+
PDC_20621_SEQCTL
+
(
seq
*
4
));
/* flush */
writel
(
pkt_ofs
,
mmio
+
PDC_HDMA_PKT_SUBMIT
);
readl
(
mmio
+
PDC_HDMA_PKT_SUBMIT
);
/* flush */
}
static
void
pdc20621_push_hdma
(
struct
ata_queued_cmd
*
qc
,
unsigned
int
seq
,
u32
pkt_ofs
)
{
struct
ata_port
*
ap
=
qc
->
ap
;
struct
pdc_host_priv
*
pp
=
ap
->
host_set
->
private_data
;
unsigned
int
idx
=
pp
->
hdma_prod
&
PDC_HDMA_Q_MASK
;
writel
(
host_sg
,
mmio
+
0x108
);
writel
(
dimm_sg
,
mmio
+
0x10C
);
writel
(
0
,
mmio
+
0x128
);
if
(
!
pp
->
doing_hdma
)
{
__pdc20621_push_hdma
(
qc
,
seq
,
pkt_ofs
);
pp
->
doing_hdma
=
1
;
return
;
}
tmp
|=
(
1
<<
7
);
writel
(
tmp
,
mmio
+
PDC_HDMA_CTLSTAT
);
readl
(
mmio
+
PDC_HDMA_CTLSTAT
);
/* flush */
pp
->
hdma
[
idx
].
qc
=
qc
;
pp
->
hdma
[
idx
].
seq
=
seq
;
pp
->
hdma
[
idx
].
pkt_ofs
=
pkt_ofs
;
pp
->
hdma_prod
++
;
}
static
void
pdc20621_pop_hdma
(
struct
ata_queued_cmd
*
qc
)
{
struct
ata_port
*
ap
=
qc
->
ap
;
struct
pdc_host_priv
*
pp
=
ap
->
host_set
->
private_data
;
unsigned
int
idx
=
pp
->
hdma_cons
&
PDC_HDMA_Q_MASK
;
/* if nothing on queue, we're done */
if
(
pp
->
hdma_prod
==
pp
->
hdma_cons
)
{
pp
->
doing_hdma
=
0
;
return
;
}
__pdc20621_push_hdma
(
pp
->
hdma
[
idx
].
qc
,
pp
->
hdma
[
idx
].
seq
,
pp
->
hdma
[
idx
].
pkt_ofs
);
pp
->
hdma_cons
++
;
}
#endif
#ifdef ATA_VERBOSE_DEBUG
static
void
pdc20621_dump_hdma
(
struct
ata_queued_cmd
*
qc
)
{
struct
ata_port
*
ap
=
qc
->
ap
;
unsigned
int
port_no
=
ap
->
port_no
;
void
*
dimm_mmio
=
ap
->
host_set
->
private_data
;
struct
pdc_host_priv
*
hpriv
=
ap
->
host_set
->
private_data
;
void
*
dimm_mmio
=
hpriv
->
dimm_mmio
;
dimm_mmio
+=
(
port_no
*
PDC_DIMM_WINDOW_STEP
);
dimm_mmio
+=
PDC_DIMM_HOST_PKT
;
...
...
@@ -724,23 +806,17 @@ static void pdc20621_dma_start(struct ata_queued_cmd *qc)
wmb
();
/* flush PRD, pkt writes */
writel
(
0x00000001
,
mmio
+
PDC_20621_SEQCTL
+
(
seq
*
4
));
readl
(
mmio
+
PDC_20621_SEQCTL
+
(
seq
*
4
));
/* flush */
if
(
doing_hdma
)
{
pdc20621_dump_hdma
(
qc
);
#ifdef DIRECT_HDMA
pdc20621_push_hdma
(
qc
);
#else
writel
(
port_ofs
+
PDC_DIMM_HOST_PKT
,
mmio
+
PDC_HDMA_PKT_SUBMIT
);
readl
(
mmio
+
PDC_HDMA_PKT_SUBMIT
);
/* flush */
#endif
VPRINTK
(
"submitted ofs 0x%x (%u), seq %u
\n
"
,
port_ofs
+
PDC_DIMM_HOST_PKT
,
port_ofs
+
PDC_DIMM_HOST_PKT
,
seq
);
pdc20621_push_hdma
(
qc
,
seq
,
port_ofs
+
PDC_DIMM_HOST_PKT
);
VPRINTK
(
"queued ofs 0x%x (%u), seq %u
\n
"
,
port_ofs
+
PDC_DIMM_HOST_PKT
,
port_ofs
+
PDC_DIMM_HOST_PKT
,
seq
);
}
else
{
writel
(
0x00000001
,
mmio
+
PDC_20621_SEQCTL
+
(
seq
*
4
));
readl
(
mmio
+
PDC_20621_SEQCTL
+
(
seq
*
4
));
/* flush */
writel
(
port_ofs
+
PDC_DIMM_ATA_PKT
,
(
void
*
)
ap
->
ioaddr
.
cmd_addr
+
PDC_PKT_SUBMIT
);
readl
((
void
*
)
ap
->
ioaddr
.
cmd_addr
+
PDC_PKT_SUBMIT
);
...
...
@@ -771,6 +847,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
VPRINTK
(
"ata%u: read hdma, 0x%x 0x%x
\n
"
,
ap
->
id
,
readl
(
mmio
+
0x104
),
readl
(
mmio
+
PDC_HDMA_CTLSTAT
));
pdc_dma_complete
(
ap
,
qc
);
pdc20621_pop_hdma
(
qc
);
}
/* step one - exec ATA command */
...
...
@@ -781,15 +858,8 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
/* submit hdma pkt */
pdc20621_dump_hdma
(
qc
);
writel
(
0x00000001
,
mmio
+
PDC_20621_SEQCTL
+
(
seq
*
4
));
readl
(
mmio
+
PDC_20621_SEQCTL
+
(
seq
*
4
));
#ifdef DIRECT_HDMA
pdc20621_push_hdma
(
qc
);
#else
writel
(
port_ofs
+
PDC_DIMM_HOST_PKT
,
mmio
+
PDC_HDMA_PKT_SUBMIT
);
readl
(
mmio
+
PDC_HDMA_PKT_SUBMIT
);
#endif
pdc20621_push_hdma
(
qc
,
seq
,
port_ofs
+
PDC_DIMM_HOST_PKT
);
}
handled
=
1
;
break
;
...
...
@@ -814,6 +884,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
VPRINTK
(
"ata%u: write ata, 0x%x 0x%x
\n
"
,
ap
->
id
,
readl
(
mmio
+
0x104
),
readl
(
mmio
+
PDC_HDMA_CTLSTAT
));
pdc_dma_complete
(
ap
,
qc
);
pdc20621_pop_hdma
(
qc
);
}
handled
=
1
;
break
;
...
...
@@ -1098,11 +1169,373 @@ static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base)
port
->
ctl_addr
=
base
+
0x38
;
}
#ifdef ATA_VERBOSE_DEBUG
static
void
pdc20621_get_from_dimm
(
struct
ata_probe_ent
*
pe
,
void
*
psource
,
u32
offset
,
u32
size
)
{
u32
window_size
;
u16
idx
;
u8
page_mask
;
long
dist
;
void
*
mmio
=
pe
->
mmio_base
;
struct
pdc_host_priv
*
hpriv
=
pe
->
private_data
;
void
*
dimm_mmio
=
hpriv
->
dimm_mmio
;
/* hard-code chip #0 */
mmio
+=
PDC_CHIP0_OFS
;
page_mask
=
0x00
;
window_size
=
0x2000
*
4
;
/* 32K byte uchar size */
idx
=
(
u16
)
(
offset
/
window_size
);
writel
(
0x01
,
mmio
+
PDC_GENERAL_CTLR
);
readl
(
mmio
+
PDC_GENERAL_CTLR
);
writel
(((
idx
)
<<
page_mask
),
mmio
+
PDC_DIMM_WINDOW_CTLR
);
readl
(
mmio
+
PDC_DIMM_WINDOW_CTLR
);
offset
-=
(
idx
*
window_size
);
idx
++
;
dist
=
((
long
)
(
window_size
-
(
offset
+
size
)))
>=
0
?
size
:
(
long
)
(
window_size
-
offset
);
memcpy_fromio
((
char
*
)
psource
,
(
char
*
)
(
dimm_mmio
+
offset
/
4
),
dist
);
psource
+=
dist
;
size
-=
dist
;
for
(;
(
long
)
size
>=
(
long
)
window_size
;)
{
writel
(
0x01
,
mmio
+
PDC_GENERAL_CTLR
);
readl
(
mmio
+
PDC_GENERAL_CTLR
);
writel
(((
idx
)
<<
page_mask
),
mmio
+
PDC_DIMM_WINDOW_CTLR
);
readl
(
mmio
+
PDC_DIMM_WINDOW_CTLR
);
memcpy_fromio
((
char
*
)
psource
,
(
char
*
)
(
dimm_mmio
),
window_size
/
4
);
psource
+=
window_size
;
size
-=
window_size
;
idx
++
;
}
if
(
size
)
{
writel
(
0x01
,
mmio
+
PDC_GENERAL_CTLR
);
readl
(
mmio
+
PDC_GENERAL_CTLR
);
writel
(((
idx
)
<<
page_mask
),
mmio
+
PDC_DIMM_WINDOW_CTLR
);
readl
(
mmio
+
PDC_DIMM_WINDOW_CTLR
);
memcpy_fromio
((
char
*
)
psource
,
(
char
*
)
(
dimm_mmio
),
size
/
4
);
}
}
#endif
static
void
pdc20621_put_to_dimm
(
struct
ata_probe_ent
*
pe
,
void
*
psource
,
u32
offset
,
u32
size
)
{
u32
window_size
;
u16
idx
;
u8
page_mask
;
long
dist
;
void
*
mmio
=
pe
->
mmio_base
;
struct
pdc_host_priv
*
hpriv
=
pe
->
private_data
;
void
*
dimm_mmio
=
hpriv
->
dimm_mmio
;
/* hard-code chip #0 */
mmio
+=
PDC_CHIP0_OFS
;
page_mask
=
0x00
;
window_size
=
0x2000
*
4
;
/* 32K byte uchar size */
idx
=
(
u16
)
(
offset
/
window_size
);
writel
(((
idx
)
<<
page_mask
),
mmio
+
PDC_DIMM_WINDOW_CTLR
);
readl
(
mmio
+
PDC_DIMM_WINDOW_CTLR
);
offset
-=
(
idx
*
window_size
);
idx
++
;
dist
=
((
long
)
(
window_size
-
(
offset
+
size
)))
>=
0
?
size
:
(
long
)
(
window_size
-
offset
);
memcpy_toio
((
char
*
)
(
dimm_mmio
+
offset
/
4
),
(
char
*
)
psource
,
dist
);
writel
(
0x01
,
mmio
+
PDC_GENERAL_CTLR
);
readl
(
mmio
+
PDC_GENERAL_CTLR
);
psource
+=
dist
;
size
-=
dist
;
for
(;
(
long
)
size
>=
(
long
)
window_size
;)
{
writel
(((
idx
)
<<
page_mask
),
mmio
+
PDC_DIMM_WINDOW_CTLR
);
readl
(
mmio
+
PDC_DIMM_WINDOW_CTLR
);
memcpy_toio
((
char
*
)
(
dimm_mmio
),
(
char
*
)
psource
,
window_size
/
4
);
writel
(
0x01
,
mmio
+
PDC_GENERAL_CTLR
);
readl
(
mmio
+
PDC_GENERAL_CTLR
);
psource
+=
window_size
;
size
-=
window_size
;
idx
++
;
}
if
(
size
)
{
writel
(((
idx
)
<<
page_mask
),
mmio
+
PDC_DIMM_WINDOW_CTLR
);
readl
(
mmio
+
PDC_DIMM_WINDOW_CTLR
);
memcpy_toio
((
char
*
)
(
dimm_mmio
),
(
char
*
)
psource
,
size
/
4
);
writel
(
0x01
,
mmio
+
PDC_GENERAL_CTLR
);
readl
(
mmio
+
PDC_GENERAL_CTLR
);
}
}
static
unsigned
int
pdc20621_i2c_read
(
struct
ata_probe_ent
*
pe
,
u32
device
,
u32
subaddr
,
u32
*
pdata
)
{
void
*
mmio
=
pe
->
mmio_base
;
u32
i2creg
=
0
;
u32
status
;
u32
count
=
0
;
/* hard-code chip #0 */
mmio
+=
PDC_CHIP0_OFS
;
i2creg
|=
device
<<
24
;
i2creg
|=
subaddr
<<
16
;
/* Set the device and subaddress */
writel
(
i2creg
,
mmio
+
PDC_I2C_ADDR_DATA_OFFSET
);
readl
(
mmio
+
PDC_I2C_ADDR_DATA_OFFSET
);
/* Write Control to perform read operation, mask int */
writel
(
PDC_I2C_READ
|
PDC_I2C_START
|
PDC_I2C_MASK_INT
,
mmio
+
PDC_I2C_CONTROL_OFFSET
);
for
(
count
=
0
;
count
<=
1000
;
count
++
)
{
status
=
readl
(
mmio
+
PDC_I2C_CONTROL_OFFSET
);
if
(
status
&
PDC_I2C_COMPLETE
)
{
status
=
readl
(
mmio
+
PDC_I2C_ADDR_DATA_OFFSET
);
break
;
}
else
if
(
count
==
1000
)
return
0
;
}
*
pdata
=
(
status
>>
8
)
&
0x000000ff
;
return
1
;
}
static
int
pdc20621_detect_dimm
(
struct
ata_probe_ent
*
pe
)
{
u32
data
=
0
;
if
(
pdc20621_i2c_read
(
pe
,
PDC_DIMM0_SPD_DEV_ADDRESS
,
PDC_DIMM_SPD_SYSTEM_FREQ
,
&
data
))
{
if
(
data
==
100
)
return
100
;
}
else
return
0
;
if
(
pdc20621_i2c_read
(
pe
,
PDC_DIMM0_SPD_DEV_ADDRESS
,
9
,
&
data
))
{
if
(
data
<=
0x75
)
return
133
;
}
else
return
0
;
return
0
;
}
static
int
pdc20621_prog_dimm0
(
struct
ata_probe_ent
*
pe
)
{
u32
spd0
[
50
];
u32
data
=
0
;
int
size
,
i
;
u8
bdimmsize
;
void
*
mmio
=
pe
->
mmio_base
;
static
const
struct
{
unsigned
int
reg
;
unsigned
int
ofs
;
}
pdc_i2c_read_data
[]
=
{
{
PDC_DIMM_SPD_TYPE
,
11
},
{
PDC_DIMM_SPD_FRESH_RATE
,
12
},
{
PDC_DIMM_SPD_COLUMN_NUM
,
4
},
{
PDC_DIMM_SPD_ATTRIBUTE
,
21
},
{
PDC_DIMM_SPD_ROW_NUM
,
3
},
{
PDC_DIMM_SPD_BANK_NUM
,
17
},
{
PDC_DIMM_SPD_MODULE_ROW
,
5
},
{
PDC_DIMM_SPD_ROW_PRE_CHARGE
,
27
},
{
PDC_DIMM_SPD_ROW_ACTIVE_DELAY
,
28
},
{
PDC_DIMM_SPD_RAS_CAS_DELAY
,
29
},
{
PDC_DIMM_SPD_ACTIVE_PRECHARGE
,
30
},
{
PDC_DIMM_SPD_CAS_LATENCY
,
18
},
};
/* hard-code chip #0 */
mmio
+=
PDC_CHIP0_OFS
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
pdc_i2c_read_data
);
i
++
)
pdc20621_i2c_read
(
pe
,
PDC_DIMM0_SPD_DEV_ADDRESS
,
pdc_i2c_read_data
[
i
].
reg
,
&
spd0
[
pdc_i2c_read_data
[
i
].
ofs
]);
data
|=
(
spd0
[
4
]
-
8
)
|
((
spd0
[
21
]
!=
0
)
<<
3
)
|
((
spd0
[
3
]
-
11
)
<<
4
);
data
|=
((
spd0
[
17
]
/
4
)
<<
6
)
|
((
spd0
[
5
]
/
2
)
<<
7
)
|
((((
spd0
[
27
]
+
9
)
/
10
)
-
1
)
<<
8
)
;
data
|=
(((((
spd0
[
29
]
>
spd0
[
28
])
?
spd0
[
29
]
:
spd0
[
28
])
+
9
)
/
10
)
-
1
)
<<
10
;
data
|=
((
spd0
[
30
]
-
spd0
[
29
]
+
9
)
/
10
-
2
)
<<
12
;
if
(
spd0
[
18
]
&
0x08
)
data
|=
((
0x03
)
<<
14
);
else
if
(
spd0
[
18
]
&
0x04
)
data
|=
((
0x02
)
<<
14
);
else
if
(
spd0
[
18
]
&
0x01
)
data
|=
((
0x01
)
<<
14
);
else
data
|=
(
0
<<
14
);
/*
Calculate the size of bDIMMSize (power of 2) and
merge the DIMM size by program start/end address.
*/
bdimmsize
=
spd0
[
4
]
+
(
spd0
[
5
]
/
2
)
+
spd0
[
3
]
+
(
spd0
[
17
]
/
2
)
+
3
;
size
=
(
1
<<
bdimmsize
)
>>
20
;
/* size = xxx(MB) */
data
|=
(((
size
/
16
)
-
1
)
<<
16
);
data
|=
(
0
<<
23
);
data
|=
8
;
writel
(
data
,
mmio
+
PDC_DIMM0_CONTROL_OFFSET
);
readl
(
mmio
+
PDC_DIMM0_CONTROL_OFFSET
);
return
size
;
}
static
unsigned
int
pdc20621_prog_dimm_global
(
struct
ata_probe_ent
*
pe
)
{
u32
data
,
spd0
;
int
error
,
i
;
void
*
mmio
=
pe
->
mmio_base
;
/* hard-code chip #0 */
mmio
+=
PDC_CHIP0_OFS
;
/*
Set To Default : DIMM Module Global Control Register (0x022259F1)
DIMM Arbitration Disable (bit 20)
DIMM Data/Control Output Driving Selection (bit12 - bit15)
Refresh Enable (bit 17)
*/
data
=
0x022259F1
;
writel
(
data
,
mmio
+
PDC_SDRAM_CONTROL_OFFSET
);
readl
(
mmio
+
PDC_SDRAM_CONTROL_OFFSET
);
/* Turn on for ECC */
pdc20621_i2c_read
(
pe
,
PDC_DIMM0_SPD_DEV_ADDRESS
,
PDC_DIMM_SPD_TYPE
,
&
spd0
);
if
(
spd0
==
0x02
)
{
data
|=
(
0x01
<<
16
);
writel
(
data
,
mmio
+
PDC_SDRAM_CONTROL_OFFSET
);
readl
(
mmio
+
PDC_SDRAM_CONTROL_OFFSET
);
printk
(
KERN_ERR
"Local DIMM ECC Enabled
\n
"
);
}
/* DIMM Initialization Select/Enable (bit 18/19) */
data
&=
(
~
(
1
<<
18
));
data
|=
(
1
<<
19
);
writel
(
data
,
mmio
+
PDC_SDRAM_CONTROL_OFFSET
);
error
=
1
;
for
(
i
=
1
;
i
<=
10
;
i
++
)
{
/* polling ~5 secs */
data
=
readl
(
mmio
+
PDC_SDRAM_CONTROL_OFFSET
);
if
(
!
(
data
&
(
1
<<
19
)))
{
error
=
0
;
break
;
}
set_current_state
(
TASK_INTERRUPTIBLE
);
schedule_timeout
((
i
*
100
)
*
HZ
/
1000
);
}
return
error
;
}
static
unsigned
int
pdc20621_dimm_init
(
struct
ata_probe_ent
*
pe
)
{
int
speed
,
size
,
length
;
u32
addr
,
spd0
,
pci_status
;
u32
tmp
=
0
;
void
*
mmio
=
pe
->
mmio_base
;
/* hard-code chip #0 */
mmio
+=
PDC_CHIP0_OFS
;
/* Initialize PLL. */
pci_status
=
0x8a531824
;
writel
(
pci_status
,
mmio
+
PDC_CTL_STATUS
);
readl
(
mmio
+
PDC_CTL_STATUS
);
/*
Read SPD of DIMM by I2C interface,
and program the DIMM Module Controller.
*/
if
(
!
(
speed
=
pdc20621_detect_dimm
(
pe
)))
{
printk
(
KERN_ERR
"Detect Local DIMM Fail
\n
"
);
return
1
;
/* DIMM error */
}
VPRINTK
(
"Local DIMM Speed = %d
\n
"
,
speed
);
/* Programming DIMM0 Module Control Register (index_CID0:80h) */
size
=
pdc20621_prog_dimm0
(
pe
);
VPRINTK
(
"Local DIMM Size = %dMB
\n
"
,
size
);
/* Programming DIMM Module Global Control Register (index_CID0:88h) */
if
(
pdc20621_prog_dimm_global
(
pe
))
{
printk
(
KERN_ERR
"Programming DIMM Module Global Control Register Fail
\n
"
);
return
1
;
}
#ifdef ATA_VERBOSE_DEBUG
{
u8
test_parttern1
[
40
]
=
{
0x55
,
0xAA
,
'P'
,
'r'
,
'o'
,
'm'
,
'i'
,
's'
,
'e'
,
' '
,
'N'
,
'o'
,
't'
,
' '
,
'Y'
,
'e'
,
't'
,
' '
,
'D'
,
'e'
,
'f'
,
'i'
,
'n'
,
'e'
,
'd'
,
' '
,
'1'
,
'.'
,
'1'
,
'0'
,
'9'
,
'8'
,
'0'
,
'3'
,
'1'
,
'6'
,
'1'
,
'2'
,
0
,
0
};
u8
test_parttern2
[
40
]
=
{
0
};
pdc20621_put_to_dimm
(
pe
,
(
void
*
)
test_parttern2
,
0x10040
,
40
);
pdc20621_put_to_dimm
(
pe
,
(
void
*
)
test_parttern2
,
0x40
,
40
);
pdc20621_put_to_dimm
(
pe
,
(
void
*
)
test_parttern1
,
0x10040
,
40
);
pdc20621_get_from_dimm
(
pe
,
(
void
*
)
test_parttern2
,
0x40
,
40
);
printk
(
KERN_ERR
"%x, %x, %s
\n
"
,
test_parttern2
[
0
],
test_parttern2
[
1
],
&
(
test_parttern2
[
2
]));
pdc20621_get_from_dimm
(
pe
,
(
void
*
)
test_parttern2
,
0x10040
,
40
);
printk
(
KERN_ERR
"%x, %x, %s
\n
"
,
test_parttern2
[
0
],
test_parttern2
[
1
],
&
(
test_parttern2
[
2
]));
pdc20621_put_to_dimm
(
pe
,
(
void
*
)
test_parttern1
,
0x40
,
40
);
pdc20621_get_from_dimm
(
pe
,
(
void
*
)
test_parttern2
,
0x40
,
40
);
printk
(
KERN_ERR
"%x, %x, %s
\n
"
,
test_parttern2
[
0
],
test_parttern2
[
1
],
&
(
test_parttern2
[
2
]));
}
#endif
/* ECC initiliazation. */
pdc20621_i2c_read
(
pe
,
PDC_DIMM0_SPD_DEV_ADDRESS
,
PDC_DIMM_SPD_TYPE
,
&
spd0
);
if
(
spd0
==
0x02
)
{
VPRINTK
(
"Start ECC initialization
\n
"
);
addr
=
0
;
length
=
size
*
1024
*
1024
;
while
(
addr
<
length
)
{
pdc20621_put_to_dimm
(
pe
,
(
void
*
)
&
tmp
,
addr
,
sizeof
(
u32
));
addr
+=
sizeof
(
u32
);
}
VPRINTK
(
"Finish ECC initialization
\n
"
);
}
return
0
;
}
static
void
pdc_20621_init
(
struct
ata_probe_ent
*
pe
)
{
u32
tmp
;
void
*
mmio
=
pe
->
mmio_base
;
/* hard-code chip #0 */
mmio
+=
PDC_CHIP0_OFS
;
/*
...
...
@@ -1170,6 +1603,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
struct
ata_probe_ent
*
probe_ent
=
NULL
;
unsigned
long
base
;
void
*
mmio_base
,
*
dimm_mmio
=
NULL
;
struct
pdc_host_priv
*
hpriv
=
NULL
;
unsigned
int
board_idx
=
(
unsigned
int
)
ent
->
driver_data
;
unsigned
int
have_20621
=
(
board_idx
==
board_20621
);
int
rc
;
...
...
@@ -1212,12 +1646,22 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
base
=
(
unsigned
long
)
mmio_base
;
if
(
have_20621
)
{
hpriv
=
kmalloc
(
sizeof
(
*
hpriv
),
GFP_KERNEL
);
if
(
!
hpriv
)
{
rc
=
-
ENOMEM
;
goto
err_out_iounmap
;
}
memset
(
hpriv
,
0
,
sizeof
(
*
hpriv
));
dimm_mmio
=
ioremap
(
pci_resource_start
(
pdev
,
4
),
pci_resource_len
(
pdev
,
4
));
if
(
!
dimm_mmio
)
{
kfree
(
hpriv
);
rc
=
-
ENOMEM
;
goto
err_out_iounmap
;
}
hpriv
->
dimm_mmio
=
dimm_mmio
;
}
probe_ent
->
sht
=
pdc_port_info
[
board_idx
].
sht
;
...
...
@@ -1231,7 +1675,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
probe_ent
->
mmio_base
=
mmio_base
;
if
(
have_20621
)
{
probe_ent
->
private_data
=
dimm_mmio
;
probe_ent
->
private_data
=
hpriv
;
base
+=
PDC_CHIP0_OFS
;
}
...
...
@@ -1268,9 +1712,14 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
pci_set_master
(
pdev
);
/* initialize adapter */
if
(
have_20621
)
if
(
have_20621
)
{
/* initialize local dimm */
if
(
pdc20621_dimm_init
(
probe_ent
))
{
rc
=
-
ENOMEM
;
goto
err_out_iounmap_dimm
;
}
pdc_20621_init
(
probe_ent
);
else
}
else
pdc_host_init
(
board_idx
,
probe_ent
);
/* FIXME: check ata_device_add return value */
...
...
@@ -1279,6 +1728,9 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
return
0
;
err_out_iounmap_dimm:
/* only get to this label if 20621 */
kfree
(
hpriv
);
iounmap
(
dimm_mmio
);
err_out_iounmap:
iounmap
(
mmio_base
);
err_out_free_ent:
...
...
drivers/scsi/sata_sil.c
View file @
361d16e2
...
...
@@ -87,6 +87,7 @@ static Scsi_Host_Template sil_sht = {
.
proc_name
=
DRV_NAME
,
.
dma_boundary
=
ATA_DMA_BOUNDARY
,
.
slave_configure
=
ata_scsi_slave_config
,
.
bios_param
=
ata_std_bios_param
,
};
static
struct
ata_port_operations
sil_ops
=
{
...
...
drivers/scsi/sata_svw.c
View file @
361d16e2
...
...
@@ -219,6 +219,7 @@ static Scsi_Host_Template k2_sata_sht = {
#ifdef CONFIG_ALL_PPC
.
proc_info
=
k2_sata_proc_info
#endif
.
bios_param
=
ata_std_bios_param
,
};
...
...
drivers/scsi/sata_via.c
View file @
361d16e2
...
...
@@ -78,6 +78,7 @@ static Scsi_Host_Template svia_sht = {
.
proc_name
=
DRV_NAME
,
.
dma_boundary
=
ATA_DMA_BOUNDARY
,
.
slave_configure
=
ata_scsi_slave_config
,
.
bios_param
=
ata_std_bios_param
,
};
static
struct
ata_port_operations
svia_sata_ops
=
{
...
...
drivers/usb/host/uhci-hcd.c
View file @
361d16e2
...
...
@@ -2182,6 +2182,9 @@ static int uhci_reset(struct usb_hcd *hcd)
uhci
->
io_addr
=
(
unsigned
long
)
hcd
->
regs
;
/* Turn off all interrupts */
outw
(
0
,
uhci
->
io_addr
+
USBINTR
);
/* Maybe kick BIOS off this hardware. Then reset, so we won't get
* interrupts from any previous setup.
*/
...
...
drivers/usb/input/hid-core.c
View file @
361d16e2
...
...
@@ -1354,6 +1354,9 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_A4TECH 0x09DA
#define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006
#define USB_VENDOR_ID_BERKSHIRE 0x0c98
#define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140
struct
hid_blacklist
{
__u16
idVendor
;
__u16
idProduct
;
...
...
@@ -1403,6 +1406,7 @@ struct hid_blacklist {
{
USB_VENDOR_ID_TANGTOP
,
USB_DEVICE_ID_TANGTOP_USBPS2
,
HID_QUIRK_NOGET
},
{
USB_VENDOR_ID_ESSENTIAL_REALITY
,
USB_DEVICE_ID_ESSENTIAL_REALITY_P5
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_A4TECH
,
USB_DEVICE_ID_A4TECH_WCP32PU
,
HID_QUIRK_2WHEEL_MOUSE_HACK
},
{
USB_VENDOR_ID_BERKSHIRE
,
USB_DEVICE_ID_BERKSHIRE_PCWD
,
HID_QUIRK_IGNORE
},
{
0
,
0
}
};
...
...
include/asm-i386/irq.h
View file @
361d16e2
...
...
@@ -24,6 +24,7 @@ extern void disable_irq(unsigned int);
extern
void
disable_irq_nosync
(
unsigned
int
);
extern
void
enable_irq
(
unsigned
int
);
extern
void
release_x86_irqs
(
struct
task_struct
*
);
extern
int
can_request_irq
(
unsigned
int
,
unsigned
long
flags
);
#ifdef CONFIG_X86_LOCAL_APIC
#define ARCH_HAS_NMI_WATCHDOG
/* See include/linux/nmi.h */
...
...
include/linux/input.h
View file @
361d16e2
...
...
@@ -870,6 +870,7 @@ struct input_handler {
char
*
name
;
struct
input_device_id
*
id_table
;
struct
input_device_id
*
blacklist
;
struct
list_head
h_list
;
struct
list_head
node
;
...
...
include/linux/keyboard.h
View file @
361d16e2
...
...
@@ -2,7 +2,6 @@
#define __LINUX_KEYBOARD_H
#include <linux/wait.h>
#include <linux/input.h>
#define KG_SHIFT 0
#define KG_CTRL 2
...
...
@@ -17,7 +16,7 @@
#define NR_SHIFT 9
#define NR_KEYS
(KEY_MAX+1)
#define NR_KEYS
255
#define MAX_NR_KEYMAPS 256
/* This means 128Kb if all keymaps are allocated. Only the superuser
may increase the number of keymaps beyond MAX_NR_OF_USER_KEYMAPS. */
...
...
include/linux/libata.h
View file @
361d16e2
...
...
@@ -28,6 +28,7 @@
#include <asm/io.h>
#include <linux/ata.h>
/*
* compile-time options
*/
...
...
@@ -66,8 +67,6 @@
/* defines only for the constants which don't work well as enums */
#define ATA_TAG_POISON 0xfafbfcfdU
#define ATA_DMA_BOUNDARY 0xffffUL
#define ATA_DMA_MASK 0xffffffffULL
enum
{
/* various global constants */
...
...
@@ -171,6 +170,7 @@ enum {
};
/* forward declarations */
struct
scsi_device
;
struct
ata_port_operations
;
struct
ata_port
;
struct
ata_queued_cmd
;
...
...
@@ -247,8 +247,8 @@ struct ata_queued_cmd {
struct
ata_port
*
ap
;
struct
ata_device
*
dev
;
Scsi_C
mnd
*
scsicmd
;
void
(
*
scsidone
)(
Scsi_C
mnd
*
);
struct
scsi_c
mnd
*
scsicmd
;
void
(
*
scsidone
)(
struct
scsi_c
mnd
*
);
struct
list_head
node
;
unsigned
long
flags
;
/* ATA_QCFLAG_xxx */
...
...
@@ -403,7 +403,7 @@ extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_i
extern
void
ata_pci_remove_one
(
struct
pci_dev
*
pdev
);
extern
int
ata_device_add
(
struct
ata_probe_ent
*
ent
);
extern
int
ata_scsi_detect
(
Scsi_Host_Template
*
sht
);
extern
int
ata_scsi_queuecmd
(
Scsi_Cmnd
*
cmd
,
void
(
*
done
)(
Scsi_C
mnd
*
));
extern
int
ata_scsi_queuecmd
(
struct
scsi_cmnd
*
cmd
,
void
(
*
done
)(
struct
scsi_c
mnd
*
));
extern
int
ata_scsi_error
(
struct
Scsi_Host
*
host
);
extern
int
ata_scsi_release
(
struct
Scsi_Host
*
host
);
extern
int
ata_scsi_slave_config
(
struct
scsi_device
*
sdev
);
...
...
@@ -427,6 +427,9 @@ extern void ata_bmdma_start_pio (struct ata_queued_cmd *qc);
extern
int
pci_test_config_bits
(
struct
pci_dev
*
pdev
,
struct
pci_bits
*
bits
);
extern
void
ata_qc_complete
(
struct
ata_queued_cmd
*
qc
,
u8
drv_stat
,
unsigned
int
done_late
);
extern
void
ata_eng_timeout
(
struct
ata_port
*
ap
);
extern
int
ata_std_bios_param
(
struct
scsi_device
*
sdev
,
struct
block_device
*
bdev
,
sector_t
capacity
,
int
geom
[]);
static
inline
unsigned
long
msecs_to_jiffies
(
unsigned
long
msecs
)
...
...
include/linux/serio.h
View file @
361d16e2
...
...
@@ -49,6 +49,7 @@ struct serio_dev {
irqreturn_t
(
*
interrupt
)(
struct
serio
*
,
unsigned
char
,
unsigned
int
,
struct
pt_regs
*
);
void
(
*
connect
)(
struct
serio
*
,
struct
serio_dev
*
dev
);
int
(
*
reconnect
)(
struct
serio
*
);
void
(
*
disconnect
)(
struct
serio
*
);
void
(
*
cleanup
)(
struct
serio
*
);
...
...
@@ -58,12 +59,15 @@ struct serio_dev {
int
serio_open
(
struct
serio
*
serio
,
struct
serio_dev
*
dev
);
void
serio_close
(
struct
serio
*
serio
);
void
serio_rescan
(
struct
serio
*
serio
);
void
serio_reconnect
(
struct
serio
*
serio
);
irqreturn_t
serio_interrupt
(
struct
serio
*
serio
,
unsigned
char
data
,
unsigned
int
flags
,
struct
pt_regs
*
regs
);
void
serio_register_port
(
struct
serio
*
serio
);
void
serio_register_slave_port
(
struct
serio
*
serio
);
void
serio_register_port_delayed
(
struct
serio
*
serio
);
void
__serio_register_port
(
struct
serio
*
serio
);
void
serio_unregister_port
(
struct
serio
*
serio
);
void
serio_unregister_slave_port
(
struct
serio
*
serio
);
void
serio_unregister_port_delayed
(
struct
serio
*
serio
);
void
__serio_unregister_port
(
struct
serio
*
serio
);
void
serio_register_device
(
struct
serio_dev
*
dev
);
void
serio_unregister_device
(
struct
serio_dev
*
dev
);
...
...
kernel/sched.c
View file @
361d16e2
...
...
@@ -1470,6 +1470,7 @@ void scheduling_functions_start_here(void) { }
*/
asmlinkage
void
schedule
(
void
)
{
long
*
switch_count
;
task_t
*
prev
,
*
next
;
runqueue_t
*
rq
;
prio_array_t
*
array
;
...
...
@@ -1516,32 +1517,25 @@ asmlinkage void schedule(void)
* if entering off of a kernel preemption go straight
* to picking the next task.
*/
if
(
unlikely
(
preempt_count
()
&
PREEMPT_ACTIVE
))
goto
pick_next_task
;
switch
(
prev
->
state
)
{
case
TASK_INTERRUPTIBLE
:
if
(
unlikely
(
signal_pending
(
prev
)))
{
switch_count
=
&
prev
->
nivcsw
;
if
(
prev
->
state
&&
!
(
preempt_count
()
&
PREEMPT_ACTIVE
))
{
switch_count
=
&
prev
->
nvcsw
;
if
(
unlikely
((
prev
->
state
&
TASK_INTERRUPTIBLE
)
&&
unlikely
(
signal_pending
(
prev
))))
prev
->
state
=
TASK_RUNNING
;
break
;
}
default:
deactivate_task
(
prev
,
rq
);
prev
->
nvcsw
++
;
break
;
case
TASK_RUNNING
:
prev
->
nivcsw
++
;
else
deactivate_task
(
prev
,
rq
);
}
pick_next_task:
if
(
unlikely
(
!
rq
->
nr_running
))
{
#ifdef CONFIG_SMP
load_balance
(
rq
,
1
,
cpu_to_node_mask
(
smp_processor_id
()));
if
(
rq
->
nr_running
)
goto
pick_next_task
;
#endif
next
=
rq
->
idle
;
rq
->
expired_timestamp
=
0
;
goto
switch_tasks
;
if
(
!
rq
->
nr_running
)
{
next
=
rq
->
idle
;
rq
->
expired_timestamp
=
0
;
goto
switch_tasks
;
}
}
array
=
rq
->
active
;
...
...
@@ -1588,6 +1582,7 @@ asmlinkage void schedule(void)
next
->
timestamp
=
now
;
rq
->
nr_switches
++
;
rq
->
curr
=
next
;
++*
switch_count
;
prepare_arch_switch
(
rq
,
next
);
prev
=
context_switch
(
rq
,
prev
,
next
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment