diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-02-13 01:43:25 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-02-13 01:43:25 -0500 |
commit | d9bc125caf592b7d081021f32ce5b717efdf70c8 (patch) | |
tree | 263b7066ba22ddce21db610c0300f6eaac6f2064 /drivers/char | |
parent | 43d78ef2ba5bec26d0315859e8324bfc0be23766 (diff) | |
parent | ec2f9d1331f658433411c58077871e1eef4ee1b4 (diff) |
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Conflicts:
net/sunrpc/auth_gss/gss_krb5_crypto.c
net/sunrpc/auth_gss/gss_spkm3_token.c
net/sunrpc/clnt.c
Merge with mainline and fix conflicts.
Diffstat (limited to 'drivers/char')
88 files changed, 4841 insertions, 4824 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 9e43e39dc35c..d0a6dc53213c 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -191,7 +191,7 @@ config MOXA_INTELLIO | |||
191 | module will be called moxa. | 191 | module will be called moxa. |
192 | 192 | ||
193 | config MOXA_SMARTIO | 193 | config MOXA_SMARTIO |
194 | tristate "Moxa SmartIO support" | 194 | tristate "Moxa SmartIO support (OBSOLETE)" |
195 | depends on SERIAL_NONSTANDARD | 195 | depends on SERIAL_NONSTANDARD |
196 | help | 196 | help |
197 | Say Y here if you have a Moxa SmartIO multiport serial card. | 197 | Say Y here if you have a Moxa SmartIO multiport serial card. |
@@ -202,7 +202,7 @@ config MOXA_SMARTIO | |||
202 | here. | 202 | here. |
203 | 203 | ||
204 | config MOXA_SMARTIO_NEW | 204 | config MOXA_SMARTIO_NEW |
205 | tristate "Moxa SmartIO support v. 2.0 (EXPERIMENTAL)" | 205 | tristate "Moxa SmartIO support v. 2.0" |
206 | depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) | 206 | depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) |
207 | help | 207 | help |
208 | Say Y here if you have a Moxa SmartIO multiport serial card and/or | 208 | Say Y here if you have a Moxa SmartIO multiport serial card and/or |
@@ -610,6 +610,13 @@ config HVC_RTAS | |||
610 | help | 610 | help |
611 | IBM Console device driver which makes use of RTAS | 611 | IBM Console device driver which makes use of RTAS |
612 | 612 | ||
613 | config HVC_BEAT | ||
614 | bool "Toshiba's Beat Hypervisor Console support" | ||
615 | depends on PPC_CELLEB | ||
616 | select HVC_DRIVER | ||
617 | help | ||
618 | Toshiba's Cell Reference Set Beat Console device driver | ||
619 | |||
613 | config HVCS | 620 | config HVCS |
614 | tristate "IBM Hypervisor Virtual Console Server support" | 621 | tristate "IBM Hypervisor Virtual Console Server support" |
615 | depends on PPC_PSERIES | 622 | depends on PPC_PSERIES |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index fc110637ced6..ae8567cc529c 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -45,6 +45,7 @@ obj-$(CONFIG_RIO) += rio/ generic_serial.o | |||
45 | obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o | 45 | obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o |
46 | obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o | 46 | obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o |
47 | obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o | 47 | obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o |
48 | obj-$(CONFIG_HVC_BEAT) += hvc_beat.o | ||
48 | obj-$(CONFIG_HVC_DRIVER) += hvc_console.o | 49 | obj-$(CONFIG_HVC_DRIVER) += hvc_console.o |
49 | obj-$(CONFIG_RAW_DRIVER) += raw.o | 50 | obj-$(CONFIG_RAW_DRIVER) += raw.o |
50 | obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o | 51 | obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o |
@@ -59,6 +60,8 @@ obj-$(CONFIG_BRIQ_PANEL) += briq_panel.o | |||
59 | obj-$(CONFIG_PRINTER) += lp.o | 60 | obj-$(CONFIG_PRINTER) += lp.o |
60 | obj-$(CONFIG_TIPAR) += tipar.o | 61 | obj-$(CONFIG_TIPAR) += tipar.o |
61 | 62 | ||
63 | obj-$(CONFIG_APM_EMULATION) += apm-emulation.o | ||
64 | |||
62 | obj-$(CONFIG_DTLK) += dtlk.o | 65 | obj-$(CONFIG_DTLK) += dtlk.o |
63 | obj-$(CONFIG_R3964) += n_r3964.o | 66 | obj-$(CONFIG_R3964) += n_r3964.o |
64 | obj-$(CONFIG_APPLICOM) += applicom.o | 67 | obj-$(CONFIG_APPLICOM) += applicom.o |
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index feb4ac802a0d..0e2b72f2b887 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c | |||
@@ -527,10 +527,8 @@ static void do_softint(unsigned long private_) | |||
527 | if (!tty) | 527 | if (!tty) |
528 | return; | 528 | return; |
529 | 529 | ||
530 | if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { | 530 | if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) |
531 | tty_wakeup(tty); | 531 | tty_wakeup(tty); |
532 | wake_up_interruptible(&tty->write_wait); | ||
533 | } | ||
534 | } | 532 | } |
535 | 533 | ||
536 | /* | 534 | /* |
@@ -904,8 +902,7 @@ static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count | |||
904 | if (!info->xmit.buf) | 902 | if (!info->xmit.buf) |
905 | return 0; | 903 | return 0; |
906 | 904 | ||
907 | local_save_flags(flags); | 905 | local_irq_save(flags); |
908 | local_irq_disable(); | ||
909 | while (1) { | 906 | while (1) { |
910 | c = CIRC_SPACE_TO_END(info->xmit.head, | 907 | c = CIRC_SPACE_TO_END(info->xmit.head, |
911 | info->xmit.tail, | 908 | info->xmit.tail, |
@@ -968,7 +965,6 @@ static void rs_flush_buffer(struct tty_struct *tty) | |||
968 | local_irq_save(flags); | 965 | local_irq_save(flags); |
969 | info->xmit.head = info->xmit.tail = 0; | 966 | info->xmit.head = info->xmit.tail = 0; |
970 | local_irq_restore(flags); | 967 | local_irq_restore(flags); |
971 | wake_up_interruptible(&tty->write_wait); | ||
972 | tty_wakeup(tty); | 968 | tty_wakeup(tty); |
973 | } | 969 | } |
974 | 970 | ||
diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c new file mode 100644 index 000000000000..179c7a3b6e75 --- /dev/null +++ b/drivers/char/apm-emulation.c | |||
@@ -0,0 +1,672 @@ | |||
1 | /* | ||
2 | * bios-less APM driver for ARM Linux | ||
3 | * Jamey Hicks <jamey@crl.dec.com> | ||
4 | * adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com) | ||
5 | * | ||
6 | * APM 1.2 Reference: | ||
7 | * Intel Corporation, Microsoft Corporation. Advanced Power Management | ||
8 | * (APM) BIOS Interface Specification, Revision 1.2, February 1996. | ||
9 | * | ||
10 | * [This document is available from Microsoft at: | ||
11 | * http://www.microsoft.com/hwdev/busbios/amp_12.htm] | ||
12 | */ | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/poll.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/proc_fs.h> | ||
17 | #include <linux/miscdevice.h> | ||
18 | #include <linux/apm_bios.h> | ||
19 | #include <linux/capability.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/pm.h> | ||
22 | #include <linux/apm-emulation.h> | ||
23 | #include <linux/device.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/list.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/completion.h> | ||
28 | #include <linux/kthread.h> | ||
29 | #include <linux/delay.h> | ||
30 | |||
31 | #include <asm/system.h> | ||
32 | |||
33 | /* | ||
34 | * The apm_bios device is one of the misc char devices. | ||
35 | * This is its minor number. | ||
36 | */ | ||
37 | #define APM_MINOR_DEV 134 | ||
38 | |||
39 | /* | ||
40 | * See Documentation/Config.help for the configuration options. | ||
41 | * | ||
42 | * Various options can be changed at boot time as follows: | ||
43 | * (We allow underscores for compatibility with the modules code) | ||
44 | * apm=on/off enable/disable APM | ||
45 | */ | ||
46 | |||
47 | /* | ||
48 | * Maximum number of events stored | ||
49 | */ | ||
50 | #define APM_MAX_EVENTS 16 | ||
51 | |||
52 | struct apm_queue { | ||
53 | unsigned int event_head; | ||
54 | unsigned int event_tail; | ||
55 | apm_event_t events[APM_MAX_EVENTS]; | ||
56 | }; | ||
57 | |||
58 | /* | ||
59 | * The per-file APM data | ||
60 | */ | ||
61 | struct apm_user { | ||
62 | struct list_head list; | ||
63 | |||
64 | unsigned int suser: 1; | ||
65 | unsigned int writer: 1; | ||
66 | unsigned int reader: 1; | ||
67 | |||
68 | int suspend_result; | ||
69 | unsigned int suspend_state; | ||
70 | #define SUSPEND_NONE 0 /* no suspend pending */ | ||
71 | #define SUSPEND_PENDING 1 /* suspend pending read */ | ||
72 | #define SUSPEND_READ 2 /* suspend read, pending ack */ | ||
73 | #define SUSPEND_ACKED 3 /* suspend acked */ | ||
74 | #define SUSPEND_WAIT 4 /* waiting for suspend */ | ||
75 | #define SUSPEND_DONE 5 /* suspend completed */ | ||
76 | |||
77 | struct apm_queue queue; | ||
78 | }; | ||
79 | |||
80 | /* | ||
81 | * Local variables | ||
82 | */ | ||
83 | static int suspends_pending; | ||
84 | static int apm_disabled; | ||
85 | static struct task_struct *kapmd_tsk; | ||
86 | |||
87 | static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue); | ||
88 | static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue); | ||
89 | |||
90 | /* | ||
91 | * This is a list of everyone who has opened /dev/apm_bios | ||
92 | */ | ||
93 | static DECLARE_RWSEM(user_list_lock); | ||
94 | static LIST_HEAD(apm_user_list); | ||
95 | |||
96 | /* | ||
97 | * kapmd info. kapmd provides us a process context to handle | ||
98 | * "APM" events within - specifically necessary if we're going | ||
99 | * to be suspending the system. | ||
100 | */ | ||
101 | static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait); | ||
102 | static DEFINE_SPINLOCK(kapmd_queue_lock); | ||
103 | static struct apm_queue kapmd_queue; | ||
104 | |||
105 | static DEFINE_MUTEX(state_lock); | ||
106 | |||
107 | static const char driver_version[] = "1.13"; /* no spaces */ | ||
108 | |||
109 | |||
110 | |||
111 | /* | ||
112 | * Compatibility cruft until the IPAQ people move over to the new | ||
113 | * interface. | ||
114 | */ | ||
115 | static void __apm_get_power_status(struct apm_power_info *info) | ||
116 | { | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * This allows machines to provide their own "apm get power status" function. | ||
121 | */ | ||
122 | void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status; | ||
123 | EXPORT_SYMBOL(apm_get_power_status); | ||
124 | |||
125 | |||
126 | /* | ||
127 | * APM event queue management. | ||
128 | */ | ||
129 | static inline int queue_empty(struct apm_queue *q) | ||
130 | { | ||
131 | return q->event_head == q->event_tail; | ||
132 | } | ||
133 | |||
134 | static inline apm_event_t queue_get_event(struct apm_queue *q) | ||
135 | { | ||
136 | q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS; | ||
137 | return q->events[q->event_tail]; | ||
138 | } | ||
139 | |||
140 | static void queue_add_event(struct apm_queue *q, apm_event_t event) | ||
141 | { | ||
142 | q->event_head = (q->event_head + 1) % APM_MAX_EVENTS; | ||
143 | if (q->event_head == q->event_tail) { | ||
144 | static int notified; | ||
145 | |||
146 | if (notified++ == 0) | ||
147 | printk(KERN_ERR "apm: an event queue overflowed\n"); | ||
148 | q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS; | ||
149 | } | ||
150 | q->events[q->event_head] = event; | ||
151 | } | ||
152 | |||
153 | static void queue_event(apm_event_t event) | ||
154 | { | ||
155 | struct apm_user *as; | ||
156 | |||
157 | down_read(&user_list_lock); | ||
158 | list_for_each_entry(as, &apm_user_list, list) { | ||
159 | if (as->reader) | ||
160 | queue_add_event(&as->queue, event); | ||
161 | } | ||
162 | up_read(&user_list_lock); | ||
163 | wake_up_interruptible(&apm_waitqueue); | ||
164 | } | ||
165 | |||
166 | /* | ||
167 | * queue_suspend_event - queue an APM suspend event. | ||
168 | * | ||
169 | * Check that we're in a state where we can suspend. If not, | ||
170 | * return -EBUSY. Otherwise, queue an event to all "writer" | ||
171 | * users. If there are no "writer" users, return '1' to | ||
172 | * indicate that we can immediately suspend. | ||
173 | */ | ||
174 | static int queue_suspend_event(apm_event_t event, struct apm_user *sender) | ||
175 | { | ||
176 | struct apm_user *as; | ||
177 | int ret = 1; | ||
178 | |||
179 | mutex_lock(&state_lock); | ||
180 | down_read(&user_list_lock); | ||
181 | |||
182 | /* | ||
183 | * If a thread is still processing, we can't suspend, so reject | ||
184 | * the request. | ||
185 | */ | ||
186 | list_for_each_entry(as, &apm_user_list, list) { | ||
187 | if (as != sender && as->reader && as->writer && as->suser && | ||
188 | as->suspend_state != SUSPEND_NONE) { | ||
189 | ret = -EBUSY; | ||
190 | goto out; | ||
191 | } | ||
192 | } | ||
193 | |||
194 | list_for_each_entry(as, &apm_user_list, list) { | ||
195 | if (as != sender && as->reader && as->writer && as->suser) { | ||
196 | as->suspend_state = SUSPEND_PENDING; | ||
197 | suspends_pending++; | ||
198 | queue_add_event(&as->queue, event); | ||
199 | ret = 0; | ||
200 | } | ||
201 | } | ||
202 | out: | ||
203 | up_read(&user_list_lock); | ||
204 | mutex_unlock(&state_lock); | ||
205 | wake_up_interruptible(&apm_waitqueue); | ||
206 | return ret; | ||
207 | } | ||
208 | |||
209 | static void apm_suspend(void) | ||
210 | { | ||
211 | struct apm_user *as; | ||
212 | int err = pm_suspend(PM_SUSPEND_MEM); | ||
213 | |||
214 | /* | ||
215 | * Anyone on the APM queues will think we're still suspended. | ||
216 | * Send a message so everyone knows we're now awake again. | ||
217 | */ | ||
218 | queue_event(APM_NORMAL_RESUME); | ||
219 | |||
220 | /* | ||
221 | * Finally, wake up anyone who is sleeping on the suspend. | ||
222 | */ | ||
223 | mutex_lock(&state_lock); | ||
224 | down_read(&user_list_lock); | ||
225 | list_for_each_entry(as, &apm_user_list, list) { | ||
226 | if (as->suspend_state == SUSPEND_WAIT || | ||
227 | as->suspend_state == SUSPEND_ACKED) { | ||
228 | as->suspend_result = err; | ||
229 | as->suspend_state = SUSPEND_DONE; | ||
230 | } | ||
231 | } | ||
232 | up_read(&user_list_lock); | ||
233 | mutex_unlock(&state_lock); | ||
234 | |||
235 | wake_up(&apm_suspend_waitqueue); | ||
236 | } | ||
237 | |||
238 | static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos) | ||
239 | { | ||
240 | struct apm_user *as = fp->private_data; | ||
241 | apm_event_t event; | ||
242 | int i = count, ret = 0; | ||
243 | |||
244 | if (count < sizeof(apm_event_t)) | ||
245 | return -EINVAL; | ||
246 | |||
247 | if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK) | ||
248 | return -EAGAIN; | ||
249 | |||
250 | wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue)); | ||
251 | |||
252 | while ((i >= sizeof(event)) && !queue_empty(&as->queue)) { | ||
253 | event = queue_get_event(&as->queue); | ||
254 | |||
255 | ret = -EFAULT; | ||
256 | if (copy_to_user(buf, &event, sizeof(event))) | ||
257 | break; | ||
258 | |||
259 | mutex_lock(&state_lock); | ||
260 | if (as->suspend_state == SUSPEND_PENDING && | ||
261 | (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND)) | ||
262 | as->suspend_state = SUSPEND_READ; | ||
263 | mutex_unlock(&state_lock); | ||
264 | |||
265 | buf += sizeof(event); | ||
266 | i -= sizeof(event); | ||
267 | } | ||
268 | |||
269 | if (i < count) | ||
270 | ret = count - i; | ||
271 | |||
272 | return ret; | ||
273 | } | ||
274 | |||
275 | static unsigned int apm_poll(struct file *fp, poll_table * wait) | ||
276 | { | ||
277 | struct apm_user *as = fp->private_data; | ||
278 | |||
279 | poll_wait(fp, &apm_waitqueue, wait); | ||
280 | return queue_empty(&as->queue) ? 0 : POLLIN | POLLRDNORM; | ||
281 | } | ||
282 | |||
283 | /* | ||
284 | * apm_ioctl - handle APM ioctl | ||
285 | * | ||
286 | * APM_IOC_SUSPEND | ||
287 | * This IOCTL is overloaded, and performs two functions. It is used to: | ||
288 | * - initiate a suspend | ||
289 | * - acknowledge a suspend read from /dev/apm_bios. | ||
290 | * Only when everyone who has opened /dev/apm_bios with write permission | ||
291 | * has acknowledge does the actual suspend happen. | ||
292 | */ | ||
293 | static int | ||
294 | apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) | ||
295 | { | ||
296 | struct apm_user *as = filp->private_data; | ||
297 | unsigned long flags; | ||
298 | int err = -EINVAL; | ||
299 | |||
300 | if (!as->suser || !as->writer) | ||
301 | return -EPERM; | ||
302 | |||
303 | switch (cmd) { | ||
304 | case APM_IOC_SUSPEND: | ||
305 | mutex_lock(&state_lock); | ||
306 | |||
307 | as->suspend_result = -EINTR; | ||
308 | |||
309 | if (as->suspend_state == SUSPEND_READ) { | ||
310 | int pending; | ||
311 | |||
312 | /* | ||
313 | * If we read a suspend command from /dev/apm_bios, | ||
314 | * then the corresponding APM_IOC_SUSPEND ioctl is | ||
315 | * interpreted as an acknowledge. | ||
316 | */ | ||
317 | as->suspend_state = SUSPEND_ACKED; | ||
318 | suspends_pending--; | ||
319 | pending = suspends_pending == 0; | ||
320 | mutex_unlock(&state_lock); | ||
321 | |||
322 | /* | ||
323 | * If there are no further acknowledges required, | ||
324 | * suspend the system. | ||
325 | */ | ||
326 | if (pending) | ||
327 | apm_suspend(); | ||
328 | |||
329 | /* | ||
330 | * Wait for the suspend/resume to complete. If there | ||
331 | * are pending acknowledges, we wait here for them. | ||
332 | * | ||
333 | * Note: we need to ensure that the PM subsystem does | ||
334 | * not kick us out of the wait when it suspends the | ||
335 | * threads. | ||
336 | */ | ||
337 | flags = current->flags; | ||
338 | current->flags |= PF_NOFREEZE; | ||
339 | |||
340 | wait_event(apm_suspend_waitqueue, | ||
341 | as->suspend_state == SUSPEND_DONE); | ||
342 | } else { | ||
343 | as->suspend_state = SUSPEND_WAIT; | ||
344 | mutex_unlock(&state_lock); | ||
345 | |||
346 | /* | ||
347 | * Otherwise it is a request to suspend the system. | ||
348 | * Queue an event for all readers, and expect an | ||
349 | * acknowledge from all writers who haven't already | ||
350 | * acknowledged. | ||
351 | */ | ||
352 | err = queue_suspend_event(APM_USER_SUSPEND, as); | ||
353 | if (err < 0) { | ||
354 | /* | ||
355 | * Avoid taking the lock here - this | ||
356 | * should be fine. | ||
357 | */ | ||
358 | as->suspend_state = SUSPEND_NONE; | ||
359 | break; | ||
360 | } | ||
361 | |||
362 | if (err > 0) | ||
363 | apm_suspend(); | ||
364 | |||
365 | /* | ||
366 | * Wait for the suspend/resume to complete. If there | ||
367 | * are pending acknowledges, we wait here for them. | ||
368 | * | ||
369 | * Note: we need to ensure that the PM subsystem does | ||
370 | * not kick us out of the wait when it suspends the | ||
371 | * threads. | ||
372 | */ | ||
373 | flags = current->flags; | ||
374 | current->flags |= PF_NOFREEZE; | ||
375 | |||
376 | wait_event_interruptible(apm_suspend_waitqueue, | ||
377 | as->suspend_state == SUSPEND_DONE); | ||
378 | } | ||
379 | |||
380 | current->flags = flags; | ||
381 | |||
382 | mutex_lock(&state_lock); | ||
383 | err = as->suspend_result; | ||
384 | as->suspend_state = SUSPEND_NONE; | ||
385 | mutex_unlock(&state_lock); | ||
386 | break; | ||
387 | } | ||
388 | |||
389 | return err; | ||
390 | } | ||
391 | |||
392 | static int apm_release(struct inode * inode, struct file * filp) | ||
393 | { | ||
394 | struct apm_user *as = filp->private_data; | ||
395 | int pending = 0; | ||
396 | |||
397 | filp->private_data = NULL; | ||
398 | |||
399 | down_write(&user_list_lock); | ||
400 | list_del(&as->list); | ||
401 | up_write(&user_list_lock); | ||
402 | |||
403 | /* | ||
404 | * We are now unhooked from the chain. As far as new | ||
405 | * events are concerned, we no longer exist. However, we | ||
406 | * need to balance suspends_pending, which means the | ||
407 | * possibility of sleeping. | ||
408 | */ | ||
409 | mutex_lock(&state_lock); | ||
410 | if (as->suspend_state != SUSPEND_NONE) { | ||
411 | suspends_pending -= 1; | ||
412 | pending = suspends_pending == 0; | ||
413 | } | ||
414 | mutex_unlock(&state_lock); | ||
415 | if (pending) | ||
416 | apm_suspend(); | ||
417 | |||
418 | kfree(as); | ||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | static int apm_open(struct inode * inode, struct file * filp) | ||
423 | { | ||
424 | struct apm_user *as; | ||
425 | |||
426 | as = kzalloc(sizeof(*as), GFP_KERNEL); | ||
427 | if (as) { | ||
428 | /* | ||
429 | * XXX - this is a tiny bit broken, when we consider BSD | ||
430 | * process accounting. If the device is opened by root, we | ||
431 | * instantly flag that we used superuser privs. Who knows, | ||
432 | * we might close the device immediately without doing a | ||
433 | * privileged operation -- cevans | ||
434 | */ | ||
435 | as->suser = capable(CAP_SYS_ADMIN); | ||
436 | as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE; | ||
437 | as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ; | ||
438 | |||
439 | down_write(&user_list_lock); | ||
440 | list_add(&as->list, &apm_user_list); | ||
441 | up_write(&user_list_lock); | ||
442 | |||
443 | filp->private_data = as; | ||
444 | } | ||
445 | |||
446 | return as ? 0 : -ENOMEM; | ||
447 | } | ||
448 | |||
449 | static struct file_operations apm_bios_fops = { | ||
450 | .owner = THIS_MODULE, | ||
451 | .read = apm_read, | ||
452 | .poll = apm_poll, | ||
453 | .ioctl = apm_ioctl, | ||
454 | .open = apm_open, | ||
455 | .release = apm_release, | ||
456 | }; | ||
457 | |||
458 | static struct miscdevice apm_device = { | ||
459 | .minor = APM_MINOR_DEV, | ||
460 | .name = "apm_bios", | ||
461 | .fops = &apm_bios_fops | ||
462 | }; | ||
463 | |||
464 | |||
465 | #ifdef CONFIG_PROC_FS | ||
466 | /* | ||
467 | * Arguments, with symbols from linux/apm_bios.h. | ||
468 | * | ||
469 | * 0) Linux driver version (this will change if format changes) | ||
470 | * 1) APM BIOS Version. Usually 1.0, 1.1 or 1.2. | ||
471 | * 2) APM flags from APM Installation Check (0x00): | ||
472 | * bit 0: APM_16_BIT_SUPPORT | ||
473 | * bit 1: APM_32_BIT_SUPPORT | ||
474 | * bit 2: APM_IDLE_SLOWS_CLOCK | ||
475 | * bit 3: APM_BIOS_DISABLED | ||
476 | * bit 4: APM_BIOS_DISENGAGED | ||
477 | * 3) AC line status | ||
478 | * 0x00: Off-line | ||
479 | * 0x01: On-line | ||
480 | * 0x02: On backup power (BIOS >= 1.1 only) | ||
481 | * 0xff: Unknown | ||
482 | * 4) Battery status | ||
483 | * 0x00: High | ||
484 | * 0x01: Low | ||
485 | * 0x02: Critical | ||
486 | * 0x03: Charging | ||
487 | * 0x04: Selected battery not present (BIOS >= 1.2 only) | ||
488 | * 0xff: Unknown | ||
489 | * 5) Battery flag | ||
490 | * bit 0: High | ||
491 | * bit 1: Low | ||
492 | * bit 2: Critical | ||
493 | * bit 3: Charging | ||
494 | * bit 7: No system battery | ||
495 | * 0xff: Unknown | ||
496 | * 6) Remaining battery life (percentage of charge): | ||
497 | * 0-100: valid | ||
498 | * -1: Unknown | ||
499 | * 7) Remaining battery life (time units): | ||
500 | * Number of remaining minutes or seconds | ||
501 | * -1: Unknown | ||
502 | * 8) min = minutes; sec = seconds | ||
503 | */ | ||
504 | static int apm_get_info(char *buf, char **start, off_t fpos, int length) | ||
505 | { | ||
506 | struct apm_power_info info; | ||
507 | char *units; | ||
508 | int ret; | ||
509 | |||
510 | info.ac_line_status = 0xff; | ||
511 | info.battery_status = 0xff; | ||
512 | info.battery_flag = 0xff; | ||
513 | info.battery_life = -1; | ||
514 | info.time = -1; | ||
515 | info.units = -1; | ||
516 | |||
517 | if (apm_get_power_status) | ||
518 | apm_get_power_status(&info); | ||
519 | |||
520 | switch (info.units) { | ||
521 | default: units = "?"; break; | ||
522 | case 0: units = "min"; break; | ||
523 | case 1: units = "sec"; break; | ||
524 | } | ||
525 | |||
526 | ret = sprintf(buf, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n", | ||
527 | driver_version, APM_32_BIT_SUPPORT, | ||
528 | info.ac_line_status, info.battery_status, | ||
529 | info.battery_flag, info.battery_life, | ||
530 | info.time, units); | ||
531 | |||
532 | return ret; | ||
533 | } | ||
534 | #endif | ||
535 | |||
536 | static int kapmd(void *arg) | ||
537 | { | ||
538 | do { | ||
539 | apm_event_t event; | ||
540 | int ret; | ||
541 | |||
542 | wait_event_interruptible(kapmd_wait, | ||
543 | !queue_empty(&kapmd_queue) || kthread_should_stop()); | ||
544 | |||
545 | if (kthread_should_stop()) | ||
546 | break; | ||
547 | |||
548 | spin_lock_irq(&kapmd_queue_lock); | ||
549 | event = 0; | ||
550 | if (!queue_empty(&kapmd_queue)) | ||
551 | event = queue_get_event(&kapmd_queue); | ||
552 | spin_unlock_irq(&kapmd_queue_lock); | ||
553 | |||
554 | switch (event) { | ||
555 | case 0: | ||
556 | break; | ||
557 | |||
558 | case APM_LOW_BATTERY: | ||
559 | case APM_POWER_STATUS_CHANGE: | ||
560 | queue_event(event); | ||
561 | break; | ||
562 | |||
563 | case APM_USER_SUSPEND: | ||
564 | case APM_SYS_SUSPEND: | ||
565 | ret = queue_suspend_event(event, NULL); | ||
566 | if (ret < 0) { | ||
567 | /* | ||
568 | * We were busy. Try again in 50ms. | ||
569 | */ | ||
570 | queue_add_event(&kapmd_queue, event); | ||
571 | msleep(50); | ||
572 | } | ||
573 | if (ret > 0) | ||
574 | apm_suspend(); | ||
575 | break; | ||
576 | |||
577 | case APM_CRITICAL_SUSPEND: | ||
578 | apm_suspend(); | ||
579 | break; | ||
580 | } | ||
581 | } while (1); | ||
582 | |||
583 | return 0; | ||
584 | } | ||
585 | |||
586 | static int __init apm_init(void) | ||
587 | { | ||
588 | int ret; | ||
589 | |||
590 | if (apm_disabled) { | ||
591 | printk(KERN_NOTICE "apm: disabled on user request.\n"); | ||
592 | return -ENODEV; | ||
593 | } | ||
594 | |||
595 | kapmd_tsk = kthread_create(kapmd, NULL, "kapmd"); | ||
596 | if (IS_ERR(kapmd_tsk)) { | ||
597 | ret = PTR_ERR(kapmd_tsk); | ||
598 | kapmd_tsk = NULL; | ||
599 | return ret; | ||
600 | } | ||
601 | kapmd_tsk->flags |= PF_NOFREEZE; | ||
602 | wake_up_process(kapmd_tsk); | ||
603 | |||
604 | #ifdef CONFIG_PROC_FS | ||
605 | create_proc_info_entry("apm", 0, NULL, apm_get_info); | ||
606 | #endif | ||
607 | |||
608 | ret = misc_register(&apm_device); | ||
609 | if (ret != 0) { | ||
610 | remove_proc_entry("apm", NULL); | ||
611 | kthread_stop(kapmd_tsk); | ||
612 | } | ||
613 | |||
614 | return ret; | ||
615 | } | ||
616 | |||
617 | static void __exit apm_exit(void) | ||
618 | { | ||
619 | misc_deregister(&apm_device); | ||
620 | remove_proc_entry("apm", NULL); | ||
621 | |||
622 | kthread_stop(kapmd_tsk); | ||
623 | } | ||
624 | |||
625 | module_init(apm_init); | ||
626 | module_exit(apm_exit); | ||
627 | |||
628 | MODULE_AUTHOR("Stephen Rothwell"); | ||
629 | MODULE_DESCRIPTION("Advanced Power Management"); | ||
630 | MODULE_LICENSE("GPL"); | ||
631 | |||
632 | #ifndef MODULE | ||
633 | static int __init apm_setup(char *str) | ||
634 | { | ||
635 | while ((str != NULL) && (*str != '\0')) { | ||
636 | if (strncmp(str, "off", 3) == 0) | ||
637 | apm_disabled = 1; | ||
638 | if (strncmp(str, "on", 2) == 0) | ||
639 | apm_disabled = 0; | ||
640 | str = strchr(str, ','); | ||
641 | if (str != NULL) | ||
642 | str += strspn(str, ", \t"); | ||
643 | } | ||
644 | return 1; | ||
645 | } | ||
646 | |||
647 | __setup("apm=", apm_setup); | ||
648 | #endif | ||
649 | |||
650 | /** | ||
651 | * apm_queue_event - queue an APM event for kapmd | ||
652 | * @event: APM event | ||
653 | * | ||
654 | * Queue an APM event for kapmd to process and ultimately take the | ||
655 | * appropriate action. Only a subset of events are handled: | ||
656 | * %APM_LOW_BATTERY | ||
657 | * %APM_POWER_STATUS_CHANGE | ||
658 | * %APM_USER_SUSPEND | ||
659 | * %APM_SYS_SUSPEND | ||
660 | * %APM_CRITICAL_SUSPEND | ||
661 | */ | ||
662 | void apm_queue_event(apm_event_t event) | ||
663 | { | ||
664 | unsigned long flags; | ||
665 | |||
666 | spin_lock_irqsave(&kapmd_queue_lock, flags); | ||
667 | queue_add_event(&kapmd_queue, event); | ||
668 | spin_unlock_irqrestore(&kapmd_queue_lock, flags); | ||
669 | |||
670 | wake_up_interruptible(&kapmd_wait); | ||
671 | } | ||
672 | EXPORT_SYMBOL(apm_queue_event); | ||
diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c index 9f8082f8dd29..7f60a18ef76b 100644 --- a/drivers/char/briq_panel.c +++ b/drivers/char/briq_panel.c | |||
@@ -187,7 +187,7 @@ static ssize_t briq_panel_write(struct file *file, const char __user *buf, size_ | |||
187 | return len; | 187 | return len; |
188 | } | 188 | } |
189 | 189 | ||
190 | static struct file_operations briq_panel_fops = { | 190 | static const struct file_operations briq_panel_fops = { |
191 | .owner = THIS_MODULE, | 191 | .owner = THIS_MODULE, |
192 | .read = briq_panel_read, | 192 | .read = briq_panel_read, |
193 | .write = briq_panel_write, | 193 | .write = briq_panel_write, |
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 3ffa0807754c..54df35527bc5 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
@@ -829,17 +829,18 @@ static unsigned short cy_pci_nboard; | |||
829 | static unsigned short cy_isa_nboard; | 829 | static unsigned short cy_isa_nboard; |
830 | static unsigned short cy_nboard; | 830 | static unsigned short cy_nboard; |
831 | #ifdef CONFIG_PCI | 831 | #ifdef CONFIG_PCI |
832 | static unsigned short cy_pci_dev_id[] = { | 832 | static struct pci_device_id cy_pci_dev_id[] __devinitdata = { |
833 | PCI_DEVICE_ID_CYCLOM_Y_Lo, /* PCI < 1Mb */ | 833 | { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Lo) }, /* PCI < 1Mb */ |
834 | PCI_DEVICE_ID_CYCLOM_Y_Hi, /* PCI > 1Mb */ | 834 | { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Hi) }, /* PCI > 1Mb */ |
835 | PCI_DEVICE_ID_CYCLOM_4Y_Lo, /* 4Y PCI < 1Mb */ | 835 | { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Lo) }, /* 4Y PCI < 1Mb */ |
836 | PCI_DEVICE_ID_CYCLOM_4Y_Hi, /* 4Y PCI > 1Mb */ | 836 | { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Hi) }, /* 4Y PCI > 1Mb */ |
837 | PCI_DEVICE_ID_CYCLOM_8Y_Lo, /* 8Y PCI < 1Mb */ | 837 | { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Lo) }, /* 8Y PCI < 1Mb */ |
838 | PCI_DEVICE_ID_CYCLOM_8Y_Hi, /* 8Y PCI > 1Mb */ | 838 | { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Hi) }, /* 8Y PCI > 1Mb */ |
839 | PCI_DEVICE_ID_CYCLOM_Z_Lo, /* Z PCI < 1Mb */ | 839 | { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Lo) }, /* Z PCI < 1Mb */ |
840 | PCI_DEVICE_ID_CYCLOM_Z_Hi, /* Z PCI > 1Mb */ | 840 | { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Hi) }, /* Z PCI > 1Mb */ |
841 | 0 /* end of table */ | 841 | { } /* end of table */ |
842 | }; | 842 | }; |
843 | MODULE_DEVICE_TABLE(pci, cy_pci_dev_id); | ||
843 | #endif | 844 | #endif |
844 | 845 | ||
845 | static void cy_start(struct tty_struct *); | 846 | static void cy_start(struct tty_struct *); |
@@ -4488,7 +4489,6 @@ static void cy_flush_buffer(struct tty_struct *tty) | |||
4488 | CY_UNLOCK(info, flags); | 4489 | CY_UNLOCK(info, flags); |
4489 | } | 4490 | } |
4490 | tty_wakeup(tty); | 4491 | tty_wakeup(tty); |
4491 | wake_up_interruptible(&tty->write_wait); | ||
4492 | } /* cy_flush_buffer */ | 4492 | } /* cy_flush_buffer */ |
4493 | 4493 | ||
4494 | /* | 4494 | /* |
@@ -4759,7 +4759,7 @@ static int __init cy_detect_pci(void) | |||
4759 | 4759 | ||
4760 | for (i = 0; i < NR_CARDS; i++) { | 4760 | for (i = 0; i < NR_CARDS; i++) { |
4761 | /* look for a Cyclades card by vendor and device id */ | 4761 | /* look for a Cyclades card by vendor and device id */ |
4762 | while ((device_id = cy_pci_dev_id[dev_index]) != 0) { | 4762 | while ((device_id = cy_pci_dev_id[dev_index].device) != 0) { |
4763 | if ((pdev = pci_get_device(PCI_VENDOR_ID_CYCLADES, | 4763 | if ((pdev = pci_get_device(PCI_VENDOR_ID_CYCLADES, |
4764 | device_id, pdev)) == NULL) { | 4764 | device_id, pdev)) == NULL) { |
4765 | dev_index++; /* try next device id */ | 4765 | dev_index++; /* try next device id */ |
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 6dcdceb81203..85d99e21e188 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h | |||
@@ -532,11 +532,13 @@ typedef struct drm_mm_node { | |||
532 | int free; | 532 | int free; |
533 | unsigned long start; | 533 | unsigned long start; |
534 | unsigned long size; | 534 | unsigned long size; |
535 | struct drm_mm *mm; | ||
535 | void *private; | 536 | void *private; |
536 | } drm_mm_node_t; | 537 | } drm_mm_node_t; |
537 | 538 | ||
538 | typedef struct drm_mm { | 539 | typedef struct drm_mm { |
539 | drm_mm_node_t root_node; | 540 | struct list_head fl_entry; |
541 | struct list_head ml_entry; | ||
540 | } drm_mm_t; | 542 | } drm_mm_t; |
541 | 543 | ||
542 | /** | 544 | /** |
@@ -843,9 +845,6 @@ extern void drm_mem_init(void); | |||
843 | extern int drm_mem_info(char *buf, char **start, off_t offset, | 845 | extern int drm_mem_info(char *buf, char **start, off_t offset, |
844 | int request, int *eof, void *data); | 846 | int request, int *eof, void *data); |
845 | extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area); | 847 | extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area); |
846 | extern void *drm_ioremap(unsigned long offset, unsigned long size, | ||
847 | drm_device_t * dev); | ||
848 | extern void drm_ioremapfree(void *pt, unsigned long size, drm_device_t * dev); | ||
849 | 848 | ||
850 | extern DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type); | 849 | extern DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type); |
851 | extern int drm_free_agp(DRM_AGP_MEM * handle, int pages); | 850 | extern int drm_free_agp(DRM_AGP_MEM * handle, int pages); |
@@ -1053,33 +1052,18 @@ extern void drm_sysfs_device_remove(struct class_device *class_dev); | |||
1053 | extern drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent, | 1052 | extern drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent, |
1054 | unsigned long size, | 1053 | unsigned long size, |
1055 | unsigned alignment); | 1054 | unsigned alignment); |
1056 | extern void drm_mm_put_block(drm_mm_t *mm, drm_mm_node_t *cur); | 1055 | void drm_mm_put_block(drm_mm_node_t * cur); |
1057 | extern drm_mm_node_t *drm_mm_search_free(const drm_mm_t *mm, unsigned long size, | 1056 | extern drm_mm_node_t *drm_mm_search_free(const drm_mm_t *mm, unsigned long size, |
1058 | unsigned alignment, int best_match); | 1057 | unsigned alignment, int best_match); |
1059 | extern int drm_mm_init(drm_mm_t *mm, unsigned long start, unsigned long size); | 1058 | extern int drm_mm_init(drm_mm_t *mm, unsigned long start, unsigned long size); |
1060 | extern void drm_mm_takedown(drm_mm_t *mm); | 1059 | extern void drm_mm_takedown(drm_mm_t *mm); |
1060 | extern int drm_mm_clean(drm_mm_t *mm); | ||
1061 | extern unsigned long drm_mm_tail_space(drm_mm_t *mm); | ||
1062 | extern int drm_mm_remove_space_from_tail(drm_mm_t *mm, unsigned long size); | ||
1063 | extern int drm_mm_add_space_to_tail(drm_mm_t *mm, unsigned long size); | ||
1061 | 1064 | ||
1062 | /* Inline replacements for DRM_IOREMAP macros */ | 1065 | extern void drm_core_ioremap(struct drm_map *map, struct drm_device *dev); |
1063 | static __inline__ void drm_core_ioremap(struct drm_map *map, | 1066 | extern void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev); |
1064 | struct drm_device *dev) | ||
1065 | { | ||
1066 | map->handle = drm_ioremap(map->offset, map->size, dev); | ||
1067 | } | ||
1068 | |||
1069 | #if 0 | ||
1070 | static __inline__ void drm_core_ioremap_nocache(struct drm_map *map, | ||
1071 | struct drm_device *dev) | ||
1072 | { | ||
1073 | map->handle = drm_ioremap_nocache(map->offset, map->size, dev); | ||
1074 | } | ||
1075 | #endif /* 0 */ | ||
1076 | |||
1077 | static __inline__ void drm_core_ioremapfree(struct drm_map *map, | ||
1078 | struct drm_device *dev) | ||
1079 | { | ||
1080 | if (map->handle && map->size) | ||
1081 | drm_ioremapfree(map->handle, map->size, dev); | ||
1082 | } | ||
1083 | 1067 | ||
1084 | static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, | 1068 | static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, |
1085 | unsigned int token) | 1069 | unsigned int token) |
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index 9f65f5697ba8..a6828cc14e58 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c | |||
@@ -79,14 +79,14 @@ static int drm_map_handle(drm_device_t *dev, drm_hash_item_t *hash, | |||
79 | 79 | ||
80 | if (!use_hashed_handle) { | 80 | if (!use_hashed_handle) { |
81 | int ret; | 81 | int ret; |
82 | hash->key = user_token; | 82 | hash->key = user_token >> PAGE_SHIFT; |
83 | ret = drm_ht_insert_item(&dev->map_hash, hash); | 83 | ret = drm_ht_insert_item(&dev->map_hash, hash); |
84 | if (ret != -EINVAL) | 84 | if (ret != -EINVAL) |
85 | return ret; | 85 | return ret; |
86 | } | 86 | } |
87 | return drm_ht_just_insert_please(&dev->map_hash, hash, | 87 | return drm_ht_just_insert_please(&dev->map_hash, hash, |
88 | user_token, 32 - PAGE_SHIFT - 3, | 88 | user_token, 32 - PAGE_SHIFT - 3, |
89 | PAGE_SHIFT, DRM_MAP_HASH_OFFSET); | 89 | 0, DRM_MAP_HASH_OFFSET >> PAGE_SHIFT); |
90 | } | 90 | } |
91 | 91 | ||
92 | /** | 92 | /** |
@@ -178,11 +178,11 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, | |||
178 | } | 178 | } |
179 | } | 179 | } |
180 | if (map->type == _DRM_REGISTERS) | 180 | if (map->type == _DRM_REGISTERS) |
181 | map->handle = drm_ioremap(map->offset, map->size, dev); | 181 | map->handle = ioremap(map->offset, map->size); |
182 | break; | 182 | break; |
183 | 183 | ||
184 | case _DRM_SHM: | 184 | case _DRM_SHM: |
185 | map->handle = vmalloc_32(map->size); | 185 | map->handle = vmalloc_user(map->size); |
186 | DRM_DEBUG("%lu %d %p\n", | 186 | DRM_DEBUG("%lu %d %p\n", |
187 | map->size, drm_order(map->size), map->handle); | 187 | map->size, drm_order(map->size), map->handle); |
188 | if (!map->handle) { | 188 | if (!map->handle) { |
@@ -238,7 +238,7 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, | |||
238 | list = drm_alloc(sizeof(*list), DRM_MEM_MAPS); | 238 | list = drm_alloc(sizeof(*list), DRM_MEM_MAPS); |
239 | if (!list) { | 239 | if (!list) { |
240 | if (map->type == _DRM_REGISTERS) | 240 | if (map->type == _DRM_REGISTERS) |
241 | drm_ioremapfree(map->handle, map->size, dev); | 241 | iounmap(map->handle); |
242 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | 242 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); |
243 | return -EINVAL; | 243 | return -EINVAL; |
244 | } | 244 | } |
@@ -255,14 +255,14 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, | |||
255 | ret = drm_map_handle(dev, &list->hash, user_token, 0); | 255 | ret = drm_map_handle(dev, &list->hash, user_token, 0); |
256 | if (ret) { | 256 | if (ret) { |
257 | if (map->type == _DRM_REGISTERS) | 257 | if (map->type == _DRM_REGISTERS) |
258 | drm_ioremapfree(map->handle, map->size, dev); | 258 | iounmap(map->handle); |
259 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | 259 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); |
260 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); | 260 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); |
261 | mutex_unlock(&dev->struct_mutex); | 261 | mutex_unlock(&dev->struct_mutex); |
262 | return ret; | 262 | return ret; |
263 | } | 263 | } |
264 | 264 | ||
265 | list->user_token = list->hash.key; | 265 | list->user_token = list->hash.key << PAGE_SHIFT; |
266 | mutex_unlock(&dev->struct_mutex); | 266 | mutex_unlock(&dev->struct_mutex); |
267 | 267 | ||
268 | *maplist = list; | 268 | *maplist = list; |
@@ -347,7 +347,8 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map) | |||
347 | 347 | ||
348 | if (r_list->map == map) { | 348 | if (r_list->map == map) { |
349 | list_del(list); | 349 | list_del(list); |
350 | drm_ht_remove_key(&dev->map_hash, r_list->user_token); | 350 | drm_ht_remove_key(&dev->map_hash, |
351 | r_list->user_token >> PAGE_SHIFT); | ||
351 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); | 352 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); |
352 | break; | 353 | break; |
353 | } | 354 | } |
@@ -362,7 +363,7 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map) | |||
362 | 363 | ||
363 | switch (map->type) { | 364 | switch (map->type) { |
364 | case _DRM_REGISTERS: | 365 | case _DRM_REGISTERS: |
365 | drm_ioremapfree(map->handle, map->size, dev); | 366 | iounmap(map->handle); |
366 | /* FALLTHROUGH */ | 367 | /* FALLTHROUGH */ |
367 | case _DRM_FRAME_BUFFER: | 368 | case _DRM_FRAME_BUFFER: |
368 | if (drm_core_has_MTRR(dev) && map->mtrr >= 0) { | 369 | if (drm_core_has_MTRR(dev) && map->mtrr >= 0) { |
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c index a70af0de4453..f5b9b2480c14 100644 --- a/drivers/char/drm/drm_drv.c +++ b/drivers/char/drm/drm_drv.c | |||
@@ -371,7 +371,7 @@ void drm_exit(struct drm_driver *driver) | |||
371 | EXPORT_SYMBOL(drm_exit); | 371 | EXPORT_SYMBOL(drm_exit); |
372 | 372 | ||
373 | /** File operations structure */ | 373 | /** File operations structure */ |
374 | static struct file_operations drm_stub_fops = { | 374 | static const struct file_operations drm_stub_fops = { |
375 | .owner = THIS_MODULE, | 375 | .owner = THIS_MODULE, |
376 | .open = drm_stub_open | 376 | .open = drm_stub_open |
377 | }; | 377 | }; |
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c index 5681cae1d404..92a867082376 100644 --- a/drivers/char/drm/drm_memory.c +++ b/drivers/char/drm/drm_memory.c | |||
@@ -79,28 +79,6 @@ void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area) | |||
79 | } | 79 | } |
80 | 80 | ||
81 | #if __OS_HAS_AGP | 81 | #if __OS_HAS_AGP |
82 | /* | ||
83 | * Find the drm_map that covers the range [offset, offset+size). | ||
84 | */ | ||
85 | static drm_map_t *drm_lookup_map(unsigned long offset, | ||
86 | unsigned long size, drm_device_t * dev) | ||
87 | { | ||
88 | struct list_head *list; | ||
89 | drm_map_list_t *r_list; | ||
90 | drm_map_t *map; | ||
91 | |||
92 | list_for_each(list, &dev->maplist->head) { | ||
93 | r_list = (drm_map_list_t *) list; | ||
94 | map = r_list->map; | ||
95 | if (!map) | ||
96 | continue; | ||
97 | if (map->offset <= offset | ||
98 | && (offset + size) <= (map->offset + map->size)) | ||
99 | return map; | ||
100 | } | ||
101 | return NULL; | ||
102 | } | ||
103 | |||
104 | static void *agp_remap(unsigned long offset, unsigned long size, | 82 | static void *agp_remap(unsigned long offset, unsigned long size, |
105 | drm_device_t * dev) | 83 | drm_device_t * dev) |
106 | { | 84 | { |
@@ -169,13 +147,6 @@ int drm_unbind_agp(DRM_AGP_MEM * handle) | |||
169 | } | 147 | } |
170 | 148 | ||
171 | #else /* __OS_HAS_AGP */ | 149 | #else /* __OS_HAS_AGP */ |
172 | |||
173 | static inline drm_map_t *drm_lookup_map(unsigned long offset, | ||
174 | unsigned long size, drm_device_t * dev) | ||
175 | { | ||
176 | return NULL; | ||
177 | } | ||
178 | |||
179 | static inline void *agp_remap(unsigned long offset, unsigned long size, | 150 | static inline void *agp_remap(unsigned long offset, unsigned long size, |
180 | drm_device_t * dev) | 151 | drm_device_t * dev) |
181 | { | 152 | { |
@@ -184,57 +155,28 @@ static inline void *agp_remap(unsigned long offset, unsigned long size, | |||
184 | 155 | ||
185 | #endif /* agp */ | 156 | #endif /* agp */ |
186 | 157 | ||
187 | void *drm_ioremap(unsigned long offset, unsigned long size, | 158 | #endif /* debug_memory */ |
188 | drm_device_t * dev) | ||
189 | { | ||
190 | if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) { | ||
191 | drm_map_t *map = drm_lookup_map(offset, size, dev); | ||
192 | |||
193 | if (map && map->type == _DRM_AGP) | ||
194 | return agp_remap(offset, size, dev); | ||
195 | } | ||
196 | return ioremap(offset, size); | ||
197 | } | ||
198 | EXPORT_SYMBOL(drm_ioremap); | ||
199 | 159 | ||
200 | #if 0 | 160 | void drm_core_ioremap(struct drm_map *map, struct drm_device *dev) |
201 | void *drm_ioremap_nocache(unsigned long offset, | ||
202 | unsigned long size, drm_device_t * dev) | ||
203 | { | 161 | { |
204 | if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) { | 162 | if (drm_core_has_AGP(dev) && |
205 | drm_map_t *map = drm_lookup_map(offset, size, dev); | 163 | dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP) |
206 | 164 | map->handle = agp_remap(map->offset, map->size, dev); | |
207 | if (map && map->type == _DRM_AGP) | 165 | else |
208 | return agp_remap(offset, size, dev); | 166 | map->handle = ioremap(map->offset, map->size); |
209 | } | ||
210 | return ioremap_nocache(offset, size); | ||
211 | } | 167 | } |
212 | #endif /* 0 */ | 168 | EXPORT_SYMBOL(drm_core_ioremap); |
213 | 169 | ||
214 | void drm_ioremapfree(void *pt, unsigned long size, | 170 | void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev) |
215 | drm_device_t * dev) | ||
216 | { | 171 | { |
217 | /* | 172 | if (!map->handle || !map->size) |
218 | * This is a bit ugly. It would be much cleaner if the DRM API would use separate | 173 | return; |
219 | * routines for handling mappings in the AGP space. Hopefully this can be done in | 174 | |
220 | * a future revision of the interface... | 175 | if (drm_core_has_AGP(dev) && |
221 | */ | 176 | dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP) |
222 | if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture | 177 | vunmap(map->handle); |
223 | && ((unsigned long)pt >= VMALLOC_START | 178 | else |
224 | && (unsigned long)pt < VMALLOC_END)) { | 179 | iounmap(map->handle); |
225 | unsigned long offset; | ||
226 | drm_map_t *map; | ||
227 | |||
228 | offset = drm_follow_page(pt) | ((unsigned long)pt & ~PAGE_MASK); | ||
229 | map = drm_lookup_map(offset, size, dev); | ||
230 | if (map && map->type == _DRM_AGP) { | ||
231 | vunmap(pt); | ||
232 | return; | ||
233 | } | ||
234 | } | ||
235 | |||
236 | iounmap(pt); | ||
237 | } | 180 | } |
238 | EXPORT_SYMBOL(drm_ioremapfree); | 181 | EXPORT_SYMBOL(drm_core_ioremapfree); |
239 | 182 | ||
240 | #endif /* debug_memory */ | ||
diff --git a/drivers/char/drm/drm_memory.h b/drivers/char/drm/drm_memory.h index f1b97aff10cf..63e425b5ea82 100644 --- a/drivers/char/drm/drm_memory.h +++ b/drivers/char/drm/drm_memory.h | |||
@@ -56,26 +56,6 @@ | |||
56 | # endif | 56 | # endif |
57 | #endif | 57 | #endif |
58 | 58 | ||
59 | static inline unsigned long drm_follow_page(void *vaddr) | ||
60 | { | ||
61 | pgd_t *pgd = pgd_offset_k((unsigned long)vaddr); | ||
62 | pud_t *pud = pud_offset(pgd, (unsigned long)vaddr); | ||
63 | pmd_t *pmd = pmd_offset(pud, (unsigned long)vaddr); | ||
64 | pte_t *ptep = pte_offset_kernel(pmd, (unsigned long)vaddr); | ||
65 | return pte_pfn(*ptep) << PAGE_SHIFT; | ||
66 | } | ||
67 | |||
68 | #else /* __OS_HAS_AGP */ | 59 | #else /* __OS_HAS_AGP */ |
69 | 60 | ||
70 | static inline unsigned long drm_follow_page(void *vaddr) | ||
71 | { | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | #endif | 61 | #endif |
76 | |||
77 | void *drm_ioremap(unsigned long offset, unsigned long size, | ||
78 | drm_device_t * dev); | ||
79 | |||
80 | void drm_ioremapfree(void *pt, unsigned long size, | ||
81 | drm_device_t * dev); | ||
diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h index 74581af806e1..6463271deea8 100644 --- a/drivers/char/drm/drm_memory_debug.h +++ b/drivers/char/drm/drm_memory_debug.h | |||
@@ -205,76 +205,6 @@ void drm_free (void *pt, size_t size, int area) { | |||
205 | } | 205 | } |
206 | } | 206 | } |
207 | 207 | ||
208 | void *drm_ioremap (unsigned long offset, unsigned long size, | ||
209 | drm_device_t * dev) { | ||
210 | void *pt; | ||
211 | |||
212 | if (!size) { | ||
213 | DRM_MEM_ERROR(DRM_MEM_MAPPINGS, | ||
214 | "Mapping 0 bytes at 0x%08lx\n", offset); | ||
215 | return NULL; | ||
216 | } | ||
217 | |||
218 | if (!(pt = drm_ioremap(offset, size, dev))) { | ||
219 | spin_lock(&drm_mem_lock); | ||
220 | ++drm_mem_stats[DRM_MEM_MAPPINGS].fail_count; | ||
221 | spin_unlock(&drm_mem_lock); | ||
222 | return NULL; | ||
223 | } | ||
224 | spin_lock(&drm_mem_lock); | ||
225 | ++drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count; | ||
226 | drm_mem_stats[DRM_MEM_MAPPINGS].bytes_allocated += size; | ||
227 | spin_unlock(&drm_mem_lock); | ||
228 | return pt; | ||
229 | } | ||
230 | |||
231 | #if 0 | ||
232 | void *drm_ioremap_nocache (unsigned long offset, unsigned long size, | ||
233 | drm_device_t * dev) { | ||
234 | void *pt; | ||
235 | |||
236 | if (!size) { | ||
237 | DRM_MEM_ERROR(DRM_MEM_MAPPINGS, | ||
238 | "Mapping 0 bytes at 0x%08lx\n", offset); | ||
239 | return NULL; | ||
240 | } | ||
241 | |||
242 | if (!(pt = drm_ioremap_nocache(offset, size, dev))) { | ||
243 | spin_lock(&drm_mem_lock); | ||
244 | ++drm_mem_stats[DRM_MEM_MAPPINGS].fail_count; | ||
245 | spin_unlock(&drm_mem_lock); | ||
246 | return NULL; | ||
247 | } | ||
248 | spin_lock(&drm_mem_lock); | ||
249 | ++drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count; | ||
250 | drm_mem_stats[DRM_MEM_MAPPINGS].bytes_allocated += size; | ||
251 | spin_unlock(&drm_mem_lock); | ||
252 | return pt; | ||
253 | } | ||
254 | #endif /* 0 */ | ||
255 | |||
256 | void drm_ioremapfree (void *pt, unsigned long size, drm_device_t * dev) { | ||
257 | int alloc_count; | ||
258 | int free_count; | ||
259 | |||
260 | if (!pt) | ||
261 | DRM_MEM_ERROR(DRM_MEM_MAPPINGS, | ||
262 | "Attempt to free NULL pointer\n"); | ||
263 | else | ||
264 | drm_ioremapfree(pt, size, dev); | ||
265 | |||
266 | spin_lock(&drm_mem_lock); | ||
267 | drm_mem_stats[DRM_MEM_MAPPINGS].bytes_freed += size; | ||
268 | free_count = ++drm_mem_stats[DRM_MEM_MAPPINGS].free_count; | ||
269 | alloc_count = drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count; | ||
270 | spin_unlock(&drm_mem_lock); | ||
271 | if (free_count > alloc_count) { | ||
272 | DRM_MEM_ERROR(DRM_MEM_MAPPINGS, | ||
273 | "Excess frees: %d frees, %d allocs\n", | ||
274 | free_count, alloc_count); | ||
275 | } | ||
276 | } | ||
277 | |||
278 | #if __OS_HAS_AGP | 208 | #if __OS_HAS_AGP |
279 | 209 | ||
280 | DRM_AGP_MEM *drm_alloc_agp (drm_device_t *dev, int pages, u32 type) { | 210 | DRM_AGP_MEM *drm_alloc_agp (drm_device_t *dev, int pages, u32 type) { |
diff --git a/drivers/char/drm/drm_mm.c b/drivers/char/drm/drm_mm.c index 617526bd5b0c..9b46b85027d0 100644 --- a/drivers/char/drm/drm_mm.c +++ b/drivers/char/drm/drm_mm.c | |||
@@ -42,36 +42,131 @@ | |||
42 | */ | 42 | */ |
43 | 43 | ||
44 | #include "drmP.h" | 44 | #include "drmP.h" |
45 | #include <linux/slab.h> | ||
46 | |||
47 | unsigned long drm_mm_tail_space(drm_mm_t *mm) | ||
48 | { | ||
49 | struct list_head *tail_node; | ||
50 | drm_mm_node_t *entry; | ||
51 | |||
52 | tail_node = mm->ml_entry.prev; | ||
53 | entry = list_entry(tail_node, drm_mm_node_t, ml_entry); | ||
54 | if (!entry->free) | ||
55 | return 0; | ||
56 | |||
57 | return entry->size; | ||
58 | } | ||
59 | |||
60 | int drm_mm_remove_space_from_tail(drm_mm_t *mm, unsigned long size) | ||
61 | { | ||
62 | struct list_head *tail_node; | ||
63 | drm_mm_node_t *entry; | ||
64 | |||
65 | tail_node = mm->ml_entry.prev; | ||
66 | entry = list_entry(tail_node, drm_mm_node_t, ml_entry); | ||
67 | if (!entry->free) | ||
68 | return -ENOMEM; | ||
69 | |||
70 | if (entry->size <= size) | ||
71 | return -ENOMEM; | ||
72 | |||
73 | entry->size -= size; | ||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | |||
78 | static int drm_mm_create_tail_node(drm_mm_t *mm, | ||
79 | unsigned long start, | ||
80 | unsigned long size) | ||
81 | { | ||
82 | drm_mm_node_t *child; | ||
83 | |||
84 | child = (drm_mm_node_t *) | ||
85 | drm_alloc(sizeof(*child), DRM_MEM_MM); | ||
86 | if (!child) | ||
87 | return -ENOMEM; | ||
88 | |||
89 | child->free = 1; | ||
90 | child->size = size; | ||
91 | child->start = start; | ||
92 | child->mm = mm; | ||
93 | |||
94 | list_add_tail(&child->ml_entry, &mm->ml_entry); | ||
95 | list_add_tail(&child->fl_entry, &mm->fl_entry); | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | |||
101 | int drm_mm_add_space_to_tail(drm_mm_t *mm, unsigned long size) | ||
102 | { | ||
103 | struct list_head *tail_node; | ||
104 | drm_mm_node_t *entry; | ||
105 | |||
106 | tail_node = mm->ml_entry.prev; | ||
107 | entry = list_entry(tail_node, drm_mm_node_t, ml_entry); | ||
108 | if (!entry->free) { | ||
109 | return drm_mm_create_tail_node(mm, entry->start + entry->size, size); | ||
110 | } | ||
111 | entry->size += size; | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static drm_mm_node_t *drm_mm_split_at_start(drm_mm_node_t *parent, | ||
116 | unsigned long size) | ||
117 | { | ||
118 | drm_mm_node_t *child; | ||
119 | |||
120 | child = (drm_mm_node_t *) | ||
121 | drm_alloc(sizeof(*child), DRM_MEM_MM); | ||
122 | if (!child) | ||
123 | return NULL; | ||
124 | |||
125 | INIT_LIST_HEAD(&child->fl_entry); | ||
126 | |||
127 | child->free = 0; | ||
128 | child->size = size; | ||
129 | child->start = parent->start; | ||
130 | child->mm = parent->mm; | ||
131 | |||
132 | list_add_tail(&child->ml_entry, &parent->ml_entry); | ||
133 | INIT_LIST_HEAD(&child->fl_entry); | ||
134 | |||
135 | parent->size -= size; | ||
136 | parent->start += size; | ||
137 | return child; | ||
138 | } | ||
139 | |||
140 | |||
45 | 141 | ||
46 | drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent, | 142 | drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent, |
47 | unsigned long size, unsigned alignment) | 143 | unsigned long size, unsigned alignment) |
48 | { | 144 | { |
49 | 145 | ||
146 | drm_mm_node_t *align_splitoff = NULL; | ||
50 | drm_mm_node_t *child; | 147 | drm_mm_node_t *child; |
148 | unsigned tmp = 0; | ||
51 | 149 | ||
52 | if (alignment) | 150 | if (alignment) |
53 | size += alignment - 1; | 151 | tmp = parent->start % alignment; |
152 | |||
153 | if (tmp) { | ||
154 | align_splitoff = drm_mm_split_at_start(parent, alignment - tmp); | ||
155 | if (!align_splitoff) | ||
156 | return NULL; | ||
157 | } | ||
54 | 158 | ||
55 | if (parent->size == size) { | 159 | if (parent->size == size) { |
56 | list_del_init(&parent->fl_entry); | 160 | list_del_init(&parent->fl_entry); |
57 | parent->free = 0; | 161 | parent->free = 0; |
58 | return parent; | 162 | return parent; |
59 | } else { | 163 | } else { |
60 | child = (drm_mm_node_t *) drm_alloc(sizeof(*child), DRM_MEM_MM); | 164 | child = drm_mm_split_at_start(parent, size); |
61 | if (!child) | 165 | } |
62 | return NULL; | ||
63 | |||
64 | INIT_LIST_HEAD(&child->ml_entry); | ||
65 | INIT_LIST_HEAD(&child->fl_entry); | ||
66 | 166 | ||
67 | child->free = 0; | 167 | if (align_splitoff) |
68 | child->size = size; | 168 | drm_mm_put_block(align_splitoff); |
69 | child->start = parent->start; | ||
70 | 169 | ||
71 | list_add_tail(&child->ml_entry, &parent->ml_entry); | ||
72 | parent->size -= size; | ||
73 | parent->start += size; | ||
74 | } | ||
75 | return child; | 170 | return child; |
76 | } | 171 | } |
77 | 172 | ||
@@ -80,12 +175,12 @@ drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent, | |||
80 | * Otherwise add to the free stack. | 175 | * Otherwise add to the free stack. |
81 | */ | 176 | */ |
82 | 177 | ||
83 | void drm_mm_put_block(drm_mm_t * mm, drm_mm_node_t * cur) | 178 | void drm_mm_put_block(drm_mm_node_t * cur) |
84 | { | 179 | { |
85 | 180 | ||
86 | drm_mm_node_t *list_root = &mm->root_node; | 181 | drm_mm_t *mm = cur->mm; |
87 | struct list_head *cur_head = &cur->ml_entry; | 182 | struct list_head *cur_head = &cur->ml_entry; |
88 | struct list_head *root_head = &list_root->ml_entry; | 183 | struct list_head *root_head = &mm->ml_entry; |
89 | drm_mm_node_t *prev_node = NULL; | 184 | drm_mm_node_t *prev_node = NULL; |
90 | drm_mm_node_t *next_node; | 185 | drm_mm_node_t *next_node; |
91 | 186 | ||
@@ -116,7 +211,7 @@ void drm_mm_put_block(drm_mm_t * mm, drm_mm_node_t * cur) | |||
116 | } | 211 | } |
117 | if (!merged) { | 212 | if (!merged) { |
118 | cur->free = 1; | 213 | cur->free = 1; |
119 | list_add(&cur->fl_entry, &list_root->fl_entry); | 214 | list_add(&cur->fl_entry, &mm->fl_entry); |
120 | } else { | 215 | } else { |
121 | list_del(&cur->ml_entry); | 216 | list_del(&cur->ml_entry); |
122 | drm_free(cur, sizeof(*cur), DRM_MEM_MM); | 217 | drm_free(cur, sizeof(*cur), DRM_MEM_MM); |
@@ -128,20 +223,30 @@ drm_mm_node_t *drm_mm_search_free(const drm_mm_t * mm, | |||
128 | unsigned alignment, int best_match) | 223 | unsigned alignment, int best_match) |
129 | { | 224 | { |
130 | struct list_head *list; | 225 | struct list_head *list; |
131 | const struct list_head *free_stack = &mm->root_node.fl_entry; | 226 | const struct list_head *free_stack = &mm->fl_entry; |
132 | drm_mm_node_t *entry; | 227 | drm_mm_node_t *entry; |
133 | drm_mm_node_t *best; | 228 | drm_mm_node_t *best; |
134 | unsigned long best_size; | 229 | unsigned long best_size; |
230 | unsigned wasted; | ||
135 | 231 | ||
136 | best = NULL; | 232 | best = NULL; |
137 | best_size = ~0UL; | 233 | best_size = ~0UL; |
138 | 234 | ||
139 | if (alignment) | ||
140 | size += alignment - 1; | ||
141 | |||
142 | list_for_each(list, free_stack) { | 235 | list_for_each(list, free_stack) { |
143 | entry = list_entry(list, drm_mm_node_t, fl_entry); | 236 | entry = list_entry(list, drm_mm_node_t, fl_entry); |
144 | if (entry->size >= size) { | 237 | wasted = 0; |
238 | |||
239 | if (entry->size < size) | ||
240 | continue; | ||
241 | |||
242 | if (alignment) { | ||
243 | register unsigned tmp = entry->start % alignment; | ||
244 | if (tmp) | ||
245 | wasted += alignment - tmp; | ||
246 | } | ||
247 | |||
248 | |||
249 | if (entry->size >= size + wasted) { | ||
145 | if (!best_match) | 250 | if (!best_match) |
146 | return entry; | 251 | return entry; |
147 | if (size < best_size) { | 252 | if (size < best_size) { |
@@ -154,40 +259,32 @@ drm_mm_node_t *drm_mm_search_free(const drm_mm_t * mm, | |||
154 | return best; | 259 | return best; |
155 | } | 260 | } |
156 | 261 | ||
157 | int drm_mm_init(drm_mm_t * mm, unsigned long start, unsigned long size) | 262 | int drm_mm_clean(drm_mm_t * mm) |
158 | { | 263 | { |
159 | drm_mm_node_t *child; | 264 | struct list_head *head = &mm->ml_entry; |
160 | |||
161 | INIT_LIST_HEAD(&mm->root_node.ml_entry); | ||
162 | INIT_LIST_HEAD(&mm->root_node.fl_entry); | ||
163 | child = (drm_mm_node_t *) drm_alloc(sizeof(*child), DRM_MEM_MM); | ||
164 | if (!child) | ||
165 | return -ENOMEM; | ||
166 | |||
167 | INIT_LIST_HEAD(&child->ml_entry); | ||
168 | INIT_LIST_HEAD(&child->fl_entry); | ||
169 | 265 | ||
170 | child->start = start; | 266 | return (head->next->next == head); |
171 | child->size = size; | 267 | } |
172 | child->free = 1; | ||
173 | 268 | ||
174 | list_add(&child->fl_entry, &mm->root_node.fl_entry); | 269 | int drm_mm_init(drm_mm_t * mm, unsigned long start, unsigned long size) |
175 | list_add(&child->ml_entry, &mm->root_node.ml_entry); | 270 | { |
271 | INIT_LIST_HEAD(&mm->ml_entry); | ||
272 | INIT_LIST_HEAD(&mm->fl_entry); | ||
176 | 273 | ||
177 | return 0; | 274 | return drm_mm_create_tail_node(mm, start, size); |
178 | } | 275 | } |
179 | 276 | ||
180 | EXPORT_SYMBOL(drm_mm_init); | 277 | EXPORT_SYMBOL(drm_mm_init); |
181 | 278 | ||
182 | void drm_mm_takedown(drm_mm_t * mm) | 279 | void drm_mm_takedown(drm_mm_t * mm) |
183 | { | 280 | { |
184 | struct list_head *bnode = mm->root_node.fl_entry.next; | 281 | struct list_head *bnode = mm->fl_entry.next; |
185 | drm_mm_node_t *entry; | 282 | drm_mm_node_t *entry; |
186 | 283 | ||
187 | entry = list_entry(bnode, drm_mm_node_t, fl_entry); | 284 | entry = list_entry(bnode, drm_mm_node_t, fl_entry); |
188 | 285 | ||
189 | if (entry->ml_entry.next != &mm->root_node.ml_entry || | 286 | if (entry->ml_entry.next != &mm->ml_entry || |
190 | entry->fl_entry.next != &mm->root_node.fl_entry) { | 287 | entry->fl_entry.next != &mm->fl_entry) { |
191 | DRM_ERROR("Memory manager not clean. Delaying takedown\n"); | 288 | DRM_ERROR("Memory manager not clean. Delaying takedown\n"); |
192 | return; | 289 | return; |
193 | } | 290 | } |
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index 09398d5fbd3f..ad54b845978b 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h | |||
@@ -226,12 +226,14 @@ | |||
226 | {0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 226 | {0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
227 | {0x1106, 0x3118, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_PRO_GROUP_A}, \ | 227 | {0x1106, 0x3118, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_PRO_GROUP_A}, \ |
228 | {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 228 | {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
229 | {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
229 | {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 230 | {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
230 | {0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 231 | {0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
231 | {0x1106, 0x3304, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 232 | {0x1106, 0x3304, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
232 | {0x1106, 0x3157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 233 | {0x1106, 0x3157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
233 | {0x1106, 0x3344, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 234 | {0x1106, 0x3344, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
234 | {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 235 | {0x1106, 0x3343, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
236 | {0x1106, 0x3230, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_DX9_0}, \ | ||
235 | {0, 0, 0} | 237 | {0, 0, 0} |
236 | 238 | ||
237 | #define i810_PCI_IDS \ | 239 | #define i810_PCI_IDS \ |
diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c index 62d5fe15f046..7fd0da712142 100644 --- a/drivers/char/drm/drm_proc.c +++ b/drivers/char/drm/drm_proc.c | |||
@@ -500,7 +500,7 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request, | |||
500 | for (pt = dev->vmalist; pt; pt = pt->next) { | 500 | for (pt = dev->vmalist; pt; pt = pt->next) { |
501 | if (!(vma = pt->vma)) | 501 | if (!(vma = pt->vma)) |
502 | continue; | 502 | continue; |
503 | DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx", | 503 | DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000", |
504 | pt->pid, | 504 | pt->pid, |
505 | vma->vm_start, | 505 | vma->vm_start, |
506 | vma->vm_end, | 506 | vma->vm_end, |
@@ -510,7 +510,7 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request, | |||
510 | vma->vm_flags & VM_MAYSHARE ? 's' : 'p', | 510 | vma->vm_flags & VM_MAYSHARE ? 's' : 'p', |
511 | vma->vm_flags & VM_LOCKED ? 'l' : '-', | 511 | vma->vm_flags & VM_LOCKED ? 'l' : '-', |
512 | vma->vm_flags & VM_IO ? 'i' : '-', | 512 | vma->vm_flags & VM_IO ? 'i' : '-', |
513 | vma->vm_pgoff << PAGE_SHIFT); | 513 | vma->vm_pgoff); |
514 | 514 | ||
515 | #if defined(__i386__) | 515 | #if defined(__i386__) |
516 | pgprot = pgprot_val(vma->vm_page_prot); | 516 | pgprot = pgprot_val(vma->vm_page_prot); |
diff --git a/drivers/char/drm/drm_sman.c b/drivers/char/drm/drm_sman.c index 19c81d2e13d0..e15db6d6bea9 100644 --- a/drivers/char/drm/drm_sman.c +++ b/drivers/char/drm/drm_sman.c | |||
@@ -101,10 +101,9 @@ static void *drm_sman_mm_allocate(void *private, unsigned long size, | |||
101 | 101 | ||
102 | static void drm_sman_mm_free(void *private, void *ref) | 102 | static void drm_sman_mm_free(void *private, void *ref) |
103 | { | 103 | { |
104 | drm_mm_t *mm = (drm_mm_t *) private; | ||
105 | drm_mm_node_t *node = (drm_mm_node_t *) ref; | 104 | drm_mm_node_t *node = (drm_mm_node_t *) ref; |
106 | 105 | ||
107 | drm_mm_put_block(mm, node); | 106 | drm_mm_put_block(node); |
108 | } | 107 | } |
109 | 108 | ||
110 | static void drm_sman_mm_destroy(void *private) | 109 | static void drm_sman_mm_destroy(void *private) |
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c index b9cfc077f6bc..54a632848955 100644 --- a/drivers/char/drm/drm_vm.c +++ b/drivers/char/drm/drm_vm.c | |||
@@ -70,7 +70,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, | |||
70 | if (!dev->agp || !dev->agp->cant_use_aperture) | 70 | if (!dev->agp || !dev->agp->cant_use_aperture) |
71 | goto vm_nopage_error; | 71 | goto vm_nopage_error; |
72 | 72 | ||
73 | if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff << PAGE_SHIFT, &hash)) | 73 | if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash)) |
74 | goto vm_nopage_error; | 74 | goto vm_nopage_error; |
75 | 75 | ||
76 | r_list = drm_hash_entry(hash, drm_map_list_t, hash); | 76 | r_list = drm_hash_entry(hash, drm_map_list_t, hash); |
@@ -227,7 +227,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) | |||
227 | map->size); | 227 | map->size); |
228 | DRM_DEBUG("mtrr_del = %d\n", retcode); | 228 | DRM_DEBUG("mtrr_del = %d\n", retcode); |
229 | } | 229 | } |
230 | drm_ioremapfree(map->handle, map->size, dev); | 230 | iounmap(map->handle); |
231 | break; | 231 | break; |
232 | case _DRM_SHM: | 232 | case _DRM_SHM: |
233 | vfree(map->handle); | 233 | vfree(map->handle); |
@@ -463,8 +463,8 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) | |||
463 | lock_kernel(); | 463 | lock_kernel(); |
464 | dev = priv->head->dev; | 464 | dev = priv->head->dev; |
465 | dma = dev->dma; | 465 | dma = dev->dma; |
466 | DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", | 466 | DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n", |
467 | vma->vm_start, vma->vm_end, vma->vm_pgoff << PAGE_SHIFT); | 467 | vma->vm_start, vma->vm_end, vma->vm_pgoff); |
468 | 468 | ||
469 | /* Length must match exact page count */ | 469 | /* Length must match exact page count */ |
470 | if (!dma || (length >> PAGE_SHIFT) != dma->page_count) { | 470 | if (!dma || (length >> PAGE_SHIFT) != dma->page_count) { |
@@ -537,8 +537,8 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
537 | unsigned long offset = 0; | 537 | unsigned long offset = 0; |
538 | drm_hash_item_t *hash; | 538 | drm_hash_item_t *hash; |
539 | 539 | ||
540 | DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", | 540 | DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n", |
541 | vma->vm_start, vma->vm_end, vma->vm_pgoff << PAGE_SHIFT); | 541 | vma->vm_start, vma->vm_end, vma->vm_pgoff); |
542 | 542 | ||
543 | if (!priv->authenticated) | 543 | if (!priv->authenticated) |
544 | return -EACCES; | 544 | return -EACCES; |
@@ -547,7 +547,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
547 | * the AGP mapped at physical address 0 | 547 | * the AGP mapped at physical address 0 |
548 | * --BenH. | 548 | * --BenH. |
549 | */ | 549 | */ |
550 | if (!(vma->vm_pgoff << PAGE_SHIFT) | 550 | if (!vma->vm_pgoff |
551 | #if __OS_HAS_AGP | 551 | #if __OS_HAS_AGP |
552 | && (!dev->agp | 552 | && (!dev->agp |
553 | || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE) | 553 | || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE) |
@@ -555,7 +555,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
555 | ) | 555 | ) |
556 | return drm_mmap_dma(filp, vma); | 556 | return drm_mmap_dma(filp, vma); |
557 | 557 | ||
558 | if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff << PAGE_SHIFT, &hash)) { | 558 | if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash)) { |
559 | DRM_ERROR("Could not find map\n"); | 559 | DRM_ERROR("Could not find map\n"); |
560 | return -EINVAL; | 560 | return -EINVAL; |
561 | } | 561 | } |
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c index fa2de70f7401..603d17fd2d69 100644 --- a/drivers/char/drm/i810_dma.c +++ b/drivers/char/drm/i810_dma.c | |||
@@ -112,7 +112,7 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) | |||
112 | return 0; | 112 | return 0; |
113 | } | 113 | } |
114 | 114 | ||
115 | static struct file_operations i810_buffer_fops = { | 115 | static const struct file_operations i810_buffer_fops = { |
116 | .open = drm_open, | 116 | .open = drm_open, |
117 | .release = drm_release, | 117 | .release = drm_release, |
118 | .ioctl = drm_ioctl, | 118 | .ioctl = drm_ioctl, |
@@ -219,8 +219,7 @@ static int i810_dma_cleanup(drm_device_t * dev) | |||
219 | (drm_i810_private_t *) dev->dev_private; | 219 | (drm_i810_private_t *) dev->dev_private; |
220 | 220 | ||
221 | if (dev_priv->ring.virtual_start) { | 221 | if (dev_priv->ring.virtual_start) { |
222 | drm_ioremapfree((void *)dev_priv->ring.virtual_start, | 222 | drm_core_ioremapfree(&dev_priv->ring.map, dev); |
223 | dev_priv->ring.Size, dev); | ||
224 | } | 223 | } |
225 | if (dev_priv->hw_status_page) { | 224 | if (dev_priv->hw_status_page) { |
226 | pci_free_consistent(dev->pdev, PAGE_SIZE, | 225 | pci_free_consistent(dev->pdev, PAGE_SIZE, |
@@ -236,9 +235,9 @@ static int i810_dma_cleanup(drm_device_t * dev) | |||
236 | for (i = 0; i < dma->buf_count; i++) { | 235 | for (i = 0; i < dma->buf_count; i++) { |
237 | drm_buf_t *buf = dma->buflist[i]; | 236 | drm_buf_t *buf = dma->buflist[i]; |
238 | drm_i810_buf_priv_t *buf_priv = buf->dev_private; | 237 | drm_i810_buf_priv_t *buf_priv = buf->dev_private; |
238 | |||
239 | if (buf_priv->kernel_virtual && buf->total) | 239 | if (buf_priv->kernel_virtual && buf->total) |
240 | drm_ioremapfree(buf_priv->kernel_virtual, | 240 | drm_core_ioremapfree(&buf_priv->map, dev); |
241 | buf->total, dev); | ||
242 | } | 241 | } |
243 | } | 242 | } |
244 | return 0; | 243 | return 0; |
@@ -311,8 +310,15 @@ static int i810_freelist_init(drm_device_t * dev, drm_i810_private_t * dev_priv) | |||
311 | 310 | ||
312 | *buf_priv->in_use = I810_BUF_FREE; | 311 | *buf_priv->in_use = I810_BUF_FREE; |
313 | 312 | ||
314 | buf_priv->kernel_virtual = drm_ioremap(buf->bus_address, | 313 | buf_priv->map.offset = buf->bus_address; |
315 | buf->total, dev); | 314 | buf_priv->map.size = buf->total; |
315 | buf_priv->map.type = _DRM_AGP; | ||
316 | buf_priv->map.flags = 0; | ||
317 | buf_priv->map.mtrr = 0; | ||
318 | |||
319 | drm_core_ioremap(&buf_priv->map, dev); | ||
320 | buf_priv->kernel_virtual = buf_priv->map.handle; | ||
321 | |||
316 | } | 322 | } |
317 | return 0; | 323 | return 0; |
318 | } | 324 | } |
@@ -363,18 +369,24 @@ static int i810_dma_initialize(drm_device_t * dev, | |||
363 | dev_priv->ring.End = init->ring_end; | 369 | dev_priv->ring.End = init->ring_end; |
364 | dev_priv->ring.Size = init->ring_size; | 370 | dev_priv->ring.Size = init->ring_size; |
365 | 371 | ||
366 | dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base + | 372 | dev_priv->ring.map.offset = dev->agp->base + init->ring_start; |
367 | init->ring_start, | 373 | dev_priv->ring.map.size = init->ring_size; |
368 | init->ring_size, dev); | 374 | dev_priv->ring.map.type = _DRM_AGP; |
375 | dev_priv->ring.map.flags = 0; | ||
376 | dev_priv->ring.map.mtrr = 0; | ||
369 | 377 | ||
370 | if (dev_priv->ring.virtual_start == NULL) { | 378 | drm_core_ioremap(&dev_priv->ring.map, dev); |
379 | |||
380 | if (dev_priv->ring.map.handle == NULL) { | ||
371 | dev->dev_private = (void *)dev_priv; | 381 | dev->dev_private = (void *)dev_priv; |
372 | i810_dma_cleanup(dev); | 382 | i810_dma_cleanup(dev); |
373 | DRM_ERROR("can not ioremap virtual address for" | 383 | DRM_ERROR("can not ioremap virtual address for" |
374 | " ring buffer\n"); | 384 | " ring buffer\n"); |
375 | return -ENOMEM; | 385 | return DRM_ERR(ENOMEM); |
376 | } | 386 | } |
377 | 387 | ||
388 | dev_priv->ring.virtual_start = dev_priv->ring.map.handle; | ||
389 | |||
378 | dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; | 390 | dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; |
379 | 391 | ||
380 | dev_priv->w = init->w; | 392 | dev_priv->w = init->w; |
diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h index e8cf3ff606f0..e6df49f4928a 100644 --- a/drivers/char/drm/i810_drv.h +++ b/drivers/char/drm/i810_drv.h | |||
@@ -61,6 +61,7 @@ typedef struct drm_i810_buf_priv { | |||
61 | int currently_mapped; | 61 | int currently_mapped; |
62 | void *virtual; | 62 | void *virtual; |
63 | void *kernel_virtual; | 63 | void *kernel_virtual; |
64 | drm_local_map_t map; | ||
64 | } drm_i810_buf_priv_t; | 65 | } drm_i810_buf_priv_t; |
65 | 66 | ||
66 | typedef struct _drm_i810_ring_buffer { | 67 | typedef struct _drm_i810_ring_buffer { |
@@ -72,6 +73,7 @@ typedef struct _drm_i810_ring_buffer { | |||
72 | int head; | 73 | int head; |
73 | int tail; | 74 | int tail; |
74 | int space; | 75 | int space; |
76 | drm_local_map_t map; | ||
75 | } drm_i810_ring_buffer_t; | 77 | } drm_i810_ring_buffer_t; |
76 | 78 | ||
77 | typedef struct drm_i810_private { | 79 | typedef struct drm_i810_private { |
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c index 4f0e5746ab33..3314a9fea9e5 100644 --- a/drivers/char/drm/i830_dma.c +++ b/drivers/char/drm/i830_dma.c | |||
@@ -114,7 +114,7 @@ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma) | |||
114 | return 0; | 114 | return 0; |
115 | } | 115 | } |
116 | 116 | ||
117 | static struct file_operations i830_buffer_fops = { | 117 | static const struct file_operations i830_buffer_fops = { |
118 | .open = drm_open, | 118 | .open = drm_open, |
119 | .release = drm_release, | 119 | .release = drm_release, |
120 | .ioctl = drm_ioctl, | 120 | .ioctl = drm_ioctl, |
@@ -223,8 +223,7 @@ static int i830_dma_cleanup(drm_device_t * dev) | |||
223 | (drm_i830_private_t *) dev->dev_private; | 223 | (drm_i830_private_t *) dev->dev_private; |
224 | 224 | ||
225 | if (dev_priv->ring.virtual_start) { | 225 | if (dev_priv->ring.virtual_start) { |
226 | drm_ioremapfree((void *)dev_priv->ring.virtual_start, | 226 | drm_core_ioremapfree(&dev_priv->ring.map, dev); |
227 | dev_priv->ring.Size, dev); | ||
228 | } | 227 | } |
229 | if (dev_priv->hw_status_page) { | 228 | if (dev_priv->hw_status_page) { |
230 | pci_free_consistent(dev->pdev, PAGE_SIZE, | 229 | pci_free_consistent(dev->pdev, PAGE_SIZE, |
@@ -242,8 +241,7 @@ static int i830_dma_cleanup(drm_device_t * dev) | |||
242 | drm_buf_t *buf = dma->buflist[i]; | 241 | drm_buf_t *buf = dma->buflist[i]; |
243 | drm_i830_buf_priv_t *buf_priv = buf->dev_private; | 242 | drm_i830_buf_priv_t *buf_priv = buf->dev_private; |
244 | if (buf_priv->kernel_virtual && buf->total) | 243 | if (buf_priv->kernel_virtual && buf->total) |
245 | drm_ioremapfree(buf_priv->kernel_virtual, | 244 | drm_core_ioremapfree(&buf_priv->map, dev); |
246 | buf->total, dev); | ||
247 | } | 245 | } |
248 | } | 246 | } |
249 | return 0; | 247 | return 0; |
@@ -320,8 +318,14 @@ static int i830_freelist_init(drm_device_t * dev, drm_i830_private_t * dev_priv) | |||
320 | 318 | ||
321 | *buf_priv->in_use = I830_BUF_FREE; | 319 | *buf_priv->in_use = I830_BUF_FREE; |
322 | 320 | ||
323 | buf_priv->kernel_virtual = drm_ioremap(buf->bus_address, | 321 | buf_priv->map.offset = buf->bus_address; |
324 | buf->total, dev); | 322 | buf_priv->map.size = buf->total; |
323 | buf_priv->map.type = _DRM_AGP; | ||
324 | buf_priv->map.flags = 0; | ||
325 | buf_priv->map.mtrr = 0; | ||
326 | |||
327 | drm_core_ioremap(&buf_priv->map, dev); | ||
328 | buf_priv->kernel_virtual = buf_priv->map.handle; | ||
325 | } | 329 | } |
326 | return 0; | 330 | return 0; |
327 | } | 331 | } |
@@ -373,18 +377,24 @@ static int i830_dma_initialize(drm_device_t * dev, | |||
373 | dev_priv->ring.End = init->ring_end; | 377 | dev_priv->ring.End = init->ring_end; |
374 | dev_priv->ring.Size = init->ring_size; | 378 | dev_priv->ring.Size = init->ring_size; |
375 | 379 | ||
376 | dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base + | 380 | dev_priv->ring.map.offset = dev->agp->base + init->ring_start; |
377 | init->ring_start, | 381 | dev_priv->ring.map.size = init->ring_size; |
378 | init->ring_size, dev); | 382 | dev_priv->ring.map.type = _DRM_AGP; |
383 | dev_priv->ring.map.flags = 0; | ||
384 | dev_priv->ring.map.mtrr = 0; | ||
385 | |||
386 | drm_core_ioremap(&dev_priv->ring.map, dev); | ||
379 | 387 | ||
380 | if (dev_priv->ring.virtual_start == NULL) { | 388 | if (dev_priv->ring.map.handle == NULL) { |
381 | dev->dev_private = (void *)dev_priv; | 389 | dev->dev_private = (void *)dev_priv; |
382 | i830_dma_cleanup(dev); | 390 | i830_dma_cleanup(dev); |
383 | DRM_ERROR("can not ioremap virtual address for" | 391 | DRM_ERROR("can not ioremap virtual address for" |
384 | " ring buffer\n"); | 392 | " ring buffer\n"); |
385 | return -ENOMEM; | 393 | return DRM_ERR(ENOMEM); |
386 | } | 394 | } |
387 | 395 | ||
396 | dev_priv->ring.virtual_start = dev_priv->ring.map.handle; | ||
397 | |||
388 | dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; | 398 | dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; |
389 | 399 | ||
390 | dev_priv->w = init->w; | 400 | dev_priv->w = init->w; |
diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h index 85bc5be6f916..e91f94afb4bb 100644 --- a/drivers/char/drm/i830_drv.h +++ b/drivers/char/drm/i830_drv.h | |||
@@ -68,6 +68,7 @@ typedef struct drm_i830_buf_priv { | |||
68 | int currently_mapped; | 68 | int currently_mapped; |
69 | void __user *virtual; | 69 | void __user *virtual; |
70 | void *kernel_virtual; | 70 | void *kernel_virtual; |
71 | drm_local_map_t map; | ||
71 | } drm_i830_buf_priv_t; | 72 | } drm_i830_buf_priv_t; |
72 | 73 | ||
73 | typedef struct _drm_i830_ring_buffer { | 74 | typedef struct _drm_i830_ring_buffer { |
@@ -79,6 +80,7 @@ typedef struct _drm_i830_ring_buffer { | |||
79 | int head; | 80 | int head; |
80 | int tail; | 81 | int tail; |
81 | int space; | 82 | int space; |
83 | drm_local_map_t map; | ||
82 | } drm_i830_ring_buffer_t; | 84 | } drm_i830_ring_buffer_t; |
83 | 85 | ||
84 | typedef struct drm_i830_private { | 86 | typedef struct drm_i830_private { |
diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c index a691ae74129d..c0539c6299cf 100644 --- a/drivers/char/drm/via_dma.c +++ b/drivers/char/drm/via_dma.c | |||
@@ -190,6 +190,11 @@ static int via_initialize(drm_device_t * dev, | |||
190 | return DRM_ERR(EFAULT); | 190 | return DRM_ERR(EFAULT); |
191 | } | 191 | } |
192 | 192 | ||
193 | if (dev_priv->chipset == VIA_DX9_0) { | ||
194 | DRM_ERROR("AGP DMA is not supported on this chip\n"); | ||
195 | return DRM_ERR(EINVAL); | ||
196 | } | ||
197 | |||
193 | dev_priv->ring.map.offset = dev->agp->base + init->offset; | 198 | dev_priv->ring.map.offset = dev->agp->base + init->offset; |
194 | dev_priv->ring.map.size = init->size; | 199 | dev_priv->ring.map.size = init->size; |
195 | dev_priv->ring.map.type = 0; | 200 | dev_priv->ring.map.type = 0; |
@@ -480,6 +485,7 @@ static int via_hook_segment(drm_via_private_t * dev_priv, | |||
480 | VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); | 485 | VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); |
481 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); | 486 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); |
482 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); | 487 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); |
488 | VIA_READ(VIA_REG_TRANSPACE); | ||
483 | } | 489 | } |
484 | } | 490 | } |
485 | return paused; | 491 | return paused; |
@@ -557,8 +563,9 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv) | |||
557 | 563 | ||
558 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); | 564 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); |
559 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); | 565 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); |
560 | 566 | DRM_WRITEMEMORYBARRIER(); | |
561 | VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); | 567 | VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); |
568 | VIA_READ(VIA_REG_TRANSPACE); | ||
562 | } | 569 | } |
563 | 570 | ||
564 | static void via_pad_cache(drm_via_private_t * dev_priv, int qwords) | 571 | static void via_pad_cache(drm_via_private_t * dev_priv, int qwords) |
diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c index 806f9ce5f47b..2881a06b6f55 100644 --- a/drivers/char/drm/via_dmablit.c +++ b/drivers/char/drm/via_dmablit.c | |||
@@ -218,7 +218,9 @@ via_fire_dmablit(drm_device_t *dev, drm_via_sg_info_t *vsg, int engine) | |||
218 | VIA_WRITE(VIA_PCI_DMA_MR0 + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE); | 218 | VIA_WRITE(VIA_PCI_DMA_MR0 + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE); |
219 | VIA_WRITE(VIA_PCI_DMA_BCR0 + engine*0x10, 0); | 219 | VIA_WRITE(VIA_PCI_DMA_BCR0 + engine*0x10, 0); |
220 | VIA_WRITE(VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start); | 220 | VIA_WRITE(VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start); |
221 | DRM_WRITEMEMORYBARRIER(); | ||
221 | VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS); | 222 | VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS); |
223 | VIA_READ(VIA_PCI_DMA_CSR0 + engine*0x04); | ||
222 | } | 224 | } |
223 | 225 | ||
224 | /* | 226 | /* |
@@ -374,10 +376,8 @@ via_dmablit_handler(drm_device_t *dev, int engine, int from_irq) | |||
374 | blitq->cur = cur; | 376 | blitq->cur = cur; |
375 | blitq->num_outstanding--; | 377 | blitq->num_outstanding--; |
376 | blitq->end = jiffies + DRM_HZ; | 378 | blitq->end = jiffies + DRM_HZ; |
377 | if (!timer_pending(&blitq->poll_timer)) { | 379 | if (!timer_pending(&blitq->poll_timer)) |
378 | blitq->poll_timer.expires = jiffies+1; | 380 | mod_timer(&blitq->poll_timer, jiffies + 1); |
379 | add_timer(&blitq->poll_timer); | ||
380 | } | ||
381 | } else { | 381 | } else { |
382 | if (timer_pending(&blitq->poll_timer)) { | 382 | if (timer_pending(&blitq->poll_timer)) { |
383 | del_timer(&blitq->poll_timer); | 383 | del_timer(&blitq->poll_timer); |
@@ -476,8 +476,7 @@ via_dmablit_timer(unsigned long data) | |||
476 | via_dmablit_handler(dev, engine, 0); | 476 | via_dmablit_handler(dev, engine, 0); |
477 | 477 | ||
478 | if (!timer_pending(&blitq->poll_timer)) { | 478 | if (!timer_pending(&blitq->poll_timer)) { |
479 | blitq->poll_timer.expires = jiffies+1; | 479 | mod_timer(&blitq->poll_timer, jiffies + 1); |
480 | add_timer(&blitq->poll_timer); | ||
481 | 480 | ||
482 | /* | 481 | /* |
483 | * Rerun handler to delete timer if engines are off, and | 482 | * Rerun handler to delete timer if engines are off, and |
@@ -572,9 +571,8 @@ via_init_dmablit(drm_device_t *dev) | |||
572 | } | 571 | } |
573 | DRM_INIT_WAITQUEUE(&blitq->busy_queue); | 572 | DRM_INIT_WAITQUEUE(&blitq->busy_queue); |
574 | INIT_WORK(&blitq->wq, via_dmablit_workqueue); | 573 | INIT_WORK(&blitq->wq, via_dmablit_workqueue); |
575 | init_timer(&blitq->poll_timer); | 574 | setup_timer(&blitq->poll_timer, via_dmablit_timer, |
576 | blitq->poll_timer.function = &via_dmablit_timer; | 575 | (unsigned long)blitq); |
577 | blitq->poll_timer.data = (unsigned long) blitq; | ||
578 | } | 576 | } |
579 | } | 577 | } |
580 | 578 | ||
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h index d21b5b75da0f..8b8778d4a423 100644 --- a/drivers/char/drm/via_drv.h +++ b/drivers/char/drm/via_drv.h | |||
@@ -29,10 +29,10 @@ | |||
29 | 29 | ||
30 | #define DRIVER_NAME "via" | 30 | #define DRIVER_NAME "via" |
31 | #define DRIVER_DESC "VIA Unichrome / Pro" | 31 | #define DRIVER_DESC "VIA Unichrome / Pro" |
32 | #define DRIVER_DATE "20060529" | 32 | #define DRIVER_DATE "20061227" |
33 | 33 | ||
34 | #define DRIVER_MAJOR 2 | 34 | #define DRIVER_MAJOR 2 |
35 | #define DRIVER_MINOR 10 | 35 | #define DRIVER_MINOR 11 |
36 | #define DRIVER_PATCHLEVEL 0 | 36 | #define DRIVER_PATCHLEVEL 0 |
37 | 37 | ||
38 | #include "via_verifier.h" | 38 | #include "via_verifier.h" |
@@ -79,7 +79,7 @@ typedef struct drm_via_private { | |||
79 | char pci_buf[VIA_PCI_BUF_SIZE]; | 79 | char pci_buf[VIA_PCI_BUF_SIZE]; |
80 | const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE]; | 80 | const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE]; |
81 | uint32_t num_fire_offsets; | 81 | uint32_t num_fire_offsets; |
82 | int pro_group_a; | 82 | int chipset; |
83 | drm_via_irq_t via_irqs[VIA_NUM_IRQS]; | 83 | drm_via_irq_t via_irqs[VIA_NUM_IRQS]; |
84 | unsigned num_irqs; | 84 | unsigned num_irqs; |
85 | maskarray_t *irq_masks; | 85 | maskarray_t *irq_masks; |
@@ -96,8 +96,9 @@ typedef struct drm_via_private { | |||
96 | } drm_via_private_t; | 96 | } drm_via_private_t; |
97 | 97 | ||
98 | enum via_family { | 98 | enum via_family { |
99 | VIA_OTHER = 0, | 99 | VIA_OTHER = 0, /* Baseline */ |
100 | VIA_PRO_GROUP_A, | 100 | VIA_PRO_GROUP_A, /* Another video engine and DMA commands */ |
101 | VIA_DX9_0 /* Same video as pro_group_a, but 3D is unsupported */ | ||
101 | }; | 102 | }; |
102 | 103 | ||
103 | /* VIA MMIO register access */ | 104 | /* VIA MMIO register access */ |
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c index c33d068cde19..1ac5941ad237 100644 --- a/drivers/char/drm/via_irq.c +++ b/drivers/char/drm/via_irq.c | |||
@@ -258,12 +258,16 @@ void via_driver_irq_preinstall(drm_device_t * dev) | |||
258 | dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE; | 258 | dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE; |
259 | dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING; | 259 | dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING; |
260 | 260 | ||
261 | dev_priv->irq_masks = (dev_priv->pro_group_a) ? | 261 | if (dev_priv->chipset == VIA_PRO_GROUP_A || |
262 | via_pro_group_a_irqs : via_unichrome_irqs; | 262 | dev_priv->chipset == VIA_DX9_0) { |
263 | dev_priv->num_irqs = (dev_priv->pro_group_a) ? | 263 | dev_priv->irq_masks = via_pro_group_a_irqs; |
264 | via_num_pro_group_a : via_num_unichrome; | 264 | dev_priv->num_irqs = via_num_pro_group_a; |
265 | dev_priv->irq_map = (dev_priv->pro_group_a) ? | 265 | dev_priv->irq_map = via_irqmap_pro_group_a; |
266 | via_irqmap_pro_group_a : via_irqmap_unichrome; | 266 | } else { |
267 | dev_priv->irq_masks = via_unichrome_irqs; | ||
268 | dev_priv->num_irqs = via_num_unichrome; | ||
269 | dev_priv->irq_map = via_irqmap_unichrome; | ||
270 | } | ||
267 | 271 | ||
268 | for (i = 0; i < dev_priv->num_irqs; ++i) { | 272 | for (i = 0; i < dev_priv->num_irqs; ++i) { |
269 | atomic_set(&cur_irq->irq_received, 0); | 273 | atomic_set(&cur_irq->irq_received, 0); |
diff --git a/drivers/char/drm/via_map.c b/drivers/char/drm/via_map.c index 782011e0a58d..4e3fc072aa3b 100644 --- a/drivers/char/drm/via_map.c +++ b/drivers/char/drm/via_map.c | |||
@@ -106,8 +106,7 @@ int via_driver_load(drm_device_t *dev, unsigned long chipset) | |||
106 | 106 | ||
107 | dev->dev_private = (void *)dev_priv; | 107 | dev->dev_private = (void *)dev_priv; |
108 | 108 | ||
109 | if (chipset == VIA_PRO_GROUP_A) | 109 | dev_priv->chipset = chipset; |
110 | dev_priv->pro_group_a = 1; | ||
111 | 110 | ||
112 | ret = drm_sman_init(&dev_priv->sman, 2, 12, 8); | 111 | ret = drm_sman_init(&dev_priv->sman, 2, 12, 8); |
113 | if (ret) { | 112 | if (ret) { |
diff --git a/drivers/char/drm/via_verifier.c b/drivers/char/drm/via_verifier.c index 70c897c88766..2e7e08078287 100644 --- a/drivers/char/drm/via_verifier.c +++ b/drivers/char/drm/via_verifier.c | |||
@@ -306,6 +306,7 @@ static __inline__ int finish_current_sequence(drm_via_state_t * cur_seq) | |||
306 | unsigned long lo = ~0, hi = 0, tmp; | 306 | unsigned long lo = ~0, hi = 0, tmp; |
307 | uint32_t *addr, *pitch, *height, tex; | 307 | uint32_t *addr, *pitch, *height, tex; |
308 | unsigned i; | 308 | unsigned i; |
309 | int npot; | ||
309 | 310 | ||
310 | if (end > 9) | 311 | if (end > 9) |
311 | end = 9; | 312 | end = 9; |
@@ -316,12 +317,15 @@ static __inline__ int finish_current_sequence(drm_via_state_t * cur_seq) | |||
316 | &(cur_seq->t_addr[tex = cur_seq->texture][start]); | 317 | &(cur_seq->t_addr[tex = cur_seq->texture][start]); |
317 | pitch = &(cur_seq->pitch[tex][start]); | 318 | pitch = &(cur_seq->pitch[tex][start]); |
318 | height = &(cur_seq->height[tex][start]); | 319 | height = &(cur_seq->height[tex][start]); |
319 | 320 | npot = cur_seq->tex_npot[tex]; | |
320 | for (i = start; i <= end; ++i) { | 321 | for (i = start; i <= end; ++i) { |
321 | tmp = *addr++; | 322 | tmp = *addr++; |
322 | if (tmp < lo) | 323 | if (tmp < lo) |
323 | lo = tmp; | 324 | lo = tmp; |
324 | tmp += (*height++ << *pitch++); | 325 | if (i == 0 && npot) |
326 | tmp += (*height++ * *pitch++); | ||
327 | else | ||
328 | tmp += (*height++ << *pitch++); | ||
325 | if (tmp > hi) | 329 | if (tmp > hi) |
326 | hi = tmp; | 330 | hi = tmp; |
327 | } | 331 | } |
@@ -443,13 +447,21 @@ investigate_hazard(uint32_t cmd, hazard_t hz, drm_via_state_t * cur_seq) | |||
443 | return 0; | 447 | return 0; |
444 | case check_texture_addr3: | 448 | case check_texture_addr3: |
445 | cur_seq->unfinished = tex_address; | 449 | cur_seq->unfinished = tex_address; |
446 | tmp = ((cmd >> 24) - 0x2B); | 450 | tmp = ((cmd >> 24) - HC_SubA_HTXnL0Pit); |
447 | cur_seq->pitch[cur_seq->texture][tmp] = | 451 | if (tmp == 0 && |
448 | (cmd & 0x00F00000) >> 20; | 452 | (cmd & HC_HTXnEnPit_MASK)) { |
449 | if (!tmp && (cmd & 0x000FFFFF)) { | 453 | cur_seq->pitch[cur_seq->texture][tmp] = |
450 | DRM_ERROR | 454 | (cmd & HC_HTXnLnPit_MASK); |
451 | ("Unimplemented texture level 0 pitch mode.\n"); | 455 | cur_seq->tex_npot[cur_seq->texture] = 1; |
452 | return 2; | 456 | } else { |
457 | cur_seq->pitch[cur_seq->texture][tmp] = | ||
458 | (cmd & HC_HTXnLnPitE_MASK) >> HC_HTXnLnPitE_SHIFT; | ||
459 | cur_seq->tex_npot[cur_seq->texture] = 0; | ||
460 | if (cmd & 0x000FFFFF) { | ||
461 | DRM_ERROR | ||
462 | ("Unimplemented texture level 0 pitch mode.\n"); | ||
463 | return 2; | ||
464 | } | ||
453 | } | 465 | } |
454 | return 0; | 466 | return 0; |
455 | case check_texture_addr4: | 467 | case check_texture_addr4: |
@@ -961,7 +973,13 @@ via_verify_command_stream(const uint32_t * buf, unsigned int size, | |||
961 | uint32_t cmd; | 973 | uint32_t cmd; |
962 | const uint32_t *buf_end = buf + (size >> 2); | 974 | const uint32_t *buf_end = buf + (size >> 2); |
963 | verifier_state_t state = state_command; | 975 | verifier_state_t state = state_command; |
964 | int pro_group_a = dev_priv->pro_group_a; | 976 | int cme_video; |
977 | int supported_3d; | ||
978 | |||
979 | cme_video = (dev_priv->chipset == VIA_PRO_GROUP_A || | ||
980 | dev_priv->chipset == VIA_DX9_0); | ||
981 | |||
982 | supported_3d = dev_priv->chipset != VIA_DX9_0; | ||
965 | 983 | ||
966 | hc_state->dev = dev; | 984 | hc_state->dev = dev; |
967 | hc_state->unfinished = no_sequence; | 985 | hc_state->unfinished = no_sequence; |
@@ -986,17 +1004,21 @@ via_verify_command_stream(const uint32_t * buf, unsigned int size, | |||
986 | state = via_check_vheader6(&buf, buf_end); | 1004 | state = via_check_vheader6(&buf, buf_end); |
987 | break; | 1005 | break; |
988 | case state_command: | 1006 | case state_command: |
989 | if (HALCYON_HEADER2 == (cmd = *buf)) | 1007 | if ((HALCYON_HEADER2 == (cmd = *buf)) && |
1008 | supported_3d) | ||
990 | state = state_header2; | 1009 | state = state_header2; |
991 | else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) | 1010 | else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) |
992 | state = state_header1; | 1011 | state = state_header1; |
993 | else if (pro_group_a | 1012 | else if (cme_video |
994 | && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5) | 1013 | && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5) |
995 | state = state_vheader5; | 1014 | state = state_vheader5; |
996 | else if (pro_group_a | 1015 | else if (cme_video |
997 | && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6) | 1016 | && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6) |
998 | state = state_vheader6; | 1017 | state = state_vheader6; |
999 | else { | 1018 | else if ((cmd == HALCYON_HEADER2) && !supported_3d) { |
1019 | DRM_ERROR("Accelerated 3D is not supported on this chipset yet.\n"); | ||
1020 | state = state_error; | ||
1021 | } else { | ||
1000 | DRM_ERROR | 1022 | DRM_ERROR |
1001 | ("Invalid / Unimplemented DMA HEADER command. 0x%x\n", | 1023 | ("Invalid / Unimplemented DMA HEADER command. 0x%x\n", |
1002 | cmd); | 1024 | cmd); |
diff --git a/drivers/char/drm/via_verifier.h b/drivers/char/drm/via_verifier.h index 256590fcc22a..b77f59df0278 100644 --- a/drivers/char/drm/via_verifier.h +++ b/drivers/char/drm/via_verifier.h | |||
@@ -43,6 +43,7 @@ typedef struct { | |||
43 | uint32_t tex_level_lo[2]; | 43 | uint32_t tex_level_lo[2]; |
44 | uint32_t tex_level_hi[2]; | 44 | uint32_t tex_level_hi[2]; |
45 | uint32_t tex_palette_size[2]; | 45 | uint32_t tex_palette_size[2]; |
46 | uint32_t tex_npot[2]; | ||
46 | drm_via_sequence_t unfinished; | 47 | drm_via_sequence_t unfinished; |
47 | int agp_texture; | 48 | int agp_texture; |
48 | int multitex; | 49 | int multitex; |
diff --git a/drivers/char/ds1302.c b/drivers/char/ds1302.c index bcdb107aa967..fada6ddefbae 100644 --- a/drivers/char/ds1302.c +++ b/drivers/char/ds1302.c | |||
@@ -120,7 +120,6 @@ get_rtc_time(struct rtc_time *rtc_tm) | |||
120 | unsigned long flags; | 120 | unsigned long flags; |
121 | 121 | ||
122 | local_irq_save(flags); | 122 | local_irq_save(flags); |
123 | local_irq_disable(); | ||
124 | 123 | ||
125 | rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS); | 124 | rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS); |
126 | rtc_tm->tm_min = CMOS_READ(RTC_MINUTES); | 125 | rtc_tm->tm_min = CMOS_READ(RTC_MINUTES); |
@@ -219,7 +218,6 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
219 | BIN_TO_BCD(yrs); | 218 | BIN_TO_BCD(yrs); |
220 | 219 | ||
221 | local_irq_save(flags); | 220 | local_irq_save(flags); |
222 | local_irq_disable(); | ||
223 | CMOS_WRITE(yrs, RTC_YEAR); | 221 | CMOS_WRITE(yrs, RTC_YEAR); |
224 | CMOS_WRITE(mon, RTC_MONTH); | 222 | CMOS_WRITE(mon, RTC_MONTH); |
225 | CMOS_WRITE(day, RTC_DAY_OF_MONTH); | 223 | CMOS_WRITE(day, RTC_DAY_OF_MONTH); |
diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c index d4005e94fe5f..d8dbdb916232 100644 --- a/drivers/char/dtlk.c +++ b/drivers/char/dtlk.c | |||
@@ -72,6 +72,7 @@ | |||
72 | #define TRACE_RET ((void) 0) | 72 | #define TRACE_RET ((void) 0) |
73 | #endif /* TRACING */ | 73 | #endif /* TRACING */ |
74 | 74 | ||
75 | static void dtlk_timer_tick(unsigned long data); | ||
75 | 76 | ||
76 | static int dtlk_major; | 77 | static int dtlk_major; |
77 | static int dtlk_port_lpc; | 78 | static int dtlk_port_lpc; |
@@ -81,7 +82,7 @@ static int dtlk_has_indexing; | |||
81 | static unsigned int dtlk_portlist[] = | 82 | static unsigned int dtlk_portlist[] = |
82 | {0x25e, 0x29e, 0x2de, 0x31e, 0x35e, 0x39e, 0}; | 83 | {0x25e, 0x29e, 0x2de, 0x31e, 0x35e, 0x39e, 0}; |
83 | static wait_queue_head_t dtlk_process_list; | 84 | static wait_queue_head_t dtlk_process_list; |
84 | static struct timer_list dtlk_timer; | 85 | static DEFINE_TIMER(dtlk_timer, dtlk_timer_tick, 0, 0); |
85 | 86 | ||
86 | /* prototypes for file_operations struct */ | 87 | /* prototypes for file_operations struct */ |
87 | static ssize_t dtlk_read(struct file *, char __user *, | 88 | static ssize_t dtlk_read(struct file *, char __user *, |
@@ -117,7 +118,6 @@ static char dtlk_write_tts(char); | |||
117 | /* | 118 | /* |
118 | static void dtlk_handle_error(char, char, unsigned int); | 119 | static void dtlk_handle_error(char, char, unsigned int); |
119 | */ | 120 | */ |
120 | static void dtlk_timer_tick(unsigned long data); | ||
121 | 121 | ||
122 | static ssize_t dtlk_read(struct file *file, char __user *buf, | 122 | static ssize_t dtlk_read(struct file *file, char __user *buf, |
123 | size_t count, loff_t * ppos) | 123 | size_t count, loff_t * ppos) |
@@ -318,7 +318,7 @@ static int dtlk_release(struct inode *inode, struct file *file) | |||
318 | } | 318 | } |
319 | TRACE_RET; | 319 | TRACE_RET; |
320 | 320 | ||
321 | del_timer(&dtlk_timer); | 321 | del_timer_sync(&dtlk_timer); |
322 | 322 | ||
323 | return 0; | 323 | return 0; |
324 | } | 324 | } |
@@ -336,8 +336,6 @@ static int __init dtlk_init(void) | |||
336 | if (dtlk_dev_probe() == 0) | 336 | if (dtlk_dev_probe() == 0) |
337 | printk(", MAJOR %d\n", dtlk_major); | 337 | printk(", MAJOR %d\n", dtlk_major); |
338 | 338 | ||
339 | init_timer(&dtlk_timer); | ||
340 | dtlk_timer.function = dtlk_timer_tick; | ||
341 | init_waitqueue_head(&dtlk_process_list); | 339 | init_waitqueue_head(&dtlk_process_list); |
342 | 340 | ||
343 | return 0; | 341 | return 0; |
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index a0f822c9d74d..88fc24fc4392 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
@@ -844,7 +844,6 @@ static void pc_flush_buffer(struct tty_struct *tty) | |||
844 | fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0); | 844 | fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0); |
845 | memoff(ch); | 845 | memoff(ch); |
846 | spin_unlock_irqrestore(&epca_lock, flags); | 846 | spin_unlock_irqrestore(&epca_lock, flags); |
847 | wake_up_interruptible(&tty->write_wait); | ||
848 | tty_wakeup(tty); | 847 | tty_wakeup(tty); |
849 | } /* End pc_flush_buffer */ | 848 | } /* End pc_flush_buffer */ |
850 | 849 | ||
@@ -1795,7 +1794,6 @@ static void doevent(int crd) | |||
1795 | { /* Begin if LOWWAIT */ | 1794 | { /* Begin if LOWWAIT */ |
1796 | ch->statusflags &= ~LOWWAIT; | 1795 | ch->statusflags &= ~LOWWAIT; |
1797 | tty_wakeup(tty); | 1796 | tty_wakeup(tty); |
1798 | wake_up_interruptible(&tty->write_wait); | ||
1799 | } /* End if LOWWAIT */ | 1797 | } /* End if LOWWAIT */ |
1800 | } else if (event & EMPTYTX_IND) { /* Begin EMPTYTX_IND */ | 1798 | } else if (event & EMPTYTX_IND) { /* Begin EMPTYTX_IND */ |
1801 | /* This event is generated by setup_empty_event */ | 1799 | /* This event is generated by setup_empty_event */ |
@@ -1803,7 +1801,6 @@ static void doevent(int crd) | |||
1803 | if (ch->statusflags & EMPTYWAIT) { /* Begin if EMPTYWAIT */ | 1801 | if (ch->statusflags & EMPTYWAIT) { /* Begin if EMPTYWAIT */ |
1804 | ch->statusflags &= ~EMPTYWAIT; | 1802 | ch->statusflags &= ~EMPTYWAIT; |
1805 | tty_wakeup(tty); | 1803 | tty_wakeup(tty); |
1806 | wake_up_interruptible(&tty->write_wait); | ||
1807 | } /* End if EMPTYWAIT */ | 1804 | } /* End if EMPTYWAIT */ |
1808 | } /* End EMPTYTX_IND */ | 1805 | } /* End EMPTYTX_IND */ |
1809 | } /* End if valid tty */ | 1806 | } /* End if valid tty */ |
diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c index 43ff59816511..2398e864c28d 100644 --- a/drivers/char/generic_nvram.c +++ b/drivers/char/generic_nvram.c | |||
@@ -117,7 +117,7 @@ static int nvram_ioctl(struct inode *inode, struct file *file, | |||
117 | return 0; | 117 | return 0; |
118 | } | 118 | } |
119 | 119 | ||
120 | struct file_operations nvram_fops = { | 120 | const struct file_operations nvram_fops = { |
121 | .owner = THIS_MODULE, | 121 | .owner = THIS_MODULE, |
122 | .llseek = nvram_llseek, | 122 | .llseek = nvram_llseek, |
123 | .read = read_nvram, | 123 | .read = read_nvram, |
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index e769811e7417..337bbcdcf13d 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c | |||
@@ -382,7 +382,6 @@ void gs_flush_buffer(struct tty_struct *tty) | |||
382 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; | 382 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; |
383 | spin_unlock_irqrestore (&port->driver_lock, flags); | 383 | spin_unlock_irqrestore (&port->driver_lock, flags); |
384 | 384 | ||
385 | wake_up_interruptible(&tty->write_wait); | ||
386 | tty_wakeup(tty); | 385 | tty_wakeup(tty); |
387 | func_exit (); | 386 | func_exit (); |
388 | } | 387 | } |
diff --git a/drivers/char/hvc_beat.c b/drivers/char/hvc_beat.c new file mode 100644 index 000000000000..6f019f19be71 --- /dev/null +++ b/drivers/char/hvc_beat.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * Beat hypervisor console driver | ||
3 | * | ||
4 | * (C) Copyright 2006 TOSHIBA CORPORATION | ||
5 | * | ||
6 | * This code is based on drivers/char/hvc_rtas.c: | ||
7 | * (C) Copyright IBM Corporation 2001-2005 | ||
8 | * (C) Copyright Red Hat, Inc. 2005 | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
23 | */ | ||
24 | |||
25 | #include <linux/module.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/err.h> | ||
28 | #include <linux/string.h> | ||
29 | #include <linux/console.h> | ||
30 | #include <asm/prom.h> | ||
31 | #include <asm/hvconsole.h> | ||
32 | #include <asm/firmware.h> | ||
33 | |||
34 | #include "hvc_console.h" | ||
35 | |||
36 | extern int64_t beat_get_term_char(uint64_t, uint64_t *, uint64_t *, uint64_t *); | ||
37 | extern int64_t beat_put_term_char(uint64_t, uint64_t, uint64_t, uint64_t); | ||
38 | |||
39 | struct hvc_struct *hvc_beat_dev = NULL; | ||
40 | |||
41 | /* bug: only one queue is available regardless of vtermno */ | ||
42 | static int hvc_beat_get_chars(uint32_t vtermno, char *buf, int cnt) | ||
43 | { | ||
44 | static unsigned char q[sizeof(unsigned long) * 2] | ||
45 | __attribute__((aligned(sizeof(unsigned long)))); | ||
46 | static int qlen = 0; | ||
47 | unsigned long got; | ||
48 | |||
49 | again: | ||
50 | if (qlen) { | ||
51 | if (qlen > cnt) { | ||
52 | memcpy(buf, q, cnt); | ||
53 | qlen -= cnt; | ||
54 | memmove(q + cnt, q, qlen); | ||
55 | return cnt; | ||
56 | } else { /* qlen <= cnt */ | ||
57 | int r; | ||
58 | |||
59 | memcpy(buf, q, qlen); | ||
60 | r = qlen; | ||
61 | qlen = 0; | ||
62 | return r; | ||
63 | } | ||
64 | } | ||
65 | if (beat_get_term_char(vtermno, &got, | ||
66 | ((unsigned long *)q), ((unsigned long *)q) + 1) == 0) { | ||
67 | qlen = got; | ||
68 | goto again; | ||
69 | } | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int hvc_beat_put_chars(uint32_t vtermno, const char *buf, int cnt) | ||
74 | { | ||
75 | unsigned long kb[2]; | ||
76 | int rest, nlen; | ||
77 | |||
78 | for (rest = cnt; rest > 0; rest -= nlen) { | ||
79 | nlen = (rest > 16) ? 16 : rest; | ||
80 | memcpy(kb, buf, nlen); | ||
81 | beat_put_term_char(vtermno, rest, kb[0], kb[1]); | ||
82 | rest -= nlen; | ||
83 | } | ||
84 | return cnt; | ||
85 | } | ||
86 | |||
87 | static struct hv_ops hvc_beat_get_put_ops = { | ||
88 | .get_chars = hvc_beat_get_chars, | ||
89 | .put_chars = hvc_beat_put_chars, | ||
90 | }; | ||
91 | |||
92 | static int hvc_beat_useit = 1; | ||
93 | |||
94 | static int hvc_beat_config(char *p) | ||
95 | { | ||
96 | hvc_beat_useit = simple_strtoul(p, NULL, 0); | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static int hvc_beat_console_init(void) | ||
101 | { | ||
102 | if (hvc_beat_useit && machine_is_compatible("Beat")) { | ||
103 | hvc_instantiate(0, 0, &hvc_beat_get_put_ops); | ||
104 | } | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | /* temp */ | ||
109 | static int hvc_beat_init(void) | ||
110 | { | ||
111 | struct hvc_struct *hp; | ||
112 | |||
113 | if (!firmware_has_feature(FW_FEATURE_BEAT)) | ||
114 | return -ENODEV; | ||
115 | |||
116 | hp = hvc_alloc(0, NO_IRQ, &hvc_beat_get_put_ops, 16); | ||
117 | if (IS_ERR(hp)) | ||
118 | return PTR_ERR(hp); | ||
119 | hvc_beat_dev = hp; | ||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static void __exit hvc_beat_exit(void) | ||
124 | { | ||
125 | if (hvc_beat_dev) | ||
126 | hvc_remove(hvc_beat_dev); | ||
127 | } | ||
128 | |||
129 | module_init(hvc_beat_init); | ||
130 | module_exit(hvc_beat_exit); | ||
131 | |||
132 | __setup("hvc_beat=", hvc_beat_config); | ||
133 | |||
134 | console_initcall(hvc_beat_console_init); | ||
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index f22e78e3c70f..cc1046e6ee02 100644 --- a/drivers/char/hw_random/intel-rng.c +++ b/drivers/char/hw_random/intel-rng.c | |||
@@ -96,49 +96,49 @@ | |||
96 | */ | 96 | */ |
97 | static const struct pci_device_id pci_tbl[] = { | 97 | static const struct pci_device_id pci_tbl[] = { |
98 | /* AA | 98 | /* AA |
99 | { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ | 99 | { PCI_DEVICE(0x8086, 0x2418) }, */ |
100 | { 0x8086, 0x2410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* AA */ | 100 | { PCI_DEVICE(0x8086, 0x2410) }, /* AA */ |
101 | /* AB | 101 | /* AB |
102 | { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ | 102 | { PCI_DEVICE(0x8086, 0x2428) }, */ |
103 | { 0x8086, 0x2420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* AB */ | 103 | { PCI_DEVICE(0x8086, 0x2420) }, /* AB */ |
104 | /* ?? | 104 | /* ?? |
105 | { 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ | 105 | { PCI_DEVICE(0x8086, 0x2430) }, */ |
106 | /* BAM, CAM, DBM, FBM, GxM | 106 | /* BAM, CAM, DBM, FBM, GxM |
107 | { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ | 107 | { PCI_DEVICE(0x8086, 0x2448) }, */ |
108 | { 0x8086, 0x244c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* BAM */ | 108 | { PCI_DEVICE(0x8086, 0x244c) }, /* BAM */ |
109 | { 0x8086, 0x248c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CAM */ | 109 | { PCI_DEVICE(0x8086, 0x248c) }, /* CAM */ |
110 | { 0x8086, 0x24cc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* DBM */ | 110 | { PCI_DEVICE(0x8086, 0x24cc) }, /* DBM */ |
111 | { 0x8086, 0x2641, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* FBM */ | 111 | { PCI_DEVICE(0x8086, 0x2641) }, /* FBM */ |
112 | { 0x8086, 0x27b9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* GxM */ | 112 | { PCI_DEVICE(0x8086, 0x27b9) }, /* GxM */ |
113 | { 0x8086, 0x27bd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* GxM DH */ | 113 | { PCI_DEVICE(0x8086, 0x27bd) }, /* GxM DH */ |
114 | /* BA, CA, DB, Ex, 6300, Fx, 631x/632x, Gx | 114 | /* BA, CA, DB, Ex, 6300, Fx, 631x/632x, Gx |
115 | { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ | 115 | { PCI_DEVICE(0x8086, 0x244e) }, */ |
116 | { 0x8086, 0x2440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* BA */ | 116 | { PCI_DEVICE(0x8086, 0x2440) }, /* BA */ |
117 | { 0x8086, 0x2480, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CA */ | 117 | { PCI_DEVICE(0x8086, 0x2480) }, /* CA */ |
118 | { 0x8086, 0x24c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* DB */ | 118 | { PCI_DEVICE(0x8086, 0x24c0) }, /* DB */ |
119 | { 0x8086, 0x24d0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Ex */ | 119 | { PCI_DEVICE(0x8086, 0x24d0) }, /* Ex */ |
120 | { 0x8086, 0x25a1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 6300 */ | 120 | { PCI_DEVICE(0x8086, 0x25a1) }, /* 6300 */ |
121 | { 0x8086, 0x2640, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Fx */ | 121 | { PCI_DEVICE(0x8086, 0x2640) }, /* Fx */ |
122 | { 0x8086, 0x2670, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ | 122 | { PCI_DEVICE(0x8086, 0x2670) }, /* 631x/632x */ |
123 | { 0x8086, 0x2671, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ | 123 | { PCI_DEVICE(0x8086, 0x2671) }, /* 631x/632x */ |
124 | { 0x8086, 0x2672, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ | 124 | { PCI_DEVICE(0x8086, 0x2672) }, /* 631x/632x */ |
125 | { 0x8086, 0x2673, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ | 125 | { PCI_DEVICE(0x8086, 0x2673) }, /* 631x/632x */ |
126 | { 0x8086, 0x2674, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ | 126 | { PCI_DEVICE(0x8086, 0x2674) }, /* 631x/632x */ |
127 | { 0x8086, 0x2675, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ | 127 | { PCI_DEVICE(0x8086, 0x2675) }, /* 631x/632x */ |
128 | { 0x8086, 0x2676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ | 128 | { PCI_DEVICE(0x8086, 0x2676) }, /* 631x/632x */ |
129 | { 0x8086, 0x2677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ | 129 | { PCI_DEVICE(0x8086, 0x2677) }, /* 631x/632x */ |
130 | { 0x8086, 0x2678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ | 130 | { PCI_DEVICE(0x8086, 0x2678) }, /* 631x/632x */ |
131 | { 0x8086, 0x2679, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ | 131 | { PCI_DEVICE(0x8086, 0x2679) }, /* 631x/632x */ |
132 | { 0x8086, 0x267a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ | 132 | { PCI_DEVICE(0x8086, 0x267a) }, /* 631x/632x */ |
133 | { 0x8086, 0x267b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ | 133 | { PCI_DEVICE(0x8086, 0x267b) }, /* 631x/632x */ |
134 | { 0x8086, 0x267c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ | 134 | { PCI_DEVICE(0x8086, 0x267c) }, /* 631x/632x */ |
135 | { 0x8086, 0x267d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ | 135 | { PCI_DEVICE(0x8086, 0x267d) }, /* 631x/632x */ |
136 | { 0x8086, 0x267e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ | 136 | { PCI_DEVICE(0x8086, 0x267e) }, /* 631x/632x */ |
137 | { 0x8086, 0x267f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ | 137 | { PCI_DEVICE(0x8086, 0x267f) }, /* 631x/632x */ |
138 | { 0x8086, 0x27b8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Gx */ | 138 | { PCI_DEVICE(0x8086, 0x27b8) }, /* Gx */ |
139 | /* E | 139 | /* E |
140 | { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ | 140 | { PCI_DEVICE(0x8086, 0x245e) }, */ |
141 | { 0x8086, 0x2450, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* E */ | 141 | { PCI_DEVICE(0x8086, 0x2450) }, /* E */ |
142 | { 0, }, /* terminate list */ | 142 | { 0, }, /* terminate list */ |
143 | }; | 143 | }; |
144 | MODULE_DEVICE_TABLE(pci, pci_tbl); | 144 | MODULE_DEVICE_TABLE(pci, pci_tbl); |
diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c index 78045767ec33..f86fa0c55d36 100644 --- a/drivers/char/ip2/i2lib.c +++ b/drivers/char/ip2/i2lib.c | |||
@@ -80,7 +80,7 @@ static int i2RetryFlushOutput(i2ChanStrPtr); | |||
80 | // Not a documented part of the library routines (careful...) but the Diagnostic | 80 | // Not a documented part of the library routines (careful...) but the Diagnostic |
81 | // i2diag.c finds them useful to help the throughput in certain limited | 81 | // i2diag.c finds them useful to help the throughput in certain limited |
82 | // single-threaded operations. | 82 | // single-threaded operations. |
83 | static void iiSendPendingMail(i2eBordStrPtr); | 83 | static inline void iiSendPendingMail(i2eBordStrPtr); |
84 | static void serviceOutgoingFifo(i2eBordStrPtr); | 84 | static void serviceOutgoingFifo(i2eBordStrPtr); |
85 | 85 | ||
86 | // Functions defined in ip2.c as part of interrupt handling | 86 | // Functions defined in ip2.c as part of interrupt handling |
@@ -150,6 +150,13 @@ i2Validate ( i2ChanStrPtr pCh ) | |||
150 | == (CHANNEL_MAGIC | CHANNEL_SUPPORT)); | 150 | == (CHANNEL_MAGIC | CHANNEL_SUPPORT)); |
151 | } | 151 | } |
152 | 152 | ||
153 | static void iiSendPendingMail_t(unsigned long data) | ||
154 | { | ||
155 | i2eBordStrPtr pB = (i2eBordStrPtr)data; | ||
156 | |||
157 | iiSendPendingMail(pB); | ||
158 | } | ||
159 | |||
153 | //****************************************************************************** | 160 | //****************************************************************************** |
154 | // Function: iiSendPendingMail(pB) | 161 | // Function: iiSendPendingMail(pB) |
155 | // Parameters: Pointer to a board structure | 162 | // Parameters: Pointer to a board structure |
@@ -184,12 +191,9 @@ iiSendPendingMail(i2eBordStrPtr pB) | |||
184 | /\/\|=mhw=|\/\/ */ | 191 | /\/\|=mhw=|\/\/ */ |
185 | 192 | ||
186 | if( ++pB->SendPendingRetry < 16 ) { | 193 | if( ++pB->SendPendingRetry < 16 ) { |
187 | 194 | setup_timer(&pB->SendPendingTimer, | |
188 | init_timer( &(pB->SendPendingTimer) ); | 195 | iiSendPendingMail_t, (unsigned long)pB); |
189 | pB->SendPendingTimer.expires = jiffies + 1; | 196 | mod_timer(&pB->SendPendingTimer, jiffies + 1); |
190 | pB->SendPendingTimer.function = (void*)(unsigned long)iiSendPendingMail; | ||
191 | pB->SendPendingTimer.data = (unsigned long)pB; | ||
192 | add_timer( &(pB->SendPendingTimer) ); | ||
193 | } else { | 197 | } else { |
194 | printk( KERN_ERR "IP2: iiSendPendingMail unable to queue outbound mail\n" ); | 198 | printk( KERN_ERR "IP2: iiSendPendingMail unable to queue outbound mail\n" ); |
195 | } | 199 | } |
@@ -1265,8 +1269,10 @@ i2RetryFlushOutput(i2ChanStrPtr pCh) | |||
1265 | // soon as all the data is completely sent. | 1269 | // soon as all the data is completely sent. |
1266 | //****************************************************************************** | 1270 | //****************************************************************************** |
1267 | static void | 1271 | static void |
1268 | i2DrainWakeup(i2ChanStrPtr pCh) | 1272 | i2DrainWakeup(unsigned long d) |
1269 | { | 1273 | { |
1274 | i2ChanStrPtr pCh = (i2ChanStrPtr)d; | ||
1275 | |||
1270 | ip2trace (CHANN, ITRC_DRAIN, 10, 1, pCh->BookmarkTimer.expires ); | 1276 | ip2trace (CHANN, ITRC_DRAIN, 10, 1, pCh->BookmarkTimer.expires ); |
1271 | 1277 | ||
1272 | pCh->BookmarkTimer.expires = 0; | 1278 | pCh->BookmarkTimer.expires = 0; |
@@ -1292,14 +1298,12 @@ i2DrainOutput(i2ChanStrPtr pCh, int timeout) | |||
1292 | } | 1298 | } |
1293 | if ((timeout > 0) && (pCh->BookmarkTimer.expires == 0 )) { | 1299 | if ((timeout > 0) && (pCh->BookmarkTimer.expires == 0 )) { |
1294 | // One per customer (channel) | 1300 | // One per customer (channel) |
1295 | init_timer( &(pCh->BookmarkTimer) ); | 1301 | setup_timer(&pCh->BookmarkTimer, i2DrainWakeup, |
1296 | pCh->BookmarkTimer.expires = jiffies + timeout; | 1302 | (unsigned long)pCh); |
1297 | pCh->BookmarkTimer.function = (void*)(unsigned long)i2DrainWakeup; | ||
1298 | pCh->BookmarkTimer.data = (unsigned long)pCh; | ||
1299 | 1303 | ||
1300 | ip2trace (CHANN, ITRC_DRAIN, 1, 1, pCh->BookmarkTimer.expires ); | 1304 | ip2trace (CHANN, ITRC_DRAIN, 1, 1, pCh->BookmarkTimer.expires ); |
1301 | 1305 | ||
1302 | add_timer( &(pCh->BookmarkTimer) ); | 1306 | mod_timer(&pCh->BookmarkTimer, jiffies + timeout); |
1303 | } | 1307 | } |
1304 | 1308 | ||
1305 | i2QueueCommands( PTYPE_INLINE, pCh, -1, 1, CMD_BMARK_REQ ); | 1309 | i2QueueCommands( PTYPE_INLINE, pCh, -1, 1, CMD_BMARK_REQ ); |
@@ -1373,15 +1377,7 @@ ip2_owake( PTTY tp) | |||
1373 | ip2trace (CHANN, ITRC_SICMD, 10, 2, tp->flags, | 1377 | ip2trace (CHANN, ITRC_SICMD, 10, 2, tp->flags, |
1374 | (1 << TTY_DO_WRITE_WAKEUP) ); | 1378 | (1 << TTY_DO_WRITE_WAKEUP) ); |
1375 | 1379 | ||
1376 | wake_up_interruptible ( &tp->write_wait ); | 1380 | tty_wakeup(tp); |
1377 | if ( ( tp->flags & (1 << TTY_DO_WRITE_WAKEUP) ) | ||
1378 | && tp->ldisc.write_wakeup ) | ||
1379 | { | ||
1380 | (tp->ldisc.write_wakeup) ( tp ); | ||
1381 | |||
1382 | ip2trace (CHANN, ITRC_SICMD, 11, 0 ); | ||
1383 | |||
1384 | } | ||
1385 | } | 1381 | } |
1386 | 1382 | ||
1387 | static inline void | 1383 | static inline void |
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 7c70310a49b5..83c7258d3580 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c | |||
@@ -1271,8 +1271,8 @@ static void do_input(struct work_struct *work) | |||
1271 | // code duplicated from n_tty (ldisc) | 1271 | // code duplicated from n_tty (ldisc) |
1272 | static inline void isig(int sig, struct tty_struct *tty, int flush) | 1272 | static inline void isig(int sig, struct tty_struct *tty, int flush) |
1273 | { | 1273 | { |
1274 | if (tty->pgrp > 0) | 1274 | if (tty->pgrp) |
1275 | kill_pg(tty->pgrp, sig, 1); | 1275 | kill_pgrp(tty->pgrp, sig, 1); |
1276 | if (flush || !L_NOFLSH(tty)) { | 1276 | if (flush || !L_NOFLSH(tty)) { |
1277 | if ( tty->ldisc.flush_buffer ) | 1277 | if ( tty->ldisc.flush_buffer ) |
1278 | tty->ldisc.flush_buffer(tty); | 1278 | tty->ldisc.flush_buffer(tty); |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 53582b53da95..3aff5e99b674 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -406,13 +406,14 @@ static void clean_up_interface_data(ipmi_smi_t intf) | |||
406 | free_smi_msg_list(&intf->waiting_msgs); | 406 | free_smi_msg_list(&intf->waiting_msgs); |
407 | free_recv_msg_list(&intf->waiting_events); | 407 | free_recv_msg_list(&intf->waiting_events); |
408 | 408 | ||
409 | /* Wholesale remove all the entries from the list in the | 409 | /* |
410 | * interface and wait for RCU to know that none are in use. */ | 410 | * Wholesale remove all the entries from the list in the |
411 | * interface and wait for RCU to know that none are in use. | ||
412 | */ | ||
411 | mutex_lock(&intf->cmd_rcvrs_mutex); | 413 | mutex_lock(&intf->cmd_rcvrs_mutex); |
412 | list_add_rcu(&list, &intf->cmd_rcvrs); | 414 | INIT_LIST_HEAD(&list); |
413 | list_del_rcu(&intf->cmd_rcvrs); | 415 | list_splice_init_rcu(&intf->cmd_rcvrs, &list, synchronize_rcu); |
414 | mutex_unlock(&intf->cmd_rcvrs_mutex); | 416 | mutex_unlock(&intf->cmd_rcvrs_mutex); |
415 | synchronize_rcu(); | ||
416 | 417 | ||
417 | list_for_each_entry_safe(rcvr, rcvr2, &list, link) | 418 | list_for_each_entry_safe(rcvr, rcvr2, &list, link) |
418 | kfree(rcvr); | 419 | kfree(rcvr); |
@@ -451,7 +452,7 @@ int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher) | |||
451 | mutex_lock(&ipmi_interfaces_mutex); | 452 | mutex_lock(&ipmi_interfaces_mutex); |
452 | 453 | ||
453 | /* Build a list of things to deliver. */ | 454 | /* Build a list of things to deliver. */ |
454 | list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { | 455 | list_for_each_entry(intf, &ipmi_interfaces, link) { |
455 | if (intf->intf_num == -1) | 456 | if (intf->intf_num == -1) |
456 | continue; | 457 | continue; |
457 | e = kmalloc(sizeof(*e), GFP_KERNEL); | 458 | e = kmalloc(sizeof(*e), GFP_KERNEL); |
@@ -1886,7 +1887,6 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name, | |||
1886 | kfree(entry); | 1887 | kfree(entry); |
1887 | rv = -ENOMEM; | 1888 | rv = -ENOMEM; |
1888 | } else { | 1889 | } else { |
1889 | file->nlink = 1; | ||
1890 | file->data = data; | 1890 | file->data = data; |
1891 | file->read_proc = read_proc; | 1891 | file->read_proc = read_proc; |
1892 | file->write_proc = write_proc; | 1892 | file->write_proc = write_proc; |
@@ -2760,9 +2760,15 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
2760 | synchronize_rcu(); | 2760 | synchronize_rcu(); |
2761 | kref_put(&intf->refcount, intf_free); | 2761 | kref_put(&intf->refcount, intf_free); |
2762 | } else { | 2762 | } else { |
2763 | /* After this point the interface is legal to use. */ | 2763 | /* |
2764 | * Keep memory order straight for RCU readers. Make | ||
2765 | * sure everything else is committed to memory before | ||
2766 | * setting intf_num to mark the interface valid. | ||
2767 | */ | ||
2768 | smp_wmb(); | ||
2764 | intf->intf_num = i; | 2769 | intf->intf_num = i; |
2765 | mutex_unlock(&ipmi_interfaces_mutex); | 2770 | mutex_unlock(&ipmi_interfaces_mutex); |
2771 | /* After this point the interface is legal to use. */ | ||
2766 | call_smi_watchers(i, intf->si_dev); | 2772 | call_smi_watchers(i, intf->si_dev); |
2767 | mutex_unlock(&smi_watchers_mutex); | 2773 | mutex_unlock(&smi_watchers_mutex); |
2768 | } | 2774 | } |
@@ -3923,6 +3929,14 @@ static void send_panic_events(char *str) | |||
3923 | /* Interface was not ready yet. */ | 3929 | /* Interface was not ready yet. */ |
3924 | continue; | 3930 | continue; |
3925 | 3931 | ||
3932 | /* | ||
3933 | * intf_num is used as an marker to tell if the | ||
3934 | * interface is valid. Thus we need a read barrier to | ||
3935 | * make sure data fetched before checking intf_num | ||
3936 | * won't be used. | ||
3937 | */ | ||
3938 | smp_rmb(); | ||
3939 | |||
3926 | /* First job here is to figure out where to send the | 3940 | /* First job here is to figure out where to send the |
3927 | OEM events. There's no way in IPMI to send OEM | 3941 | OEM events. There's no way in IPMI to send OEM |
3928 | events using an event send command, so we have to | 3942 | events using an event send command, so we have to |
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index f1afd26a509f..a7b33d2f5991 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -1802,7 +1802,7 @@ static __devinit int try_init_acpi(struct SPMITable *spmi) | |||
1802 | return -ENODEV; | 1802 | return -ENODEV; |
1803 | } | 1803 | } |
1804 | 1804 | ||
1805 | if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) | 1805 | if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) |
1806 | addr_space = IPMI_MEM_ADDR_SPACE; | 1806 | addr_space = IPMI_MEM_ADDR_SPACE; |
1807 | else | 1807 | else |
1808 | addr_space = IPMI_IO_ADDR_SPACE; | 1808 | addr_space = IPMI_IO_ADDR_SPACE; |
@@ -1848,19 +1848,19 @@ static __devinit int try_init_acpi(struct SPMITable *spmi) | |||
1848 | info->irq_setup = NULL; | 1848 | info->irq_setup = NULL; |
1849 | } | 1849 | } |
1850 | 1850 | ||
1851 | if (spmi->addr.register_bit_width) { | 1851 | if (spmi->addr.bit_width) { |
1852 | /* A (hopefully) properly formed register bit width. */ | 1852 | /* A (hopefully) properly formed register bit width. */ |
1853 | info->io.regspacing = spmi->addr.register_bit_width / 8; | 1853 | info->io.regspacing = spmi->addr.bit_width / 8; |
1854 | } else { | 1854 | } else { |
1855 | info->io.regspacing = DEFAULT_REGSPACING; | 1855 | info->io.regspacing = DEFAULT_REGSPACING; |
1856 | } | 1856 | } |
1857 | info->io.regsize = info->io.regspacing; | 1857 | info->io.regsize = info->io.regspacing; |
1858 | info->io.regshift = spmi->addr.register_bit_offset; | 1858 | info->io.regshift = spmi->addr.bit_offset; |
1859 | 1859 | ||
1860 | if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { | 1860 | if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { |
1861 | info->io_setup = mem_setup; | 1861 | info->io_setup = mem_setup; |
1862 | info->io.addr_type = IPMI_IO_ADDR_SPACE; | 1862 | info->io.addr_type = IPMI_IO_ADDR_SPACE; |
1863 | } else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) { | 1863 | } else if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_IO) { |
1864 | info->io_setup = port_setup; | 1864 | info->io_setup = port_setup; |
1865 | info->io.addr_type = IPMI_MEM_ADDR_SPACE; | 1865 | info->io.addr_type = IPMI_MEM_ADDR_SPACE; |
1866 | } else { | 1866 | } else { |
@@ -1888,10 +1888,8 @@ static __devinit void acpi_find_bmc(void) | |||
1888 | return; | 1888 | return; |
1889 | 1889 | ||
1890 | for (i = 0; ; i++) { | 1890 | for (i = 0; ; i++) { |
1891 | status = acpi_get_firmware_table("SPMI", i+1, | 1891 | status = acpi_get_table(ACPI_SIG_SPMI, i+1, |
1892 | ACPI_LOGICAL_ADDRESSING, | 1892 | (struct acpi_table_header **)&spmi); |
1893 | (struct acpi_table_header **) | ||
1894 | &spmi); | ||
1895 | if (status != AE_OK) | 1893 | if (status != AE_OK) |
1896 | return; | 1894 | return; |
1897 | 1895 | ||
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 01084abffddf..43ab9edc76f5 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
@@ -183,7 +183,7 @@ static DEFINE_TIMER(tx, isicom_tx, 0, 0); | |||
183 | /* baud index mappings from linux defns to isi */ | 183 | /* baud index mappings from linux defns to isi */ |
184 | 184 | ||
185 | static signed char linuxb_to_isib[] = { | 185 | static signed char linuxb_to_isib[] = { |
186 | -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19 | 186 | -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19, 20, 21 |
187 | }; | 187 | }; |
188 | 188 | ||
189 | struct isi_board { | 189 | struct isi_board { |
@@ -213,8 +213,6 @@ struct isi_port { | |||
213 | struct tty_struct * tty; | 213 | struct tty_struct * tty; |
214 | wait_queue_head_t close_wait; | 214 | wait_queue_head_t close_wait; |
215 | wait_queue_head_t open_wait; | 215 | wait_queue_head_t open_wait; |
216 | struct work_struct hangup_tq; | ||
217 | struct work_struct bh_tqueue; | ||
218 | unsigned char * xmit_buf; | 216 | unsigned char * xmit_buf; |
219 | int xmit_head; | 217 | int xmit_head; |
220 | int xmit_tail; | 218 | int xmit_tail; |
@@ -510,7 +508,7 @@ static void isicom_tx(unsigned long _data) | |||
510 | if (port->xmit_cnt <= 0) | 508 | if (port->xmit_cnt <= 0) |
511 | port->status &= ~ISI_TXOK; | 509 | port->status &= ~ISI_TXOK; |
512 | if (port->xmit_cnt <= WAKEUP_CHARS) | 510 | if (port->xmit_cnt <= WAKEUP_CHARS) |
513 | schedule_work(&port->bh_tqueue); | 511 | tty_wakeup(tty); |
514 | unlock_card(&isi_card[card]); | 512 | unlock_card(&isi_card[card]); |
515 | } | 513 | } |
516 | 514 | ||
@@ -524,21 +522,6 @@ sched_again: | |||
524 | mod_timer(&tx, jiffies + msecs_to_jiffies(10)); | 522 | mod_timer(&tx, jiffies + msecs_to_jiffies(10)); |
525 | } | 523 | } |
526 | 524 | ||
527 | /* Interrupt handlers */ | ||
528 | |||
529 | |||
530 | static void isicom_bottomhalf(struct work_struct *work) | ||
531 | { | ||
532 | struct isi_port *port = container_of(work, struct isi_port, bh_tqueue); | ||
533 | struct tty_struct *tty = port->tty; | ||
534 | |||
535 | if (!tty) | ||
536 | return; | ||
537 | |||
538 | tty_wakeup(tty); | ||
539 | wake_up_interruptible(&tty->write_wait); | ||
540 | } | ||
541 | |||
542 | /* | 525 | /* |
543 | * Main interrupt handler routine | 526 | * Main interrupt handler routine |
544 | */ | 527 | */ |
@@ -557,6 +540,11 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
557 | return IRQ_NONE; | 540 | return IRQ_NONE; |
558 | 541 | ||
559 | base = card->base; | 542 | base = card->base; |
543 | |||
544 | /* did the card interrupt us? */ | ||
545 | if (!(inw(base + 0x0e) & 0x02)) | ||
546 | return IRQ_NONE; | ||
547 | |||
560 | spin_lock(&card->card_lock); | 548 | spin_lock(&card->card_lock); |
561 | 549 | ||
562 | /* | 550 | /* |
@@ -581,6 +569,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
581 | port = card->ports + channel; | 569 | port = card->ports + channel; |
582 | if (!(port->flags & ASYNC_INITIALIZED)) { | 570 | if (!(port->flags & ASYNC_INITIALIZED)) { |
583 | outw(0x0000, base+0x04); /* enable interrupts */ | 571 | outw(0x0000, base+0x04); /* enable interrupts */ |
572 | spin_unlock(&card->card_lock); | ||
584 | return IRQ_HANDLED; | 573 | return IRQ_HANDLED; |
585 | } | 574 | } |
586 | 575 | ||
@@ -609,7 +598,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
609 | pr_dbg("interrupt: DCD->low.\n" | 598 | pr_dbg("interrupt: DCD->low.\n" |
610 | ); | 599 | ); |
611 | port->status &= ~ISI_DCD; | 600 | port->status &= ~ISI_DCD; |
612 | schedule_work(&port->hangup_tq); | 601 | tty_hangup(tty); |
613 | } | 602 | } |
614 | } else if (header & ISI_DCD) { | 603 | } else if (header & ISI_DCD) { |
615 | /* Carrier has been detected */ | 604 | /* Carrier has been detected */ |
@@ -631,7 +620,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
631 | /* start tx ing */ | 620 | /* start tx ing */ |
632 | port->status |= (ISI_TXOK | 621 | port->status |= (ISI_TXOK |
633 | | ISI_CTS); | 622 | | ISI_CTS); |
634 | schedule_work(&port->bh_tqueue); | 623 | tty_wakeup(tty); |
635 | } | 624 | } |
636 | } else if (!(header & ISI_CTS)) { | 625 | } else if (!(header & ISI_CTS)) { |
637 | port->tty->hw_stopped = 1; | 626 | port->tty->hw_stopped = 1; |
@@ -695,6 +684,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
695 | tty_flip_buffer_push(tty); | 684 | tty_flip_buffer_push(tty); |
696 | } | 685 | } |
697 | outw(0x0000, base+0x04); /* enable interrupts */ | 686 | outw(0x0000, base+0x04); /* enable interrupts */ |
687 | spin_unlock(&card->card_lock); | ||
698 | 688 | ||
699 | return IRQ_HANDLED; | 689 | return IRQ_HANDLED; |
700 | } | 690 | } |
@@ -720,7 +710,8 @@ static void isicom_config_port(struct isi_port *port) | |||
720 | * respectively. | 710 | * respectively. |
721 | */ | 711 | */ |
722 | 712 | ||
723 | if (baud < 1 || baud > 2) | 713 | /* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */ |
714 | if (baud < 1 || baud > 4) | ||
724 | port->tty->termios->c_cflag &= ~CBAUDEX; | 715 | port->tty->termios->c_cflag &= ~CBAUDEX; |
725 | else | 716 | else |
726 | baud += 15; | 717 | baud += 15; |
@@ -736,6 +727,10 @@ static void isicom_config_port(struct isi_port *port) | |||
736 | baud++; /* 57.6 Kbps */ | 727 | baud++; /* 57.6 Kbps */ |
737 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) | 728 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) |
738 | baud +=2; /* 115 Kbps */ | 729 | baud +=2; /* 115 Kbps */ |
730 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) | ||
731 | baud += 3; /* 230 kbps*/ | ||
732 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) | ||
733 | baud += 4; /* 460 kbps*/ | ||
739 | } | 734 | } |
740 | if (linuxb_to_isib[baud] == -1) { | 735 | if (linuxb_to_isib[baud] == -1) { |
741 | /* hang up */ | 736 | /* hang up */ |
@@ -1460,17 +1455,6 @@ static void isicom_start(struct tty_struct *tty) | |||
1460 | port->status |= ISI_TXOK; | 1455 | port->status |= ISI_TXOK; |
1461 | } | 1456 | } |
1462 | 1457 | ||
1463 | /* hangup et all */ | ||
1464 | static void do_isicom_hangup(struct work_struct *work) | ||
1465 | { | ||
1466 | struct isi_port *port = container_of(work, struct isi_port, hangup_tq); | ||
1467 | struct tty_struct *tty; | ||
1468 | |||
1469 | tty = port->tty; | ||
1470 | if (tty) | ||
1471 | tty_hangup(tty); | ||
1472 | } | ||
1473 | |||
1474 | static void isicom_hangup(struct tty_struct *tty) | 1458 | static void isicom_hangup(struct tty_struct *tty) |
1475 | { | 1459 | { |
1476 | struct isi_port *port = tty->driver_data; | 1460 | struct isi_port *port = tty->driver_data; |
@@ -1503,7 +1487,6 @@ static void isicom_flush_buffer(struct tty_struct *tty) | |||
1503 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; | 1487 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; |
1504 | spin_unlock_irqrestore(&card->card_lock, flags); | 1488 | spin_unlock_irqrestore(&card->card_lock, flags); |
1505 | 1489 | ||
1506 | wake_up_interruptible(&tty->write_wait); | ||
1507 | tty_wakeup(tty); | 1490 | tty_wakeup(tty); |
1508 | } | 1491 | } |
1509 | 1492 | ||
@@ -1536,7 +1519,7 @@ static int __devinit reset_card(struct pci_dev *pdev, | |||
1536 | { | 1519 | { |
1537 | struct isi_board *board = pci_get_drvdata(pdev); | 1520 | struct isi_board *board = pci_get_drvdata(pdev); |
1538 | unsigned long base = board->base; | 1521 | unsigned long base = board->base; |
1539 | unsigned int portcount = 0; | 1522 | unsigned int sig, portcount = 0; |
1540 | int retval = 0; | 1523 | int retval = 0; |
1541 | 1524 | ||
1542 | dev_dbg(&pdev->dev, "ISILoad:Resetting Card%d at 0x%lx\n", card + 1, | 1525 | dev_dbg(&pdev->dev, "ISILoad:Resetting Card%d at 0x%lx\n", card + 1, |
@@ -1544,27 +1527,35 @@ static int __devinit reset_card(struct pci_dev *pdev, | |||
1544 | 1527 | ||
1545 | inw(base + 0x8); | 1528 | inw(base + 0x8); |
1546 | 1529 | ||
1547 | mdelay(10); | 1530 | msleep(10); |
1548 | 1531 | ||
1549 | outw(0, base + 0x8); /* Reset */ | 1532 | outw(0, base + 0x8); /* Reset */ |
1550 | 1533 | ||
1551 | msleep(3000); | 1534 | msleep(1000); |
1552 | 1535 | ||
1553 | *signature = inw(base + 0x4) & 0xff; | 1536 | sig = inw(base + 0x4) & 0xff; |
1537 | |||
1538 | if (sig != 0xa5 && sig != 0xbb && sig != 0xcc && sig != 0xdd && | ||
1539 | sig != 0xee) { | ||
1540 | dev_warn(&pdev->dev, "ISILoad:Card%u reset failure (Possible " | ||
1541 | "bad I/O Port Address 0x%lx).\n", card + 1, base); | ||
1542 | dev_dbg(&pdev->dev, "Sig=0x%x\n", sig); | ||
1543 | retval = -EIO; | ||
1544 | goto end; | ||
1545 | } | ||
1546 | |||
1547 | msleep(10); | ||
1554 | 1548 | ||
1555 | portcount = inw(base + 0x2); | 1549 | portcount = inw(base + 0x2); |
1556 | if (!(inw(base + 0xe) & 0x1) || ((portcount != 0) && | 1550 | if (!inw(base + 0xe) & 0x1 || (portcount != 0 && portcount != 4 && |
1557 | (portcount != 4) && (portcount != 8))) { | 1551 | portcount != 8 && portcount != 16)) { |
1558 | dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n", | 1552 | dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure.", |
1559 | inw(base + 0x2), inw(base + 0xe)); | 1553 | card + 1); |
1560 | dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure " | ||
1561 | "(Possible bad I/O Port Address 0x%lx).\n", | ||
1562 | card + 1, base); | ||
1563 | retval = -EIO; | 1554 | retval = -EIO; |
1564 | goto end; | 1555 | goto end; |
1565 | } | 1556 | } |
1566 | 1557 | ||
1567 | switch (*signature) { | 1558 | switch (sig) { |
1568 | case 0xa5: | 1559 | case 0xa5: |
1569 | case 0xbb: | 1560 | case 0xbb: |
1570 | case 0xdd: | 1561 | case 0xdd: |
@@ -1572,16 +1563,13 @@ static int __devinit reset_card(struct pci_dev *pdev, | |||
1572 | board->shift_count = 12; | 1563 | board->shift_count = 12; |
1573 | break; | 1564 | break; |
1574 | case 0xcc: | 1565 | case 0xcc: |
1566 | case 0xee: | ||
1575 | board->port_count = 16; | 1567 | board->port_count = 16; |
1576 | board->shift_count = 11; | 1568 | board->shift_count = 11; |
1577 | break; | 1569 | break; |
1578 | default: | ||
1579 | dev_warn(&pdev->dev, "ISILoad:Card%d reset failure (Possible " | ||
1580 | "bad I/O Port Address 0x%lx).\n", card + 1, base); | ||
1581 | dev_dbg(&pdev->dev, "Sig=0x%lx\n", signature); | ||
1582 | retval = -EIO; | ||
1583 | } | 1570 | } |
1584 | dev_info(&pdev->dev, "-Done\n"); | 1571 | dev_info(&pdev->dev, "-Done\n"); |
1572 | *signature = sig; | ||
1585 | 1573 | ||
1586 | end: | 1574 | end: |
1587 | return retval; | 1575 | return retval; |
@@ -1757,7 +1745,7 @@ end: | |||
1757 | /* | 1745 | /* |
1758 | * Insmod can set static symbols so keep these static | 1746 | * Insmod can set static symbols so keep these static |
1759 | */ | 1747 | */ |
1760 | static int card; | 1748 | static unsigned int card_count; |
1761 | 1749 | ||
1762 | static int __devinit isicom_probe(struct pci_dev *pdev, | 1750 | static int __devinit isicom_probe(struct pci_dev *pdev, |
1763 | const struct pci_device_id *ent) | 1751 | const struct pci_device_id *ent) |
@@ -1767,7 +1755,7 @@ static int __devinit isicom_probe(struct pci_dev *pdev, | |||
1767 | u8 pciirq; | 1755 | u8 pciirq; |
1768 | struct isi_board *board = NULL; | 1756 | struct isi_board *board = NULL; |
1769 | 1757 | ||
1770 | if (card >= BOARD_COUNT) | 1758 | if (card_count >= BOARD_COUNT) |
1771 | goto err; | 1759 | goto err; |
1772 | 1760 | ||
1773 | ioaddr = pci_resource_start(pdev, 3); | 1761 | ioaddr = pci_resource_start(pdev, 3); |
@@ -1785,7 +1773,7 @@ static int __devinit isicom_probe(struct pci_dev *pdev, | |||
1785 | board->index = index; | 1773 | board->index = index; |
1786 | board->base = ioaddr; | 1774 | board->base = ioaddr; |
1787 | board->irq = pciirq; | 1775 | board->irq = pciirq; |
1788 | card++; | 1776 | card_count++; |
1789 | 1777 | ||
1790 | pci_set_drvdata(pdev, board); | 1778 | pci_set_drvdata(pdev, board); |
1791 | 1779 | ||
@@ -1795,7 +1783,7 @@ static int __devinit isicom_probe(struct pci_dev *pdev, | |||
1795 | "will be disabled.\n", board->base, board->base + 15, | 1783 | "will be disabled.\n", board->base, board->base + 15, |
1796 | index + 1); | 1784 | index + 1); |
1797 | retval = -EBUSY; | 1785 | retval = -EBUSY; |
1798 | goto err; | 1786 | goto errdec; |
1799 | } | 1787 | } |
1800 | 1788 | ||
1801 | retval = request_irq(board->irq, isicom_interrupt, | 1789 | retval = request_irq(board->irq, isicom_interrupt, |
@@ -1824,8 +1812,10 @@ errunri: | |||
1824 | free_irq(board->irq, board); | 1812 | free_irq(board->irq, board); |
1825 | errunrr: | 1813 | errunrr: |
1826 | pci_release_region(pdev, 3); | 1814 | pci_release_region(pdev, 3); |
1827 | err: | 1815 | errdec: |
1828 | board->base = 0; | 1816 | board->base = 0; |
1817 | card_count--; | ||
1818 | err: | ||
1829 | return retval; | 1819 | return retval; |
1830 | } | 1820 | } |
1831 | 1821 | ||
@@ -1839,6 +1829,8 @@ static void __devexit isicom_remove(struct pci_dev *pdev) | |||
1839 | 1829 | ||
1840 | free_irq(board->irq, board); | 1830 | free_irq(board->irq, board); |
1841 | pci_release_region(pdev, 3); | 1831 | pci_release_region(pdev, 3); |
1832 | board->base = 0; | ||
1833 | card_count--; | ||
1842 | } | 1834 | } |
1843 | 1835 | ||
1844 | static int __init isicom_init(void) | 1836 | static int __init isicom_init(void) |
@@ -1846,8 +1838,6 @@ static int __init isicom_init(void) | |||
1846 | int retval, idx, channel; | 1838 | int retval, idx, channel; |
1847 | struct isi_port *port; | 1839 | struct isi_port *port; |
1848 | 1840 | ||
1849 | card = 0; | ||
1850 | |||
1851 | for(idx = 0; idx < BOARD_COUNT; idx++) { | 1841 | for(idx = 0; idx < BOARD_COUNT; idx++) { |
1852 | port = &isi_ports[idx * 16]; | 1842 | port = &isi_ports[idx * 16]; |
1853 | isi_card[idx].ports = port; | 1843 | isi_card[idx].ports = port; |
@@ -1858,8 +1848,6 @@ static int __init isicom_init(void) | |||
1858 | port->channel = channel; | 1848 | port->channel = channel; |
1859 | port->close_delay = 50 * HZ/100; | 1849 | port->close_delay = 50 * HZ/100; |
1860 | port->closing_wait = 3000 * HZ/100; | 1850 | port->closing_wait = 3000 * HZ/100; |
1861 | INIT_WORK(&port->hangup_tq, do_isicom_hangup); | ||
1862 | INIT_WORK(&port->bh_tqueue, isicom_bottomhalf); | ||
1863 | port->status = 0; | 1851 | port->status = 0; |
1864 | init_waitqueue_head(&port->open_wait); | 1852 | init_waitqueue_head(&port->open_wait); |
1865 | init_waitqueue_head(&port->close_wait); | 1853 | init_waitqueue_head(&port->close_wait); |
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 68645d351873..7b279d1de4a2 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
@@ -2424,7 +2424,6 @@ static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp) | |||
2424 | if (tty != NULL) { | 2424 | if (tty != NULL) { |
2425 | tty_wakeup(tty); | 2425 | tty_wakeup(tty); |
2426 | EBRDENABLE(brdp); | 2426 | EBRDENABLE(brdp); |
2427 | wake_up_interruptible(&tty->write_wait); | ||
2428 | } | 2427 | } |
2429 | } | 2428 | } |
2430 | 2429 | ||
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 7a6c1c0b7a95..c654a3e0c697 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c | |||
@@ -595,15 +595,9 @@ static void fn_spawn_con(struct vc_data *vc) | |||
595 | 595 | ||
596 | static void fn_SAK(struct vc_data *vc) | 596 | static void fn_SAK(struct vc_data *vc) |
597 | { | 597 | { |
598 | struct tty_struct *tty = vc->vc_tty; | 598 | struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work; |
599 | 599 | PREPARE_WORK(SAK_work, vc_SAK); | |
600 | /* | 600 | schedule_work(SAK_work); |
601 | * SAK should also work in all raw modes and reset | ||
602 | * them properly. | ||
603 | */ | ||
604 | if (tty) | ||
605 | do_SAK(tty); | ||
606 | reset_vc(vc); | ||
607 | } | 601 | } |
608 | 602 | ||
609 | static void fn_null(struct vc_data *vc) | 603 | static void fn_null(struct vc_data *vc) |
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c index 0afb7ba999cf..57f9115a456c 100644 --- a/drivers/char/mbcs.c +++ b/drivers/char/mbcs.c | |||
@@ -46,7 +46,7 @@ LIST_HEAD(soft_list); | |||
46 | /* | 46 | /* |
47 | * file operations | 47 | * file operations |
48 | */ | 48 | */ |
49 | struct file_operations mbcs_ops = { | 49 | const struct file_operations mbcs_ops = { |
50 | .open = mbcs_open, | 50 | .open = mbcs_open, |
51 | .llseek = mbcs_sram_llseek, | 51 | .llseek = mbcs_sram_llseek, |
52 | .read = mbcs_sram_read, | 52 | .read = mbcs_sram_read, |
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index f391a24a1b44..7dbaee8d9402 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c | |||
@@ -11,15 +11,6 @@ | |||
11 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
12 | * the Free Software Foundation; either version 2 of the License, or | 12 | * the Free Software Foundation; either version 2 of the License, or |
13 | * (at your option) any later version. | 13 | * (at your option) any later version. |
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | */ | 14 | */ |
24 | 15 | ||
25 | /* | 16 | /* |
@@ -55,36 +46,20 @@ | |||
55 | #include <asm/io.h> | 46 | #include <asm/io.h> |
56 | #include <asm/uaccess.h> | 47 | #include <asm/uaccess.h> |
57 | 48 | ||
58 | #define MOXA_VERSION "5.1k" | 49 | #define MOXA_VERSION "5.1k" |
59 | 50 | ||
60 | #define MOXAMAJOR 172 | 51 | #define MOXAMAJOR 172 |
61 | #define MOXACUMAJOR 173 | 52 | #define MOXACUMAJOR 173 |
62 | 53 | ||
63 | #define put_to_user(arg1, arg2) put_user(arg1, (unsigned long *)arg2) | 54 | #define MAX_BOARDS 4 /* Don't change this value */ |
64 | #define get_from_user(arg1, arg2) get_user(arg1, (unsigned int *)arg2) | ||
65 | |||
66 | #define MAX_BOARDS 4 /* Don't change this value */ | ||
67 | #define MAX_PORTS_PER_BOARD 32 /* Don't change this value */ | 55 | #define MAX_PORTS_PER_BOARD 32 /* Don't change this value */ |
68 | #define MAX_PORTS 128 /* Don't change this value */ | 56 | #define MAX_PORTS (MAX_BOARDS * MAX_PORTS_PER_BOARD) |
69 | 57 | ||
70 | /* | 58 | /* |
71 | * Define the Moxa PCI vendor and device IDs. | 59 | * Define the Moxa PCI vendor and device IDs. |
72 | */ | 60 | */ |
73 | #define MOXA_BUS_TYPE_ISA 0 | 61 | #define MOXA_BUS_TYPE_ISA 0 |
74 | #define MOXA_BUS_TYPE_PCI 1 | 62 | #define MOXA_BUS_TYPE_PCI 1 |
75 | |||
76 | #ifndef PCI_VENDOR_ID_MOXA | ||
77 | #define PCI_VENDOR_ID_MOXA 0x1393 | ||
78 | #endif | ||
79 | #ifndef PCI_DEVICE_ID_CP204J | ||
80 | #define PCI_DEVICE_ID_CP204J 0x2040 | ||
81 | #endif | ||
82 | #ifndef PCI_DEVICE_ID_C218 | ||
83 | #define PCI_DEVICE_ID_C218 0x2180 | ||
84 | #endif | ||
85 | #ifndef PCI_DEVICE_ID_C320 | ||
86 | #define PCI_DEVICE_ID_C320 0x3200 | ||
87 | #endif | ||
88 | 63 | ||
89 | enum { | 64 | enum { |
90 | MOXA_BOARD_C218_PCI = 1, | 65 | MOXA_BOARD_C218_PCI = 1, |
@@ -105,47 +80,56 @@ static char *moxa_brdname[] = | |||
105 | 80 | ||
106 | #ifdef CONFIG_PCI | 81 | #ifdef CONFIG_PCI |
107 | static struct pci_device_id moxa_pcibrds[] = { | 82 | static struct pci_device_id moxa_pcibrds[] = { |
108 | { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C218, PCI_ANY_ID, PCI_ANY_ID, | 83 | { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C218), |
109 | 0, 0, MOXA_BOARD_C218_PCI }, | 84 | .driver_data = MOXA_BOARD_C218_PCI }, |
110 | { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C320, PCI_ANY_ID, PCI_ANY_ID, | 85 | { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C320), |
111 | 0, 0, MOXA_BOARD_C320_PCI }, | 86 | .driver_data = MOXA_BOARD_C320_PCI }, |
112 | { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CP204J, PCI_ANY_ID, PCI_ANY_ID, | 87 | { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP204J), |
113 | 0, 0, MOXA_BOARD_CP204J }, | 88 | .driver_data = MOXA_BOARD_CP204J }, |
114 | { 0 } | 89 | { 0 } |
115 | }; | 90 | }; |
116 | MODULE_DEVICE_TABLE(pci, moxa_pcibrds); | 91 | MODULE_DEVICE_TABLE(pci, moxa_pcibrds); |
117 | #endif /* CONFIG_PCI */ | 92 | #endif /* CONFIG_PCI */ |
118 | 93 | ||
119 | typedef struct _moxa_isa_board_conf { | 94 | struct moxa_isa_board_conf { |
120 | int boardType; | 95 | int boardType; |
121 | int numPorts; | 96 | int numPorts; |
122 | unsigned long baseAddr; | 97 | unsigned long baseAddr; |
123 | } moxa_isa_board_conf; | 98 | }; |
124 | 99 | ||
125 | static moxa_isa_board_conf moxa_isa_boards[] = | 100 | static struct moxa_isa_board_conf moxa_isa_boards[] = |
126 | { | 101 | { |
127 | /* {MOXA_BOARD_C218_ISA,8,0xDC000}, */ | 102 | /* {MOXA_BOARD_C218_ISA,8,0xDC000}, */ |
128 | }; | 103 | }; |
129 | 104 | ||
130 | typedef struct _moxa_pci_devinfo { | 105 | static struct moxa_board_conf { |
131 | ushort busNum; | ||
132 | ushort devNum; | ||
133 | struct pci_dev *pdev; | ||
134 | } moxa_pci_devinfo; | ||
135 | |||
136 | typedef struct _moxa_board_conf { | ||
137 | int boardType; | 106 | int boardType; |
138 | int numPorts; | 107 | int numPorts; |
139 | unsigned long baseAddr; | 108 | unsigned long baseAddr; |
140 | int busType; | 109 | int busType; |
141 | moxa_pci_devinfo pciInfo; | ||
142 | } moxa_board_conf; | ||
143 | 110 | ||
144 | static moxa_board_conf moxa_boards[MAX_BOARDS]; | 111 | int loadstat; |
145 | static void __iomem *moxaBaseAddr[MAX_BOARDS]; | 112 | |
146 | static int loadstat[MAX_BOARDS]; | 113 | void __iomem *basemem; |
114 | void __iomem *intNdx; | ||
115 | void __iomem *intPend; | ||
116 | void __iomem *intTable; | ||
117 | } moxa_boards[MAX_BOARDS]; | ||
118 | |||
119 | struct mxser_mstatus { | ||
120 | tcflag_t cflag; | ||
121 | int cts; | ||
122 | int dsr; | ||
123 | int ri; | ||
124 | int dcd; | ||
125 | }; | ||
126 | |||
127 | struct moxaq_str { | ||
128 | int inq; | ||
129 | int outq; | ||
130 | }; | ||
147 | 131 | ||
148 | struct moxa_str { | 132 | struct moxa_port { |
149 | int type; | 133 | int type; |
150 | int port; | 134 | int port; |
151 | int close_delay; | 135 | int close_delay; |
@@ -159,18 +143,18 @@ struct moxa_str { | |||
159 | int cflag; | 143 | int cflag; |
160 | wait_queue_head_t open_wait; | 144 | wait_queue_head_t open_wait; |
161 | wait_queue_head_t close_wait; | 145 | wait_queue_head_t close_wait; |
162 | struct work_struct tqueue; | ||
163 | }; | ||
164 | 146 | ||
165 | struct mxser_mstatus { | 147 | struct timer_list emptyTimer; |
166 | tcflag_t cflag; | ||
167 | int cts; | ||
168 | int dsr; | ||
169 | int ri; | ||
170 | int dcd; | ||
171 | }; | ||
172 | 148 | ||
173 | static struct mxser_mstatus GMStatus[MAX_PORTS]; | 149 | char chkPort; |
150 | char lineCtrl; | ||
151 | void __iomem *tableAddr; | ||
152 | long curBaud; | ||
153 | char DCDState; | ||
154 | char lowChkFlag; | ||
155 | |||
156 | ushort breakCnt; | ||
157 | }; | ||
174 | 158 | ||
175 | /* statusflags */ | 159 | /* statusflags */ |
176 | #define TXSTOPPED 0x1 | 160 | #define TXSTOPPED 0x1 |
@@ -178,25 +162,17 @@ static struct mxser_mstatus GMStatus[MAX_PORTS]; | |||
178 | #define EMPTYWAIT 0x4 | 162 | #define EMPTYWAIT 0x4 |
179 | #define THROTTLE 0x8 | 163 | #define THROTTLE 0x8 |
180 | 164 | ||
181 | /* event */ | ||
182 | #define MOXA_EVENT_HANGUP 1 | ||
183 | |||
184 | #define SERIAL_DO_RESTART | 165 | #define SERIAL_DO_RESTART |
185 | 166 | ||
186 | |||
187 | #define SERIAL_TYPE_NORMAL 1 | ||
188 | |||
189 | #define WAKEUP_CHARS 256 | 167 | #define WAKEUP_CHARS 256 |
190 | 168 | ||
191 | #define PORTNO(x) ((x)->index) | ||
192 | |||
193 | static int verbose = 0; | 169 | static int verbose = 0; |
194 | static int ttymajor = MOXAMAJOR; | 170 | static int ttymajor = MOXAMAJOR; |
195 | /* Variables for insmod */ | 171 | /* Variables for insmod */ |
196 | #ifdef MODULE | 172 | #ifdef MODULE |
197 | static int baseaddr[] = {0, 0, 0, 0}; | 173 | static int baseaddr[4]; |
198 | static int type[] = {0, 0, 0, 0}; | 174 | static int type[4]; |
199 | static int numports[] = {0, 0, 0, 0}; | 175 | static int numports[4]; |
200 | #endif | 176 | #endif |
201 | 177 | ||
202 | MODULE_AUTHOR("William Chen"); | 178 | MODULE_AUTHOR("William Chen"); |
@@ -210,19 +186,9 @@ module_param_array(numports, int, NULL, 0); | |||
210 | module_param(ttymajor, int, 0); | 186 | module_param(ttymajor, int, 0); |
211 | module_param(verbose, bool, 0644); | 187 | module_param(verbose, bool, 0644); |
212 | 188 | ||
213 | static struct tty_driver *moxaDriver; | ||
214 | static struct moxa_str moxaChannels[MAX_PORTS]; | ||
215 | static unsigned char *moxaXmitBuff; | ||
216 | static int moxaTimer_on; | ||
217 | static struct timer_list moxaTimer; | ||
218 | static int moxaEmptyTimer_on[MAX_PORTS]; | ||
219 | static struct timer_list moxaEmptyTimer[MAX_PORTS]; | ||
220 | static struct semaphore moxaBuffSem; | ||
221 | |||
222 | /* | 189 | /* |
223 | * static functions: | 190 | * static functions: |
224 | */ | 191 | */ |
225 | static void do_moxa_softint(struct work_struct *); | ||
226 | static int moxa_open(struct tty_struct *, struct file *); | 192 | static int moxa_open(struct tty_struct *, struct file *); |
227 | static void moxa_close(struct tty_struct *, struct file *); | 193 | static void moxa_close(struct tty_struct *, struct file *); |
228 | static int moxa_write(struct tty_struct *, const unsigned char *, int); | 194 | static int moxa_write(struct tty_struct *, const unsigned char *, int); |
@@ -244,11 +210,11 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file, | |||
244 | static void moxa_poll(unsigned long); | 210 | static void moxa_poll(unsigned long); |
245 | static void set_tty_param(struct tty_struct *); | 211 | static void set_tty_param(struct tty_struct *); |
246 | static int block_till_ready(struct tty_struct *, struct file *, | 212 | static int block_till_ready(struct tty_struct *, struct file *, |
247 | struct moxa_str *); | 213 | struct moxa_port *); |
248 | static void setup_empty_event(struct tty_struct *); | 214 | static void setup_empty_event(struct tty_struct *); |
249 | static void check_xmit_empty(unsigned long); | 215 | static void check_xmit_empty(unsigned long); |
250 | static void shut_down(struct moxa_str *); | 216 | static void shut_down(struct moxa_port *); |
251 | static void receive_data(struct moxa_str *); | 217 | static void receive_data(struct moxa_port *); |
252 | /* | 218 | /* |
253 | * moxa board interface functions: | 219 | * moxa board interface functions: |
254 | */ | 220 | */ |
@@ -278,8 +244,8 @@ static void MoxaPortTxDisable(int); | |||
278 | static void MoxaPortTxEnable(int); | 244 | static void MoxaPortTxEnable(int); |
279 | static int MoxaPortResetBrkCnt(int); | 245 | static int MoxaPortResetBrkCnt(int); |
280 | static void MoxaPortSendBreak(int, int); | 246 | static void MoxaPortSendBreak(int, int); |
281 | static int moxa_get_serial_info(struct moxa_str *, struct serial_struct __user *); | 247 | static int moxa_get_serial_info(struct moxa_port *, struct serial_struct __user *); |
282 | static int moxa_set_serial_info(struct moxa_str *, struct serial_struct __user *); | 248 | static int moxa_set_serial_info(struct moxa_port *, struct serial_struct __user *); |
283 | static void MoxaSetFifo(int port, int enable); | 249 | static void MoxaSetFifo(int port, int enable); |
284 | 250 | ||
285 | static const struct tty_operations moxa_ops = { | 251 | static const struct tty_operations moxa_ops = { |
@@ -302,12 +268,41 @@ static const struct tty_operations moxa_ops = { | |||
302 | .tiocmset = moxa_tiocmset, | 268 | .tiocmset = moxa_tiocmset, |
303 | }; | 269 | }; |
304 | 270 | ||
271 | static struct tty_driver *moxaDriver; | ||
272 | static struct moxa_port moxa_ports[MAX_PORTS]; | ||
273 | static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0); | ||
305 | static DEFINE_SPINLOCK(moxa_lock); | 274 | static DEFINE_SPINLOCK(moxa_lock); |
306 | 275 | ||
307 | #ifdef CONFIG_PCI | 276 | #ifdef CONFIG_PCI |
308 | static int moxa_get_PCI_conf(struct pci_dev *p, int board_type, moxa_board_conf * board) | 277 | static int __devinit moxa_pci_probe(struct pci_dev *pdev, |
278 | const struct pci_device_id *ent) | ||
309 | { | 279 | { |
310 | board->baseAddr = pci_resource_start (p, 2); | 280 | struct moxa_board_conf *board; |
281 | unsigned int i; | ||
282 | int board_type = ent->driver_data; | ||
283 | int retval; | ||
284 | |||
285 | retval = pci_enable_device(pdev); | ||
286 | if (retval) | ||
287 | goto err; | ||
288 | |||
289 | for (i = 0; i < MAX_BOARDS; i++) | ||
290 | if (moxa_boards[i].basemem == NULL) | ||
291 | break; | ||
292 | |||
293 | retval = -ENODEV; | ||
294 | if (i >= MAX_BOARDS) { | ||
295 | if (verbose) | ||
296 | printk("More than %d MOXA Intellio family boards " | ||
297 | "found. Board is ignored.\n", MAX_BOARDS); | ||
298 | goto err; | ||
299 | } | ||
300 | |||
301 | board = &moxa_boards[i]; | ||
302 | board->basemem = pci_iomap(pdev, 2, 0x4000); | ||
303 | if (board->basemem == NULL) | ||
304 | goto err; | ||
305 | |||
311 | board->boardType = board_type; | 306 | board->boardType = board_type; |
312 | switch (board_type) { | 307 | switch (board_type) { |
313 | case MOXA_BOARD_C218_ISA: | 308 | case MOXA_BOARD_C218_ISA: |
@@ -323,27 +318,40 @@ static int moxa_get_PCI_conf(struct pci_dev *p, int board_type, moxa_board_conf | |||
323 | break; | 318 | break; |
324 | } | 319 | } |
325 | board->busType = MOXA_BUS_TYPE_PCI; | 320 | board->busType = MOXA_BUS_TYPE_PCI; |
326 | board->pciInfo.busNum = p->bus->number; | 321 | |
327 | board->pciInfo.devNum = p->devfn >> 3; | 322 | pci_set_drvdata(pdev, board); |
328 | board->pciInfo.pdev = p; | ||
329 | /* don't lose the reference in the next pci_get_device iteration */ | ||
330 | pci_dev_get(p); | ||
331 | 323 | ||
332 | return (0); | 324 | return (0); |
325 | err: | ||
326 | return retval; | ||
333 | } | 327 | } |
328 | |||
329 | static void __devexit moxa_pci_remove(struct pci_dev *pdev) | ||
330 | { | ||
331 | struct moxa_board_conf *brd = pci_get_drvdata(pdev); | ||
332 | |||
333 | pci_iounmap(pdev, brd->basemem); | ||
334 | brd->basemem = NULL; | ||
335 | } | ||
336 | |||
337 | static struct pci_driver moxa_pci_driver = { | ||
338 | .name = "moxa", | ||
339 | .id_table = moxa_pcibrds, | ||
340 | .probe = moxa_pci_probe, | ||
341 | .remove = __devexit_p(moxa_pci_remove) | ||
342 | }; | ||
334 | #endif /* CONFIG_PCI */ | 343 | #endif /* CONFIG_PCI */ |
335 | 344 | ||
336 | static int __init moxa_init(void) | 345 | static int __init moxa_init(void) |
337 | { | 346 | { |
338 | int i, numBoards; | 347 | int i, numBoards, retval = 0; |
339 | struct moxa_str *ch; | 348 | struct moxa_port *ch; |
340 | 349 | ||
341 | printk(KERN_INFO "MOXA Intellio family driver version %s\n", MOXA_VERSION); | 350 | printk(KERN_INFO "MOXA Intellio family driver version %s\n", MOXA_VERSION); |
342 | moxaDriver = alloc_tty_driver(MAX_PORTS + 1); | 351 | moxaDriver = alloc_tty_driver(MAX_PORTS + 1); |
343 | if (!moxaDriver) | 352 | if (!moxaDriver) |
344 | return -ENOMEM; | 353 | return -ENOMEM; |
345 | 354 | ||
346 | init_MUTEX(&moxaBuffSem); | ||
347 | moxaDriver->owner = THIS_MODULE; | 355 | moxaDriver->owner = THIS_MODULE; |
348 | moxaDriver->name = "ttyMX"; | 356 | moxaDriver->name = "ttyMX"; |
349 | moxaDriver->major = ttymajor; | 357 | moxaDriver->major = ttymajor; |
@@ -351,40 +359,25 @@ static int __init moxa_init(void) | |||
351 | moxaDriver->type = TTY_DRIVER_TYPE_SERIAL; | 359 | moxaDriver->type = TTY_DRIVER_TYPE_SERIAL; |
352 | moxaDriver->subtype = SERIAL_TYPE_NORMAL; | 360 | moxaDriver->subtype = SERIAL_TYPE_NORMAL; |
353 | moxaDriver->init_termios = tty_std_termios; | 361 | moxaDriver->init_termios = tty_std_termios; |
354 | moxaDriver->init_termios.c_iflag = 0; | ||
355 | moxaDriver->init_termios.c_oflag = 0; | ||
356 | moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; | 362 | moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; |
357 | moxaDriver->init_termios.c_lflag = 0; | ||
358 | moxaDriver->init_termios.c_ispeed = 9600; | 363 | moxaDriver->init_termios.c_ispeed = 9600; |
359 | moxaDriver->init_termios.c_ospeed = 9600; | 364 | moxaDriver->init_termios.c_ospeed = 9600; |
360 | moxaDriver->flags = TTY_DRIVER_REAL_RAW; | 365 | moxaDriver->flags = TTY_DRIVER_REAL_RAW; |
361 | tty_set_operations(moxaDriver, &moxa_ops); | 366 | tty_set_operations(moxaDriver, &moxa_ops); |
362 | 367 | ||
363 | moxaXmitBuff = NULL; | 368 | for (i = 0, ch = moxa_ports; i < MAX_PORTS; i++, ch++) { |
364 | |||
365 | for (i = 0, ch = moxaChannels; i < MAX_PORTS; i++, ch++) { | ||
366 | ch->type = PORT_16550A; | 369 | ch->type = PORT_16550A; |
367 | ch->port = i; | 370 | ch->port = i; |
368 | INIT_WORK(&ch->tqueue, do_moxa_softint); | ||
369 | ch->tty = NULL; | ||
370 | ch->close_delay = 5 * HZ / 10; | 371 | ch->close_delay = 5 * HZ / 10; |
371 | ch->closing_wait = 30 * HZ; | 372 | ch->closing_wait = 30 * HZ; |
372 | ch->count = 0; | ||
373 | ch->blocked_open = 0; | ||
374 | ch->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; | 373 | ch->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; |
375 | init_waitqueue_head(&ch->open_wait); | 374 | init_waitqueue_head(&ch->open_wait); |
376 | init_waitqueue_head(&ch->close_wait); | 375 | init_waitqueue_head(&ch->close_wait); |
377 | } | ||
378 | 376 | ||
379 | for (i = 0; i < MAX_BOARDS; i++) { | 377 | setup_timer(&ch->emptyTimer, check_xmit_empty, |
380 | moxa_boards[i].boardType = 0; | 378 | (unsigned long)ch); |
381 | moxa_boards[i].numPorts = 0; | ||
382 | moxa_boards[i].baseAddr = 0; | ||
383 | moxa_boards[i].busType = 0; | ||
384 | moxa_boards[i].pciInfo.busNum = 0; | ||
385 | moxa_boards[i].pciInfo.devNum = 0; | ||
386 | } | 379 | } |
387 | MoxaDriverInit(); | 380 | |
388 | printk("Tty devices major number = %d\n", ttymajor); | 381 | printk("Tty devices major number = %d\n", ttymajor); |
389 | 382 | ||
390 | if (tty_register_driver(moxaDriver)) { | 383 | if (tty_register_driver(moxaDriver)) { |
@@ -392,18 +385,8 @@ static int __init moxa_init(void) | |||
392 | put_tty_driver(moxaDriver); | 385 | put_tty_driver(moxaDriver); |
393 | return -1; | 386 | return -1; |
394 | } | 387 | } |
395 | for (i = 0; i < MAX_PORTS; i++) { | ||
396 | init_timer(&moxaEmptyTimer[i]); | ||
397 | moxaEmptyTimer[i].function = check_xmit_empty; | ||
398 | moxaEmptyTimer[i].data = (unsigned long) & moxaChannels[i]; | ||
399 | moxaEmptyTimer_on[i] = 0; | ||
400 | } | ||
401 | 388 | ||
402 | init_timer(&moxaTimer); | 389 | mod_timer(&moxaTimer, jiffies + HZ / 50); |
403 | moxaTimer.function = moxa_poll; | ||
404 | moxaTimer.expires = jiffies + (HZ / 50); | ||
405 | moxaTimer_on = 1; | ||
406 | add_timer(&moxaTimer); | ||
407 | 390 | ||
408 | /* Find the boards defined in source code */ | 391 | /* Find the boards defined in source code */ |
409 | numBoards = 0; | 392 | numBoards = 0; |
@@ -451,35 +434,22 @@ static int __init moxa_init(void) | |||
451 | } | 434 | } |
452 | } | 435 | } |
453 | #endif | 436 | #endif |
454 | /* Find PCI boards here */ | 437 | |
455 | #ifdef CONFIG_PCI | 438 | #ifdef CONFIG_PCI |
456 | { | 439 | retval = pci_register_driver(&moxa_pci_driver); |
457 | struct pci_dev *p = NULL; | 440 | if (retval) { |
458 | int n = ARRAY_SIZE(moxa_pcibrds) - 1; | 441 | printk(KERN_ERR "Can't register moxa pci driver!\n"); |
459 | i = 0; | 442 | if (numBoards) |
460 | while (i < n) { | 443 | retval = 0; |
461 | while ((p = pci_get_device(moxa_pcibrds[i].vendor, moxa_pcibrds[i].device, p))!=NULL) | ||
462 | { | ||
463 | if (pci_enable_device(p)) | ||
464 | continue; | ||
465 | if (numBoards >= MAX_BOARDS) { | ||
466 | if (verbose) | ||
467 | printk("More than %d MOXA Intellio family boards found. Board is ignored.", MAX_BOARDS); | ||
468 | } else { | ||
469 | moxa_get_PCI_conf(p, moxa_pcibrds[i].driver_data, | ||
470 | &moxa_boards[numBoards]); | ||
471 | numBoards++; | ||
472 | } | ||
473 | } | ||
474 | i++; | ||
475 | } | ||
476 | } | 444 | } |
477 | #endif | 445 | #endif |
446 | |||
478 | for (i = 0; i < numBoards; i++) { | 447 | for (i = 0; i < numBoards; i++) { |
479 | moxaBaseAddr[i] = ioremap((unsigned long) moxa_boards[i].baseAddr, 0x4000); | 448 | moxa_boards[i].basemem = ioremap(moxa_boards[i].baseAddr, |
449 | 0x4000); | ||
480 | } | 450 | } |
481 | 451 | ||
482 | return (0); | 452 | return retval; |
483 | } | 453 | } |
484 | 454 | ||
485 | static void __exit moxa_exit(void) | 455 | static void __exit moxa_exit(void) |
@@ -489,23 +459,22 @@ static void __exit moxa_exit(void) | |||
489 | if (verbose) | 459 | if (verbose) |
490 | printk("Unloading module moxa ...\n"); | 460 | printk("Unloading module moxa ...\n"); |
491 | 461 | ||
492 | if (moxaTimer_on) | 462 | del_timer_sync(&moxaTimer); |
493 | del_timer(&moxaTimer); | ||
494 | 463 | ||
495 | for (i = 0; i < MAX_PORTS; i++) | 464 | for (i = 0; i < MAX_PORTS; i++) |
496 | if (moxaEmptyTimer_on[i]) | 465 | del_timer_sync(&moxa_ports[i].emptyTimer); |
497 | del_timer(&moxaEmptyTimer[i]); | ||
498 | 466 | ||
499 | if (tty_unregister_driver(moxaDriver)) | 467 | if (tty_unregister_driver(moxaDriver)) |
500 | printk("Couldn't unregister MOXA Intellio family serial driver\n"); | 468 | printk("Couldn't unregister MOXA Intellio family serial driver\n"); |
501 | put_tty_driver(moxaDriver); | 469 | put_tty_driver(moxaDriver); |
502 | 470 | ||
503 | for (i = 0; i < MAX_BOARDS; i++) { | 471 | #ifdef CONFIG_PCI |
504 | if (moxaBaseAddr[i]) | 472 | pci_unregister_driver(&moxa_pci_driver); |
505 | iounmap(moxaBaseAddr[i]); | 473 | #endif |
506 | if (moxa_boards[i].busType == MOXA_BUS_TYPE_PCI) | 474 | |
507 | pci_dev_put(moxa_boards[i].pciInfo.pdev); | 475 | for (i = 0; i < MAX_BOARDS; i++) |
508 | } | 476 | if (moxa_boards[i].basemem) |
477 | iounmap(moxa_boards[i].basemem); | ||
509 | 478 | ||
510 | if (verbose) | 479 | if (verbose) |
511 | printk("Done\n"); | 480 | printk("Done\n"); |
@@ -514,28 +483,13 @@ static void __exit moxa_exit(void) | |||
514 | module_init(moxa_init); | 483 | module_init(moxa_init); |
515 | module_exit(moxa_exit); | 484 | module_exit(moxa_exit); |
516 | 485 | ||
517 | static void do_moxa_softint(struct work_struct *work) | ||
518 | { | ||
519 | struct moxa_str *ch = container_of(work, struct moxa_str, tqueue); | ||
520 | struct tty_struct *tty; | ||
521 | |||
522 | if (ch && (tty = ch->tty)) { | ||
523 | if (test_and_clear_bit(MOXA_EVENT_HANGUP, &ch->event)) { | ||
524 | tty_hangup(tty); /* FIXME: module removal race here - AKPM */ | ||
525 | wake_up_interruptible(&ch->open_wait); | ||
526 | ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE; | ||
527 | } | ||
528 | } | ||
529 | } | ||
530 | |||
531 | static int moxa_open(struct tty_struct *tty, struct file *filp) | 486 | static int moxa_open(struct tty_struct *tty, struct file *filp) |
532 | { | 487 | { |
533 | struct moxa_str *ch; | 488 | struct moxa_port *ch; |
534 | int port; | 489 | int port; |
535 | int retval; | 490 | int retval; |
536 | unsigned long page; | ||
537 | 491 | ||
538 | port = PORTNO(tty); | 492 | port = tty->index; |
539 | if (port == MAX_PORTS) { | 493 | if (port == MAX_PORTS) { |
540 | return (0); | 494 | return (0); |
541 | } | 495 | } |
@@ -543,23 +497,8 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) | |||
543 | tty->driver_data = NULL; | 497 | tty->driver_data = NULL; |
544 | return (-ENODEV); | 498 | return (-ENODEV); |
545 | } | 499 | } |
546 | down(&moxaBuffSem); | ||
547 | if (!moxaXmitBuff) { | ||
548 | page = get_zeroed_page(GFP_KERNEL); | ||
549 | if (!page) { | ||
550 | up(&moxaBuffSem); | ||
551 | return (-ENOMEM); | ||
552 | } | ||
553 | /* This test is guarded by the BuffSem so no longer needed | ||
554 | delete me in 2.5 */ | ||
555 | if (moxaXmitBuff) | ||
556 | free_page(page); | ||
557 | else | ||
558 | moxaXmitBuff = (unsigned char *) page; | ||
559 | } | ||
560 | up(&moxaBuffSem); | ||
561 | 500 | ||
562 | ch = &moxaChannels[port]; | 501 | ch = &moxa_ports[port]; |
563 | ch->count++; | 502 | ch->count++; |
564 | tty->driver_data = ch; | 503 | tty->driver_data = ch; |
565 | ch->tty = tty; | 504 | ch->tty = tty; |
@@ -585,10 +524,10 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) | |||
585 | 524 | ||
586 | static void moxa_close(struct tty_struct *tty, struct file *filp) | 525 | static void moxa_close(struct tty_struct *tty, struct file *filp) |
587 | { | 526 | { |
588 | struct moxa_str *ch; | 527 | struct moxa_port *ch; |
589 | int port; | 528 | int port; |
590 | 529 | ||
591 | port = PORTNO(tty); | 530 | port = tty->index; |
592 | if (port == MAX_PORTS) { | 531 | if (port == MAX_PORTS) { |
593 | return; | 532 | return; |
594 | } | 533 | } |
@@ -605,7 +544,7 @@ static void moxa_close(struct tty_struct *tty, struct file *filp) | |||
605 | if (tty_hung_up_p(filp)) { | 544 | if (tty_hung_up_p(filp)) { |
606 | return; | 545 | return; |
607 | } | 546 | } |
608 | ch = (struct moxa_str *) tty->driver_data; | 547 | ch = (struct moxa_port *) tty->driver_data; |
609 | 548 | ||
610 | if ((tty->count == 1) && (ch->count != 1)) { | 549 | if ((tty->count == 1) && (ch->count != 1)) { |
611 | printk("moxa_close: bad serial port count; tty->count is 1, " | 550 | printk("moxa_close: bad serial port count; tty->count is 1, " |
@@ -626,8 +565,7 @@ static void moxa_close(struct tty_struct *tty, struct file *filp) | |||
626 | if (ch->asyncflags & ASYNC_INITIALIZED) { | 565 | if (ch->asyncflags & ASYNC_INITIALIZED) { |
627 | setup_empty_event(tty); | 566 | setup_empty_event(tty); |
628 | tty_wait_until_sent(tty, 30 * HZ); /* 30 seconds timeout */ | 567 | tty_wait_until_sent(tty, 30 * HZ); /* 30 seconds timeout */ |
629 | moxaEmptyTimer_on[ch->port] = 0; | 568 | del_timer_sync(&moxa_ports[ch->port].emptyTimer); |
630 | del_timer(&moxaEmptyTimer[ch->port]); | ||
631 | } | 569 | } |
632 | shut_down(ch); | 570 | shut_down(ch); |
633 | MoxaPortFlushData(port, 2); | 571 | MoxaPortFlushData(port, 2); |
@@ -652,11 +590,11 @@ static void moxa_close(struct tty_struct *tty, struct file *filp) | |||
652 | static int moxa_write(struct tty_struct *tty, | 590 | static int moxa_write(struct tty_struct *tty, |
653 | const unsigned char *buf, int count) | 591 | const unsigned char *buf, int count) |
654 | { | 592 | { |
655 | struct moxa_str *ch; | 593 | struct moxa_port *ch; |
656 | int len, port; | 594 | int len, port; |
657 | unsigned long flags; | 595 | unsigned long flags; |
658 | 596 | ||
659 | ch = (struct moxa_str *) tty->driver_data; | 597 | ch = (struct moxa_port *) tty->driver_data; |
660 | if (ch == NULL) | 598 | if (ch == NULL) |
661 | return (0); | 599 | return (0); |
662 | port = ch->port; | 600 | port = ch->port; |
@@ -675,11 +613,11 @@ static int moxa_write(struct tty_struct *tty, | |||
675 | 613 | ||
676 | static int moxa_write_room(struct tty_struct *tty) | 614 | static int moxa_write_room(struct tty_struct *tty) |
677 | { | 615 | { |
678 | struct moxa_str *ch; | 616 | struct moxa_port *ch; |
679 | 617 | ||
680 | if (tty->stopped) | 618 | if (tty->stopped) |
681 | return (0); | 619 | return (0); |
682 | ch = (struct moxa_str *) tty->driver_data; | 620 | ch = (struct moxa_port *) tty->driver_data; |
683 | if (ch == NULL) | 621 | if (ch == NULL) |
684 | return (0); | 622 | return (0); |
685 | return (MoxaPortTxFree(ch->port)); | 623 | return (MoxaPortTxFree(ch->port)); |
@@ -687,7 +625,7 @@ static int moxa_write_room(struct tty_struct *tty) | |||
687 | 625 | ||
688 | static void moxa_flush_buffer(struct tty_struct *tty) | 626 | static void moxa_flush_buffer(struct tty_struct *tty) |
689 | { | 627 | { |
690 | struct moxa_str *ch = (struct moxa_str *) tty->driver_data; | 628 | struct moxa_port *ch = (struct moxa_port *) tty->driver_data; |
691 | 629 | ||
692 | if (ch == NULL) | 630 | if (ch == NULL) |
693 | return; | 631 | return; |
@@ -698,7 +636,7 @@ static void moxa_flush_buffer(struct tty_struct *tty) | |||
698 | static int moxa_chars_in_buffer(struct tty_struct *tty) | 636 | static int moxa_chars_in_buffer(struct tty_struct *tty) |
699 | { | 637 | { |
700 | int chars; | 638 | int chars; |
701 | struct moxa_str *ch = (struct moxa_str *) tty->driver_data; | 639 | struct moxa_port *ch = (struct moxa_port *) tty->driver_data; |
702 | 640 | ||
703 | /* | 641 | /* |
704 | * Sigh...I have to check if driver_data is NULL here, because | 642 | * Sigh...I have to check if driver_data is NULL here, because |
@@ -730,17 +668,16 @@ static void moxa_flush_chars(struct tty_struct *tty) | |||
730 | 668 | ||
731 | static void moxa_put_char(struct tty_struct *tty, unsigned char c) | 669 | static void moxa_put_char(struct tty_struct *tty, unsigned char c) |
732 | { | 670 | { |
733 | struct moxa_str *ch; | 671 | struct moxa_port *ch; |
734 | int port; | 672 | int port; |
735 | unsigned long flags; | 673 | unsigned long flags; |
736 | 674 | ||
737 | ch = (struct moxa_str *) tty->driver_data; | 675 | ch = (struct moxa_port *) tty->driver_data; |
738 | if (ch == NULL) | 676 | if (ch == NULL) |
739 | return; | 677 | return; |
740 | port = ch->port; | 678 | port = ch->port; |
741 | spin_lock_irqsave(&moxa_lock, flags); | 679 | spin_lock_irqsave(&moxa_lock, flags); |
742 | moxaXmitBuff[0] = c; | 680 | MoxaPortWriteData(port, &c, 1); |
743 | MoxaPortWriteData(port, moxaXmitBuff, 1); | ||
744 | spin_unlock_irqrestore(&moxa_lock, flags); | 681 | spin_unlock_irqrestore(&moxa_lock, flags); |
745 | /************************************************ | 682 | /************************************************ |
746 | if ( !(ch->statusflags & LOWWAIT) && (MoxaPortTxFree(port) <= 100) ) | 683 | if ( !(ch->statusflags & LOWWAIT) && (MoxaPortTxFree(port) <= 100) ) |
@@ -750,11 +687,11 @@ static void moxa_put_char(struct tty_struct *tty, unsigned char c) | |||
750 | 687 | ||
751 | static int moxa_tiocmget(struct tty_struct *tty, struct file *file) | 688 | static int moxa_tiocmget(struct tty_struct *tty, struct file *file) |
752 | { | 689 | { |
753 | struct moxa_str *ch = (struct moxa_str *) tty->driver_data; | 690 | struct moxa_port *ch = (struct moxa_port *) tty->driver_data; |
754 | int port; | 691 | int port; |
755 | int flag = 0, dtr, rts; | 692 | int flag = 0, dtr, rts; |
756 | 693 | ||
757 | port = PORTNO(tty); | 694 | port = tty->index; |
758 | if ((port != MAX_PORTS) && (!ch)) | 695 | if ((port != MAX_PORTS) && (!ch)) |
759 | return (-EINVAL); | 696 | return (-EINVAL); |
760 | 697 | ||
@@ -776,11 +713,11 @@ static int moxa_tiocmget(struct tty_struct *tty, struct file *file) | |||
776 | static int moxa_tiocmset(struct tty_struct *tty, struct file *file, | 713 | static int moxa_tiocmset(struct tty_struct *tty, struct file *file, |
777 | unsigned int set, unsigned int clear) | 714 | unsigned int set, unsigned int clear) |
778 | { | 715 | { |
779 | struct moxa_str *ch = (struct moxa_str *) tty->driver_data; | 716 | struct moxa_port *ch = (struct moxa_port *) tty->driver_data; |
780 | int port; | 717 | int port; |
781 | int dtr, rts; | 718 | int dtr, rts; |
782 | 719 | ||
783 | port = PORTNO(tty); | 720 | port = tty->index; |
784 | if ((port != MAX_PORTS) && (!ch)) | 721 | if ((port != MAX_PORTS) && (!ch)) |
785 | return (-EINVAL); | 722 | return (-EINVAL); |
786 | 723 | ||
@@ -800,12 +737,12 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file, | |||
800 | static int moxa_ioctl(struct tty_struct *tty, struct file *file, | 737 | static int moxa_ioctl(struct tty_struct *tty, struct file *file, |
801 | unsigned int cmd, unsigned long arg) | 738 | unsigned int cmd, unsigned long arg) |
802 | { | 739 | { |
803 | struct moxa_str *ch = (struct moxa_str *) tty->driver_data; | 740 | struct moxa_port *ch = (struct moxa_port *) tty->driver_data; |
804 | register int port; | 741 | register int port; |
805 | void __user *argp = (void __user *)arg; | 742 | void __user *argp = (void __user *)arg; |
806 | int retval; | 743 | int retval; |
807 | 744 | ||
808 | port = PORTNO(tty); | 745 | port = tty->index; |
809 | if ((port != MAX_PORTS) && (!ch)) | 746 | if ((port != MAX_PORTS) && (!ch)) |
810 | return (-EINVAL); | 747 | return (-EINVAL); |
811 | 748 | ||
@@ -853,14 +790,14 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file, | |||
853 | 790 | ||
854 | static void moxa_throttle(struct tty_struct *tty) | 791 | static void moxa_throttle(struct tty_struct *tty) |
855 | { | 792 | { |
856 | struct moxa_str *ch = (struct moxa_str *) tty->driver_data; | 793 | struct moxa_port *ch = (struct moxa_port *) tty->driver_data; |
857 | 794 | ||
858 | ch->statusflags |= THROTTLE; | 795 | ch->statusflags |= THROTTLE; |
859 | } | 796 | } |
860 | 797 | ||
861 | static void moxa_unthrottle(struct tty_struct *tty) | 798 | static void moxa_unthrottle(struct tty_struct *tty) |
862 | { | 799 | { |
863 | struct moxa_str *ch = (struct moxa_str *) tty->driver_data; | 800 | struct moxa_port *ch = (struct moxa_port *) tty->driver_data; |
864 | 801 | ||
865 | ch->statusflags &= ~THROTTLE; | 802 | ch->statusflags &= ~THROTTLE; |
866 | } | 803 | } |
@@ -868,7 +805,7 @@ static void moxa_unthrottle(struct tty_struct *tty) | |||
868 | static void moxa_set_termios(struct tty_struct *tty, | 805 | static void moxa_set_termios(struct tty_struct *tty, |
869 | struct ktermios *old_termios) | 806 | struct ktermios *old_termios) |
870 | { | 807 | { |
871 | struct moxa_str *ch = (struct moxa_str *) tty->driver_data; | 808 | struct moxa_port *ch = (struct moxa_port *) tty->driver_data; |
872 | 809 | ||
873 | if (ch == NULL) | 810 | if (ch == NULL) |
874 | return; | 811 | return; |
@@ -880,7 +817,7 @@ static void moxa_set_termios(struct tty_struct *tty, | |||
880 | 817 | ||
881 | static void moxa_stop(struct tty_struct *tty) | 818 | static void moxa_stop(struct tty_struct *tty) |
882 | { | 819 | { |
883 | struct moxa_str *ch = (struct moxa_str *) tty->driver_data; | 820 | struct moxa_port *ch = (struct moxa_port *) tty->driver_data; |
884 | 821 | ||
885 | if (ch == NULL) | 822 | if (ch == NULL) |
886 | return; | 823 | return; |
@@ -891,7 +828,7 @@ static void moxa_stop(struct tty_struct *tty) | |||
891 | 828 | ||
892 | static void moxa_start(struct tty_struct *tty) | 829 | static void moxa_start(struct tty_struct *tty) |
893 | { | 830 | { |
894 | struct moxa_str *ch = (struct moxa_str *) tty->driver_data; | 831 | struct moxa_port *ch = (struct moxa_port *) tty->driver_data; |
895 | 832 | ||
896 | if (ch == NULL) | 833 | if (ch == NULL) |
897 | return; | 834 | return; |
@@ -905,7 +842,7 @@ static void moxa_start(struct tty_struct *tty) | |||
905 | 842 | ||
906 | static void moxa_hangup(struct tty_struct *tty) | 843 | static void moxa_hangup(struct tty_struct *tty) |
907 | { | 844 | { |
908 | struct moxa_str *ch = (struct moxa_str *) tty->driver_data; | 845 | struct moxa_port *ch = (struct moxa_port *) tty->driver_data; |
909 | 846 | ||
910 | moxa_flush_buffer(tty); | 847 | moxa_flush_buffer(tty); |
911 | shut_down(ch); | 848 | shut_down(ch); |
@@ -919,24 +856,20 @@ static void moxa_hangup(struct tty_struct *tty) | |||
919 | static void moxa_poll(unsigned long ignored) | 856 | static void moxa_poll(unsigned long ignored) |
920 | { | 857 | { |
921 | register int card; | 858 | register int card; |
922 | struct moxa_str *ch; | 859 | struct moxa_port *ch; |
923 | struct tty_struct *tp; | 860 | struct tty_struct *tp; |
924 | int i, ports; | 861 | int i, ports; |
925 | 862 | ||
926 | moxaTimer_on = 0; | ||
927 | del_timer(&moxaTimer); | 863 | del_timer(&moxaTimer); |
928 | 864 | ||
929 | if (MoxaDriverPoll() < 0) { | 865 | if (MoxaDriverPoll() < 0) { |
930 | moxaTimer.function = moxa_poll; | 866 | mod_timer(&moxaTimer, jiffies + HZ / 50); |
931 | moxaTimer.expires = jiffies + (HZ / 50); | ||
932 | moxaTimer_on = 1; | ||
933 | add_timer(&moxaTimer); | ||
934 | return; | 867 | return; |
935 | } | 868 | } |
936 | for (card = 0; card < MAX_BOARDS; card++) { | 869 | for (card = 0; card < MAX_BOARDS; card++) { |
937 | if ((ports = MoxaPortsOfCard(card)) <= 0) | 870 | if ((ports = MoxaPortsOfCard(card)) <= 0) |
938 | continue; | 871 | continue; |
939 | ch = &moxaChannels[card * MAX_PORTS_PER_BOARD]; | 872 | ch = &moxa_ports[card * MAX_PORTS_PER_BOARD]; |
940 | for (i = 0; i < ports; i++, ch++) { | 873 | for (i = 0; i < ports; i++, ch++) { |
941 | if ((ch->asyncflags & ASYNC_INITIALIZED) == 0) | 874 | if ((ch->asyncflags & ASYNC_INITIALIZED) == 0) |
942 | continue; | 875 | continue; |
@@ -962,18 +895,16 @@ static void moxa_poll(unsigned long ignored) | |||
962 | if (MoxaPortDCDON(ch->port)) | 895 | if (MoxaPortDCDON(ch->port)) |
963 | wake_up_interruptible(&ch->open_wait); | 896 | wake_up_interruptible(&ch->open_wait); |
964 | else { | 897 | else { |
965 | set_bit(MOXA_EVENT_HANGUP, &ch->event); | 898 | tty_hangup(tp); |
966 | schedule_work(&ch->tqueue); | 899 | wake_up_interruptible(&ch->open_wait); |
900 | ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE; | ||
967 | } | 901 | } |
968 | } | 902 | } |
969 | } | 903 | } |
970 | } | 904 | } |
971 | } | 905 | } |
972 | 906 | ||
973 | moxaTimer.function = moxa_poll; | 907 | mod_timer(&moxaTimer, jiffies + HZ / 50); |
974 | moxaTimer.expires = jiffies + (HZ / 50); | ||
975 | moxaTimer_on = 1; | ||
976 | add_timer(&moxaTimer); | ||
977 | } | 908 | } |
978 | 909 | ||
979 | /******************************************************************************/ | 910 | /******************************************************************************/ |
@@ -981,10 +912,10 @@ static void moxa_poll(unsigned long ignored) | |||
981 | static void set_tty_param(struct tty_struct *tty) | 912 | static void set_tty_param(struct tty_struct *tty) |
982 | { | 913 | { |
983 | register struct ktermios *ts; | 914 | register struct ktermios *ts; |
984 | struct moxa_str *ch; | 915 | struct moxa_port *ch; |
985 | int rts, cts, txflow, rxflow, xany; | 916 | int rts, cts, txflow, rxflow, xany; |
986 | 917 | ||
987 | ch = (struct moxa_str *) tty->driver_data; | 918 | ch = (struct moxa_port *) tty->driver_data; |
988 | ts = tty->termios; | 919 | ts = tty->termios; |
989 | if (ts->c_cflag & CLOCAL) | 920 | if (ts->c_cflag & CLOCAL) |
990 | ch->asyncflags &= ~ASYNC_CHECK_CD; | 921 | ch->asyncflags &= ~ASYNC_CHECK_CD; |
@@ -1004,7 +935,7 @@ static void set_tty_param(struct tty_struct *tty) | |||
1004 | } | 935 | } |
1005 | 936 | ||
1006 | static int block_till_ready(struct tty_struct *tty, struct file *filp, | 937 | static int block_till_ready(struct tty_struct *tty, struct file *filp, |
1007 | struct moxa_str *ch) | 938 | struct moxa_port *ch) |
1008 | { | 939 | { |
1009 | DECLARE_WAITQUEUE(wait,current); | 940 | DECLARE_WAITQUEUE(wait,current); |
1010 | unsigned long flags; | 941 | unsigned long flags; |
@@ -1095,40 +1026,33 @@ static int block_till_ready(struct tty_struct *tty, struct file *filp, | |||
1095 | 1026 | ||
1096 | static void setup_empty_event(struct tty_struct *tty) | 1027 | static void setup_empty_event(struct tty_struct *tty) |
1097 | { | 1028 | { |
1098 | struct moxa_str *ch = tty->driver_data; | 1029 | struct moxa_port *ch = tty->driver_data; |
1099 | unsigned long flags; | 1030 | unsigned long flags; |
1100 | 1031 | ||
1101 | spin_lock_irqsave(&moxa_lock, flags); | 1032 | spin_lock_irqsave(&moxa_lock, flags); |
1102 | ch->statusflags |= EMPTYWAIT; | 1033 | ch->statusflags |= EMPTYWAIT; |
1103 | moxaEmptyTimer_on[ch->port] = 0; | 1034 | mod_timer(&moxa_ports[ch->port].emptyTimer, jiffies + HZ); |
1104 | del_timer(&moxaEmptyTimer[ch->port]); | ||
1105 | moxaEmptyTimer[ch->port].expires = jiffies + HZ; | ||
1106 | moxaEmptyTimer_on[ch->port] = 1; | ||
1107 | add_timer(&moxaEmptyTimer[ch->port]); | ||
1108 | spin_unlock_irqrestore(&moxa_lock, flags); | 1035 | spin_unlock_irqrestore(&moxa_lock, flags); |
1109 | } | 1036 | } |
1110 | 1037 | ||
1111 | static void check_xmit_empty(unsigned long data) | 1038 | static void check_xmit_empty(unsigned long data) |
1112 | { | 1039 | { |
1113 | struct moxa_str *ch; | 1040 | struct moxa_port *ch; |
1114 | 1041 | ||
1115 | ch = (struct moxa_str *) data; | 1042 | ch = (struct moxa_port *) data; |
1116 | moxaEmptyTimer_on[ch->port] = 0; | 1043 | del_timer_sync(&moxa_ports[ch->port].emptyTimer); |
1117 | del_timer(&moxaEmptyTimer[ch->port]); | ||
1118 | if (ch->tty && (ch->statusflags & EMPTYWAIT)) { | 1044 | if (ch->tty && (ch->statusflags & EMPTYWAIT)) { |
1119 | if (MoxaPortTxQueue(ch->port) == 0) { | 1045 | if (MoxaPortTxQueue(ch->port) == 0) { |
1120 | ch->statusflags &= ~EMPTYWAIT; | 1046 | ch->statusflags &= ~EMPTYWAIT; |
1121 | tty_wakeup(ch->tty); | 1047 | tty_wakeup(ch->tty); |
1122 | return; | 1048 | return; |
1123 | } | 1049 | } |
1124 | moxaEmptyTimer[ch->port].expires = jiffies + HZ; | 1050 | mod_timer(&moxa_ports[ch->port].emptyTimer, jiffies + HZ); |
1125 | moxaEmptyTimer_on[ch->port] = 1; | ||
1126 | add_timer(&moxaEmptyTimer[ch->port]); | ||
1127 | } else | 1051 | } else |
1128 | ch->statusflags &= ~EMPTYWAIT; | 1052 | ch->statusflags &= ~EMPTYWAIT; |
1129 | } | 1053 | } |
1130 | 1054 | ||
1131 | static void shut_down(struct moxa_str *ch) | 1055 | static void shut_down(struct moxa_port *ch) |
1132 | { | 1056 | { |
1133 | struct tty_struct *tp; | 1057 | struct tty_struct *tp; |
1134 | 1058 | ||
@@ -1148,7 +1072,7 @@ static void shut_down(struct moxa_str *ch) | |||
1148 | ch->asyncflags &= ~ASYNC_INITIALIZED; | 1072 | ch->asyncflags &= ~ASYNC_INITIALIZED; |
1149 | } | 1073 | } |
1150 | 1074 | ||
1151 | static void receive_data(struct moxa_str *ch) | 1075 | static void receive_data(struct moxa_port *ch) |
1152 | { | 1076 | { |
1153 | struct tty_struct *tp; | 1077 | struct tty_struct *tp; |
1154 | struct ktermios *ts; | 1078 | struct ktermios *ts; |
@@ -1465,35 +1389,21 @@ static void receive_data(struct moxa_str *ch) | |||
1465 | /* | 1389 | /* |
1466 | * Query | 1390 | * Query |
1467 | */ | 1391 | */ |
1468 | #define QueryPort MAX_PORTS | ||
1469 | |||
1470 | |||
1471 | 1392 | ||
1472 | struct mon_str { | 1393 | struct mon_str { |
1473 | int tick; | 1394 | int tick; |
1474 | int rxcnt[MAX_PORTS]; | 1395 | int rxcnt[MAX_PORTS]; |
1475 | int txcnt[MAX_PORTS]; | 1396 | int txcnt[MAX_PORTS]; |
1476 | }; | 1397 | }; |
1477 | typedef struct mon_str mon_st; | ||
1478 | 1398 | ||
1479 | #define DCD_changed 0x01 | 1399 | #define DCD_changed 0x01 |
1480 | #define DCD_oldstate 0x80 | 1400 | #define DCD_oldstate 0x80 |
1481 | 1401 | ||
1482 | static unsigned char moxaBuff[10240]; | 1402 | static unsigned char moxaBuff[10240]; |
1483 | static void __iomem *moxaIntNdx[MAX_BOARDS]; | ||
1484 | static void __iomem *moxaIntPend[MAX_BOARDS]; | ||
1485 | static void __iomem *moxaIntTable[MAX_BOARDS]; | ||
1486 | static char moxaChkPort[MAX_PORTS]; | ||
1487 | static char moxaLineCtrl[MAX_PORTS]; | ||
1488 | static void __iomem *moxaTableAddr[MAX_PORTS]; | ||
1489 | static long moxaCurBaud[MAX_PORTS]; | ||
1490 | static char moxaDCDState[MAX_PORTS]; | ||
1491 | static char moxaLowChkFlag[MAX_PORTS]; | ||
1492 | static int moxaLowWaterChk; | 1403 | static int moxaLowWaterChk; |
1493 | static int moxaCard; | 1404 | static int moxaCard; |
1494 | static mon_st moxaLog; | 1405 | static struct mon_str moxaLog; |
1495 | static int moxaFuncTout; | 1406 | static int moxaFuncTout = HZ / 2; |
1496 | static ushort moxaBreakCnt[MAX_PORTS]; | ||
1497 | 1407 | ||
1498 | static void moxadelay(int); | 1408 | static void moxadelay(int); |
1499 | static void moxafunc(void __iomem *, int, ushort); | 1409 | static void moxafunc(void __iomem *, int, ushort); |
@@ -1514,16 +1424,18 @@ static int moxaloadc320(int, void __iomem *, int, int *); | |||
1514 | *****************************************************************************/ | 1424 | *****************************************************************************/ |
1515 | void MoxaDriverInit(void) | 1425 | void MoxaDriverInit(void) |
1516 | { | 1426 | { |
1517 | int i; | 1427 | struct moxa_port *p; |
1428 | unsigned int i; | ||
1518 | 1429 | ||
1519 | moxaFuncTout = HZ / 2; /* 500 mini-seconds */ | 1430 | moxaFuncTout = HZ / 2; /* 500 mini-seconds */ |
1520 | moxaCard = 0; | 1431 | moxaCard = 0; |
1521 | moxaLog.tick = 0; | 1432 | moxaLog.tick = 0; |
1522 | moxaLowWaterChk = 0; | 1433 | moxaLowWaterChk = 0; |
1523 | for (i = 0; i < MAX_PORTS; i++) { | 1434 | for (i = 0; i < MAX_PORTS; i++) { |
1524 | moxaChkPort[i] = 0; | 1435 | p = &moxa_ports[i]; |
1525 | moxaLowChkFlag[i] = 0; | 1436 | p->chkPort = 0; |
1526 | moxaLineCtrl[i] = 0; | 1437 | p->lowChkFlag = 0; |
1438 | p->lineCtrl = 0; | ||
1527 | moxaLog.rxcnt[i] = 0; | 1439 | moxaLog.rxcnt[i] = 0; |
1528 | moxaLog.txcnt[i] = 0; | 1440 | moxaLog.txcnt[i] = 0; |
1529 | } | 1441 | } |
@@ -1545,19 +1457,12 @@ void MoxaDriverInit(void) | |||
1545 | #define MOXA_GET_CUMAJOR (MOXA + 64) | 1457 | #define MOXA_GET_CUMAJOR (MOXA + 64) |
1546 | #define MOXA_GETMSTATUS (MOXA + 65) | 1458 | #define MOXA_GETMSTATUS (MOXA + 65) |
1547 | 1459 | ||
1548 | |||
1549 | struct moxaq_str { | ||
1550 | int inq; | ||
1551 | int outq; | ||
1552 | }; | ||
1553 | |||
1554 | struct dl_str { | 1460 | struct dl_str { |
1555 | char __user *buf; | 1461 | char __user *buf; |
1556 | int len; | 1462 | int len; |
1557 | int cardno; | 1463 | int cardno; |
1558 | }; | 1464 | }; |
1559 | 1465 | ||
1560 | static struct moxaq_str temp_queue[MAX_PORTS]; | ||
1561 | static struct dl_str dltmp; | 1466 | static struct dl_str dltmp; |
1562 | 1467 | ||
1563 | void MoxaPortFlushData(int port, int mode) | 1468 | void MoxaPortFlushData(int port, int mode) |
@@ -1565,10 +1470,10 @@ void MoxaPortFlushData(int port, int mode) | |||
1565 | void __iomem *ofsAddr; | 1470 | void __iomem *ofsAddr; |
1566 | if ((mode < 0) || (mode > 2)) | 1471 | if ((mode < 0) || (mode > 2)) |
1567 | return; | 1472 | return; |
1568 | ofsAddr = moxaTableAddr[port]; | 1473 | ofsAddr = moxa_ports[port].tableAddr; |
1569 | moxafunc(ofsAddr, FC_FlushQueue, mode); | 1474 | moxafunc(ofsAddr, FC_FlushQueue, mode); |
1570 | if (mode != 1) { | 1475 | if (mode != 1) { |
1571 | moxaLowChkFlag[port] = 0; | 1476 | moxa_ports[port].lowChkFlag = 0; |
1572 | low_water_check(ofsAddr); | 1477 | low_water_check(ofsAddr); |
1573 | } | 1478 | } |
1574 | } | 1479 | } |
@@ -1580,7 +1485,7 @@ int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port) | |||
1580 | int MoxaPortTxQueue(int), MoxaPortRxQueue(int); | 1485 | int MoxaPortTxQueue(int), MoxaPortRxQueue(int); |
1581 | void __user *argp = (void __user *)arg; | 1486 | void __user *argp = (void __user *)arg; |
1582 | 1487 | ||
1583 | if (port == QueryPort) { | 1488 | if (port == MAX_PORTS) { |
1584 | if ((cmd != MOXA_GET_CONF) && (cmd != MOXA_INIT_DRIVER) && | 1489 | if ((cmd != MOXA_GET_CONF) && (cmd != MOXA_INIT_DRIVER) && |
1585 | (cmd != MOXA_LOAD_BIOS) && (cmd != MOXA_FIND_BOARD) && (cmd != MOXA_LOAD_C320B) && | 1490 | (cmd != MOXA_LOAD_BIOS) && (cmd != MOXA_FIND_BOARD) && (cmd != MOXA_LOAD_C320B) && |
1586 | (cmd != MOXA_LOAD_CODE) && (cmd != MOXA_GETDATACOUNT) && | 1491 | (cmd != MOXA_LOAD_CODE) && (cmd != MOXA_GETDATACOUNT) && |
@@ -1590,7 +1495,8 @@ int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port) | |||
1590 | } | 1495 | } |
1591 | switch (cmd) { | 1496 | switch (cmd) { |
1592 | case MOXA_GET_CONF: | 1497 | case MOXA_GET_CONF: |
1593 | if(copy_to_user(argp, &moxa_boards, MAX_BOARDS * sizeof(moxa_board_conf))) | 1498 | if(copy_to_user(argp, &moxa_boards, MAX_BOARDS * |
1499 | sizeof(struct moxa_board_conf))) | ||
1594 | return -EFAULT; | 1500 | return -EFAULT; |
1595 | return (0); | 1501 | return (0); |
1596 | case MOXA_INIT_DRIVER: | 1502 | case MOXA_INIT_DRIVER: |
@@ -1599,23 +1505,27 @@ int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port) | |||
1599 | return (0); | 1505 | return (0); |
1600 | case MOXA_GETDATACOUNT: | 1506 | case MOXA_GETDATACOUNT: |
1601 | moxaLog.tick = jiffies; | 1507 | moxaLog.tick = jiffies; |
1602 | if(copy_to_user(argp, &moxaLog, sizeof(mon_st))) | 1508 | if(copy_to_user(argp, &moxaLog, sizeof(struct mon_str))) |
1603 | return -EFAULT; | 1509 | return -EFAULT; |
1604 | return (0); | 1510 | return (0); |
1605 | case MOXA_FLUSH_QUEUE: | 1511 | case MOXA_FLUSH_QUEUE: |
1606 | MoxaPortFlushData(port, arg); | 1512 | MoxaPortFlushData(port, arg); |
1607 | return (0); | 1513 | return (0); |
1608 | case MOXA_GET_IOQUEUE: | 1514 | case MOXA_GET_IOQUEUE: { |
1609 | for (i = 0; i < MAX_PORTS; i++) { | 1515 | struct moxaq_str __user *argm = argp; |
1610 | if (moxaChkPort[i]) { | 1516 | struct moxaq_str tmp; |
1611 | temp_queue[i].inq = MoxaPortRxQueue(i); | 1517 | |
1612 | temp_queue[i].outq = MoxaPortTxQueue(i); | 1518 | for (i = 0; i < MAX_PORTS; i++, argm++) { |
1519 | memset(&tmp, 0, sizeof(tmp)); | ||
1520 | if (moxa_ports[i].chkPort) { | ||
1521 | tmp.inq = MoxaPortRxQueue(i); | ||
1522 | tmp.outq = MoxaPortTxQueue(i); | ||
1613 | } | 1523 | } |
1524 | if (copy_to_user(argm, &tmp, sizeof(tmp))) | ||
1525 | return -EFAULT; | ||
1614 | } | 1526 | } |
1615 | if(copy_to_user(argp, temp_queue, sizeof(struct moxaq_str) * MAX_PORTS)) | ||
1616 | return -EFAULT; | ||
1617 | return (0); | 1527 | return (0); |
1618 | case MOXA_GET_OQUEUE: | 1528 | } case MOXA_GET_OQUEUE: |
1619 | i = MoxaPortTxQueue(port); | 1529 | i = MoxaPortTxQueue(port); |
1620 | return put_user(i, (unsigned long __user *)argp); | 1530 | return put_user(i, (unsigned long __user *)argp); |
1621 | case MOXA_GET_IQUEUE: | 1531 | case MOXA_GET_IQUEUE: |
@@ -1630,33 +1540,36 @@ int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port) | |||
1630 | if(copy_to_user(argp, &i, sizeof(int))) | 1540 | if(copy_to_user(argp, &i, sizeof(int))) |
1631 | return -EFAULT; | 1541 | return -EFAULT; |
1632 | return 0; | 1542 | return 0; |
1633 | case MOXA_GETMSTATUS: | 1543 | case MOXA_GETMSTATUS: { |
1634 | for (i = 0; i < MAX_PORTS; i++) { | 1544 | struct mxser_mstatus __user *argm = argp; |
1635 | GMStatus[i].ri = 0; | 1545 | struct mxser_mstatus tmp; |
1636 | GMStatus[i].dcd = 0; | 1546 | struct moxa_port *p; |
1637 | GMStatus[i].dsr = 0; | 1547 | |
1638 | GMStatus[i].cts = 0; | 1548 | for (i = 0; i < MAX_PORTS; i++, argm++) { |
1639 | if (!moxaChkPort[i]) { | 1549 | p = &moxa_ports[i]; |
1640 | continue; | 1550 | memset(&tmp, 0, sizeof(tmp)); |
1551 | if (!p->chkPort) { | ||
1552 | goto copy; | ||
1641 | } else { | 1553 | } else { |
1642 | status = MoxaPortLineStatus(moxaChannels[i].port); | 1554 | status = MoxaPortLineStatus(p->port); |
1643 | if (status & 1) | 1555 | if (status & 1) |
1644 | GMStatus[i].cts = 1; | 1556 | tmp.cts = 1; |
1645 | if (status & 2) | 1557 | if (status & 2) |
1646 | GMStatus[i].dsr = 1; | 1558 | tmp.dsr = 1; |
1647 | if (status & 4) | 1559 | if (status & 4) |
1648 | GMStatus[i].dcd = 1; | 1560 | tmp.dcd = 1; |
1649 | } | 1561 | } |
1650 | 1562 | ||
1651 | if (!moxaChannels[i].tty || !moxaChannels[i].tty->termios) | 1563 | if (!p->tty || !p->tty->termios) |
1652 | GMStatus[i].cflag = moxaChannels[i].cflag; | 1564 | tmp.cflag = p->cflag; |
1653 | else | 1565 | else |
1654 | GMStatus[i].cflag = moxaChannels[i].tty->termios->c_cflag; | 1566 | tmp.cflag = p->tty->termios->c_cflag; |
1567 | copy: | ||
1568 | if (copy_to_user(argm, &tmp, sizeof(tmp))) | ||
1569 | return -EFAULT; | ||
1655 | } | 1570 | } |
1656 | if(copy_to_user(argp, GMStatus, sizeof(struct mxser_mstatus) * MAX_PORTS)) | ||
1657 | return -EFAULT; | ||
1658 | return 0; | 1571 | return 0; |
1659 | default: | 1572 | } default: |
1660 | return (-ENOIOCTLCMD); | 1573 | return (-ENOIOCTLCMD); |
1661 | case MOXA_LOAD_BIOS: | 1574 | case MOXA_LOAD_BIOS: |
1662 | case MOXA_FIND_BOARD: | 1575 | case MOXA_FIND_BOARD: |
@@ -1694,6 +1607,7 @@ int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port) | |||
1694 | 1607 | ||
1695 | int MoxaDriverPoll(void) | 1608 | int MoxaDriverPoll(void) |
1696 | { | 1609 | { |
1610 | struct moxa_board_conf *brd; | ||
1697 | register ushort temp; | 1611 | register ushort temp; |
1698 | register int card; | 1612 | register int card; |
1699 | void __iomem *ofsAddr; | 1613 | void __iomem *ofsAddr; |
@@ -1703,43 +1617,44 @@ int MoxaDriverPoll(void) | |||
1703 | if (moxaCard == 0) | 1617 | if (moxaCard == 0) |
1704 | return (-1); | 1618 | return (-1); |
1705 | for (card = 0; card < MAX_BOARDS; card++) { | 1619 | for (card = 0; card < MAX_BOARDS; card++) { |
1706 | if (loadstat[card] == 0) | 1620 | brd = &moxa_boards[card]; |
1621 | if (brd->loadstat == 0) | ||
1707 | continue; | 1622 | continue; |
1708 | if ((ports = moxa_boards[card].numPorts) == 0) | 1623 | if ((ports = brd->numPorts) == 0) |
1709 | continue; | 1624 | continue; |
1710 | if (readb(moxaIntPend[card]) == 0xff) { | 1625 | if (readb(brd->intPend) == 0xff) { |
1711 | ip = moxaIntTable[card] + readb(moxaIntNdx[card]); | 1626 | ip = brd->intTable + readb(brd->intNdx); |
1712 | p = card * MAX_PORTS_PER_BOARD; | 1627 | p = card * MAX_PORTS_PER_BOARD; |
1713 | ports <<= 1; | 1628 | ports <<= 1; |
1714 | for (port = 0; port < ports; port += 2, p++) { | 1629 | for (port = 0; port < ports; port += 2, p++) { |
1715 | if ((temp = readw(ip + port)) != 0) { | 1630 | if ((temp = readw(ip + port)) != 0) { |
1716 | writew(0, ip + port); | 1631 | writew(0, ip + port); |
1717 | ofsAddr = moxaTableAddr[p]; | 1632 | ofsAddr = moxa_ports[p].tableAddr; |
1718 | if (temp & IntrTx) | 1633 | if (temp & IntrTx) |
1719 | writew(readw(ofsAddr + HostStat) & ~WakeupTx, ofsAddr + HostStat); | 1634 | writew(readw(ofsAddr + HostStat) & ~WakeupTx, ofsAddr + HostStat); |
1720 | if (temp & IntrBreak) { | 1635 | if (temp & IntrBreak) { |
1721 | moxaBreakCnt[p]++; | 1636 | moxa_ports[p].breakCnt++; |
1722 | } | 1637 | } |
1723 | if (temp & IntrLine) { | 1638 | if (temp & IntrLine) { |
1724 | if (readb(ofsAddr + FlagStat) & DCD_state) { | 1639 | if (readb(ofsAddr + FlagStat) & DCD_state) { |
1725 | if ((moxaDCDState[p] & DCD_oldstate) == 0) | 1640 | if ((moxa_ports[p].DCDState & DCD_oldstate) == 0) |
1726 | moxaDCDState[p] = (DCD_oldstate | | 1641 | moxa_ports[p].DCDState = (DCD_oldstate | |
1727 | DCD_changed); | 1642 | DCD_changed); |
1728 | } else { | 1643 | } else { |
1729 | if (moxaDCDState[p] & DCD_oldstate) | 1644 | if (moxa_ports[p].DCDState & DCD_oldstate) |
1730 | moxaDCDState[p] = DCD_changed; | 1645 | moxa_ports[p].DCDState = DCD_changed; |
1731 | } | 1646 | } |
1732 | } | 1647 | } |
1733 | } | 1648 | } |
1734 | } | 1649 | } |
1735 | writeb(0, moxaIntPend[card]); | 1650 | writeb(0, brd->intPend); |
1736 | } | 1651 | } |
1737 | if (moxaLowWaterChk) { | 1652 | if (moxaLowWaterChk) { |
1738 | p = card * MAX_PORTS_PER_BOARD; | 1653 | p = card * MAX_PORTS_PER_BOARD; |
1739 | for (port = 0; port < ports; port++, p++) { | 1654 | for (port = 0; port < ports; port++, p++) { |
1740 | if (moxaLowChkFlag[p]) { | 1655 | if (moxa_ports[p].lowChkFlag) { |
1741 | moxaLowChkFlag[p] = 0; | 1656 | moxa_ports[p].lowChkFlag = 0; |
1742 | ofsAddr = moxaTableAddr[p]; | 1657 | ofsAddr = moxa_ports[p].tableAddr; |
1743 | low_water_check(ofsAddr); | 1658 | low_water_check(ofsAddr); |
1744 | } | 1659 | } |
1745 | } | 1660 | } |
@@ -1767,9 +1682,7 @@ int MoxaPortsOfCard(int cardno) | |||
1767 | * 2. MoxaPortEnable(int port); * | 1682 | * 2. MoxaPortEnable(int port); * |
1768 | * 3. MoxaPortDisable(int port); * | 1683 | * 3. MoxaPortDisable(int port); * |
1769 | * 4. MoxaPortGetMaxBaud(int port); * | 1684 | * 4. MoxaPortGetMaxBaud(int port); * |
1770 | * 5. MoxaPortGetCurBaud(int port); * | ||
1771 | * 6. MoxaPortSetBaud(int port, long baud); * | 1685 | * 6. MoxaPortSetBaud(int port, long baud); * |
1772 | * 7. MoxaPortSetMode(int port, int databit, int stopbit, int parity); * | ||
1773 | * 8. MoxaPortSetTermio(int port, unsigned char *termio); * | 1686 | * 8. MoxaPortSetTermio(int port, unsigned char *termio); * |
1774 | * 9. MoxaPortGetLineOut(int port, int *dtrState, int *rtsState); * | 1687 | * 9. MoxaPortGetLineOut(int port, int *dtrState, int *rtsState); * |
1775 | * 10. MoxaPortLineCtrl(int port, int dtrState, int rtsState); * | 1688 | * 10. MoxaPortLineCtrl(int port, int dtrState, int rtsState); * |
@@ -1780,18 +1693,12 @@ int MoxaPortsOfCard(int cardno) | |||
1780 | * 15. MoxaPortFlushData(int port, int mode); * | 1693 | * 15. MoxaPortFlushData(int port, int mode); * |
1781 | * 16. MoxaPortWriteData(int port, unsigned char * buffer, int length); * | 1694 | * 16. MoxaPortWriteData(int port, unsigned char * buffer, int length); * |
1782 | * 17. MoxaPortReadData(int port, struct tty_struct *tty); * | 1695 | * 17. MoxaPortReadData(int port, struct tty_struct *tty); * |
1783 | * 18. MoxaPortTxBufSize(int port); * | ||
1784 | * 19. MoxaPortRxBufSize(int port); * | ||
1785 | * 20. MoxaPortTxQueue(int port); * | 1696 | * 20. MoxaPortTxQueue(int port); * |
1786 | * 21. MoxaPortTxFree(int port); * | 1697 | * 21. MoxaPortTxFree(int port); * |
1787 | * 22. MoxaPortRxQueue(int port); * | 1698 | * 22. MoxaPortRxQueue(int port); * |
1788 | * 23. MoxaPortRxFree(int port); * | ||
1789 | * 24. MoxaPortTxDisable(int port); * | 1699 | * 24. MoxaPortTxDisable(int port); * |
1790 | * 25. MoxaPortTxEnable(int port); * | 1700 | * 25. MoxaPortTxEnable(int port); * |
1791 | * 26. MoxaPortGetBrkCnt(int port); * | ||
1792 | * 27. MoxaPortResetBrkCnt(int port); * | 1701 | * 27. MoxaPortResetBrkCnt(int port); * |
1793 | * 28. MoxaPortSetXonXoff(int port, int xonValue, int xoffValue); * | ||
1794 | * 29. MoxaPortIsTxHold(int port); * | ||
1795 | * 30. MoxaPortSendBreak(int port, int ticks); * | 1702 | * 30. MoxaPortSendBreak(int port, int ticks); * |
1796 | *****************************************************************************/ | 1703 | *****************************************************************************/ |
1797 | /* | 1704 | /* |
@@ -1878,15 +1785,6 @@ int MoxaPortsOfCard(int cardno) | |||
1878 | * 38400/57600/115200 bps | 1785 | * 38400/57600/115200 bps |
1879 | * | 1786 | * |
1880 | * | 1787 | * |
1881 | * Function 9: Get the current baud rate of this port. | ||
1882 | * Syntax: | ||
1883 | * long MoxaPortGetCurBaud(int port); | ||
1884 | * int port : port number (0 - 127) | ||
1885 | * | ||
1886 | * return: 0 : this port is invalid | ||
1887 | * 50 - 115200 bps | ||
1888 | * | ||
1889 | * | ||
1890 | * Function 10: Setting baud rate of this port. | 1788 | * Function 10: Setting baud rate of this port. |
1891 | * Syntax: | 1789 | * Syntax: |
1892 | * long MoxaPortSetBaud(int port, long baud); | 1790 | * long MoxaPortSetBaud(int port, long baud); |
@@ -1900,18 +1798,6 @@ int MoxaPortsOfCard(int cardno) | |||
1900 | * baud rate will be the maximun baud rate. | 1798 | * baud rate will be the maximun baud rate. |
1901 | * | 1799 | * |
1902 | * | 1800 | * |
1903 | * Function 11: Setting the data-bits/stop-bits/parity of this port | ||
1904 | * Syntax: | ||
1905 | * int MoxaPortSetMode(int port, int databits, int stopbits, int parity); | ||
1906 | * int port : port number (0 - 127) | ||
1907 | * int databits : data bits (8/7/6/5) | ||
1908 | * int stopbits : stop bits (2/1/0, 0 show 1.5 stop bits) | ||
1909 | int parity : parity (0:None,1:Odd,2:Even,3:Mark,4:Space) | ||
1910 | * | ||
1911 | * return: -1 : invalid parameter | ||
1912 | * 0 : setting O.K. | ||
1913 | * | ||
1914 | * | ||
1915 | * Function 12: Configure the port. | 1801 | * Function 12: Configure the port. |
1916 | * Syntax: | 1802 | * Syntax: |
1917 | * int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud); | 1803 | * int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud); |
@@ -2016,22 +1902,6 @@ int MoxaPortsOfCard(int cardno) | |||
2016 | * return: 0 - length : real read data length | 1902 | * return: 0 - length : real read data length |
2017 | * | 1903 | * |
2018 | * | 1904 | * |
2019 | * Function 22: Get the Tx buffer size of this port | ||
2020 | * Syntax: | ||
2021 | * int MoxaPortTxBufSize(int port); | ||
2022 | * int port : port number (0 - 127) | ||
2023 | * | ||
2024 | * return: .. : Tx buffer size | ||
2025 | * | ||
2026 | * | ||
2027 | * Function 23: Get the Rx buffer size of this port | ||
2028 | * Syntax: | ||
2029 | * int MoxaPortRxBufSize(int port); | ||
2030 | * int port : port number (0 - 127) | ||
2031 | * | ||
2032 | * return: .. : Rx buffer size | ||
2033 | * | ||
2034 | * | ||
2035 | * Function 24: Get the Tx buffer current queued data bytes | 1905 | * Function 24: Get the Tx buffer current queued data bytes |
2036 | * Syntax: | 1906 | * Syntax: |
2037 | * int MoxaPortTxQueue(int port); | 1907 | * int MoxaPortTxQueue(int port); |
@@ -2056,14 +1926,6 @@ int MoxaPortsOfCard(int cardno) | |||
2056 | * return: .. : Rx buffer current queued data bytes | 1926 | * return: .. : Rx buffer current queued data bytes |
2057 | * | 1927 | * |
2058 | * | 1928 | * |
2059 | * Function 27: Get the Rx buffer current free space | ||
2060 | * Syntax: | ||
2061 | * int MoxaPortRxFree(int port); | ||
2062 | * int port : port number (0 - 127) | ||
2063 | * | ||
2064 | * return: .. : Rx buffer current free space | ||
2065 | * | ||
2066 | * | ||
2067 | * Function 28: Disable port data transmission. | 1929 | * Function 28: Disable port data transmission. |
2068 | * Syntax: | 1930 | * Syntax: |
2069 | * void MoxaPortTxDisable(int port); | 1931 | * void MoxaPortTxDisable(int port); |
@@ -2076,14 +1938,6 @@ int MoxaPortsOfCard(int cardno) | |||
2076 | * int port : port number (0 - 127) | 1938 | * int port : port number (0 - 127) |
2077 | * | 1939 | * |
2078 | * | 1940 | * |
2079 | * Function 30: Get the received BREAK signal count. | ||
2080 | * Syntax: | ||
2081 | * int MoxaPortGetBrkCnt(int port); | ||
2082 | * int port : port number (0 - 127) | ||
2083 | * | ||
2084 | * return: 0 - .. : BREAK signal count | ||
2085 | * | ||
2086 | * | ||
2087 | * Function 31: Get the received BREAK signal count and reset it. | 1941 | * Function 31: Get the received BREAK signal count and reset it. |
2088 | * Syntax: | 1942 | * Syntax: |
2089 | * int MoxaPortResetBrkCnt(int port); | 1943 | * int MoxaPortResetBrkCnt(int port); |
@@ -2092,25 +1946,6 @@ int MoxaPortsOfCard(int cardno) | |||
2092 | * return: 0 - .. : BREAK signal count | 1946 | * return: 0 - .. : BREAK signal count |
2093 | * | 1947 | * |
2094 | * | 1948 | * |
2095 | * Function 32: Set the S/W flow control new XON/XOFF value, default | ||
2096 | * XON is 0x11 & XOFF is 0x13. | ||
2097 | * Syntax: | ||
2098 | * void MoxaPortSetXonXoff(int port, int xonValue, int xoffValue); | ||
2099 | * int port : port number (0 - 127) | ||
2100 | * int xonValue : new XON value (0 - 255) | ||
2101 | * int xoffValue : new XOFF value (0 - 255) | ||
2102 | * | ||
2103 | * | ||
2104 | * Function 33: Check this port's transmission is hold by remote site | ||
2105 | * because the flow control. | ||
2106 | * Syntax: | ||
2107 | * int MoxaPortIsTxHold(int port); | ||
2108 | * int port : port number (0 - 127) | ||
2109 | * | ||
2110 | * return: 0 : normal | ||
2111 | * 1 : hold by remote site | ||
2112 | * | ||
2113 | * | ||
2114 | * Function 34: Send out a BREAK signal. | 1949 | * Function 34: Send out a BREAK signal. |
2115 | * Syntax: | 1950 | * Syntax: |
2116 | * void MoxaPortSendBreak(int port, int ms100); | 1951 | * void MoxaPortSendBreak(int port, int ms100); |
@@ -2125,7 +1960,7 @@ int MoxaPortIsValid(int port) | |||
2125 | 1960 | ||
2126 | if (moxaCard == 0) | 1961 | if (moxaCard == 0) |
2127 | return (0); | 1962 | return (0); |
2128 | if (moxaChkPort[port] == 0) | 1963 | if (moxa_ports[port].chkPort == 0) |
2129 | return (0); | 1964 | return (0); |
2130 | return (1); | 1965 | return (1); |
2131 | } | 1966 | } |
@@ -2136,9 +1971,9 @@ void MoxaPortEnable(int port) | |||
2136 | int MoxaPortLineStatus(int); | 1971 | int MoxaPortLineStatus(int); |
2137 | short lowwater = 512; | 1972 | short lowwater = 512; |
2138 | 1973 | ||
2139 | ofsAddr = moxaTableAddr[port]; | 1974 | ofsAddr = moxa_ports[port].tableAddr; |
2140 | writew(lowwater, ofsAddr + Low_water); | 1975 | writew(lowwater, ofsAddr + Low_water); |
2141 | moxaBreakCnt[port] = 0; | 1976 | moxa_ports[port].breakCnt = 0; |
2142 | if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) || | 1977 | if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) || |
2143 | (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) { | 1978 | (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) { |
2144 | moxafunc(ofsAddr, FC_SetBreakIrq, 0); | 1979 | moxafunc(ofsAddr, FC_SetBreakIrq, 0); |
@@ -2155,7 +1990,7 @@ void MoxaPortEnable(int port) | |||
2155 | 1990 | ||
2156 | void MoxaPortDisable(int port) | 1991 | void MoxaPortDisable(int port) |
2157 | { | 1992 | { |
2158 | void __iomem *ofsAddr = moxaTableAddr[port]; | 1993 | void __iomem *ofsAddr = moxa_ports[port].tableAddr; |
2159 | 1994 | ||
2160 | moxafunc(ofsAddr, FC_SetFlowCtl, 0); /* disable flow control */ | 1995 | moxafunc(ofsAddr, FC_SetFlowCtl, 0); /* disable flow control */ |
2161 | moxafunc(ofsAddr, FC_ClrLineIrq, Magic_code); | 1996 | moxafunc(ofsAddr, FC_ClrLineIrq, Magic_code); |
@@ -2181,7 +2016,7 @@ long MoxaPortSetBaud(int port, long baud) | |||
2181 | 2016 | ||
2182 | if ((baud < 50L) || ((max = MoxaPortGetMaxBaud(port)) == 0)) | 2017 | if ((baud < 50L) || ((max = MoxaPortGetMaxBaud(port)) == 0)) |
2183 | return (0); | 2018 | return (0); |
2184 | ofsAddr = moxaTableAddr[port]; | 2019 | ofsAddr = moxa_ports[port].tableAddr; |
2185 | if (baud > max) | 2020 | if (baud > max) |
2186 | baud = max; | 2021 | baud = max; |
2187 | if (max == 38400L) | 2022 | if (max == 38400L) |
@@ -2193,7 +2028,7 @@ long MoxaPortSetBaud(int port, long baud) | |||
2193 | val = clock / baud; | 2028 | val = clock / baud; |
2194 | moxafunc(ofsAddr, FC_SetBaud, val); | 2029 | moxafunc(ofsAddr, FC_SetBaud, val); |
2195 | baud = clock / val; | 2030 | baud = clock / val; |
2196 | moxaCurBaud[port] = baud; | 2031 | moxa_ports[port].curBaud = baud; |
2197 | return (baud); | 2032 | return (baud); |
2198 | } | 2033 | } |
2199 | 2034 | ||
@@ -2203,9 +2038,9 @@ int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud) | |||
2203 | tcflag_t cflag; | 2038 | tcflag_t cflag; |
2204 | tcflag_t mode = 0; | 2039 | tcflag_t mode = 0; |
2205 | 2040 | ||
2206 | if (moxaChkPort[port] == 0 || termio == 0) | 2041 | if (moxa_ports[port].chkPort == 0 || termio == 0) |
2207 | return (-1); | 2042 | return (-1); |
2208 | ofsAddr = moxaTableAddr[port]; | 2043 | ofsAddr = moxa_ports[port].tableAddr; |
2209 | cflag = termio->c_cflag; /* termio->c_cflag */ | 2044 | cflag = termio->c_cflag; /* termio->c_cflag */ |
2210 | 2045 | ||
2211 | mode = termio->c_cflag & CSIZE; | 2046 | mode = termio->c_cflag & CSIZE; |
@@ -2259,13 +2094,13 @@ int MoxaPortGetLineOut(int port, int *dtrState, int *rtsState) | |||
2259 | if (!MoxaPortIsValid(port)) | 2094 | if (!MoxaPortIsValid(port)) |
2260 | return (-1); | 2095 | return (-1); |
2261 | if (dtrState) { | 2096 | if (dtrState) { |
2262 | if (moxaLineCtrl[port] & DTR_ON) | 2097 | if (moxa_ports[port].lineCtrl & DTR_ON) |
2263 | *dtrState = 1; | 2098 | *dtrState = 1; |
2264 | else | 2099 | else |
2265 | *dtrState = 0; | 2100 | *dtrState = 0; |
2266 | } | 2101 | } |
2267 | if (rtsState) { | 2102 | if (rtsState) { |
2268 | if (moxaLineCtrl[port] & RTS_ON) | 2103 | if (moxa_ports[port].lineCtrl & RTS_ON) |
2269 | *rtsState = 1; | 2104 | *rtsState = 1; |
2270 | else | 2105 | else |
2271 | *rtsState = 0; | 2106 | *rtsState = 0; |
@@ -2278,13 +2113,13 @@ void MoxaPortLineCtrl(int port, int dtr, int rts) | |||
2278 | void __iomem *ofsAddr; | 2113 | void __iomem *ofsAddr; |
2279 | int mode; | 2114 | int mode; |
2280 | 2115 | ||
2281 | ofsAddr = moxaTableAddr[port]; | 2116 | ofsAddr = moxa_ports[port].tableAddr; |
2282 | mode = 0; | 2117 | mode = 0; |
2283 | if (dtr) | 2118 | if (dtr) |
2284 | mode |= DTR_ON; | 2119 | mode |= DTR_ON; |
2285 | if (rts) | 2120 | if (rts) |
2286 | mode |= RTS_ON; | 2121 | mode |= RTS_ON; |
2287 | moxaLineCtrl[port] = mode; | 2122 | moxa_ports[port].lineCtrl = mode; |
2288 | moxafunc(ofsAddr, FC_LineControl, mode); | 2123 | moxafunc(ofsAddr, FC_LineControl, mode); |
2289 | } | 2124 | } |
2290 | 2125 | ||
@@ -2293,7 +2128,7 @@ void MoxaPortFlowCtrl(int port, int rts, int cts, int txflow, int rxflow, int tx | |||
2293 | void __iomem *ofsAddr; | 2128 | void __iomem *ofsAddr; |
2294 | int mode; | 2129 | int mode; |
2295 | 2130 | ||
2296 | ofsAddr = moxaTableAddr[port]; | 2131 | ofsAddr = moxa_ports[port].tableAddr; |
2297 | mode = 0; | 2132 | mode = 0; |
2298 | if (rts) | 2133 | if (rts) |
2299 | mode |= RTS_FlowCtl; | 2134 | mode |= RTS_FlowCtl; |
@@ -2313,7 +2148,7 @@ int MoxaPortLineStatus(int port) | |||
2313 | void __iomem *ofsAddr; | 2148 | void __iomem *ofsAddr; |
2314 | int val; | 2149 | int val; |
2315 | 2150 | ||
2316 | ofsAddr = moxaTableAddr[port]; | 2151 | ofsAddr = moxa_ports[port].tableAddr; |
2317 | if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) || | 2152 | if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) || |
2318 | (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) { | 2153 | (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) { |
2319 | moxafunc(ofsAddr, FC_LineStatus, 0); | 2154 | moxafunc(ofsAddr, FC_LineStatus, 0); |
@@ -2324,11 +2159,11 @@ int MoxaPortLineStatus(int port) | |||
2324 | val &= 0x0B; | 2159 | val &= 0x0B; |
2325 | if (val & 8) { | 2160 | if (val & 8) { |
2326 | val |= 4; | 2161 | val |= 4; |
2327 | if ((moxaDCDState[port] & DCD_oldstate) == 0) | 2162 | if ((moxa_ports[port].DCDState & DCD_oldstate) == 0) |
2328 | moxaDCDState[port] = (DCD_oldstate | DCD_changed); | 2163 | moxa_ports[port].DCDState = (DCD_oldstate | DCD_changed); |
2329 | } else { | 2164 | } else { |
2330 | if (moxaDCDState[port] & DCD_oldstate) | 2165 | if (moxa_ports[port].DCDState & DCD_oldstate) |
2331 | moxaDCDState[port] = DCD_changed; | 2166 | moxa_ports[port].DCDState = DCD_changed; |
2332 | } | 2167 | } |
2333 | val &= 7; | 2168 | val &= 7; |
2334 | return (val); | 2169 | return (val); |
@@ -2338,10 +2173,10 @@ int MoxaPortDCDChange(int port) | |||
2338 | { | 2173 | { |
2339 | int n; | 2174 | int n; |
2340 | 2175 | ||
2341 | if (moxaChkPort[port] == 0) | 2176 | if (moxa_ports[port].chkPort == 0) |
2342 | return (0); | 2177 | return (0); |
2343 | n = moxaDCDState[port]; | 2178 | n = moxa_ports[port].DCDState; |
2344 | moxaDCDState[port] &= ~DCD_changed; | 2179 | moxa_ports[port].DCDState &= ~DCD_changed; |
2345 | n &= DCD_changed; | 2180 | n &= DCD_changed; |
2346 | return (n); | 2181 | return (n); |
2347 | } | 2182 | } |
@@ -2350,32 +2185,15 @@ int MoxaPortDCDON(int port) | |||
2350 | { | 2185 | { |
2351 | int n; | 2186 | int n; |
2352 | 2187 | ||
2353 | if (moxaChkPort[port] == 0) | 2188 | if (moxa_ports[port].chkPort == 0) |
2354 | return (0); | 2189 | return (0); |
2355 | if (moxaDCDState[port] & DCD_oldstate) | 2190 | if (moxa_ports[port].DCDState & DCD_oldstate) |
2356 | n = 1; | 2191 | n = 1; |
2357 | else | 2192 | else |
2358 | n = 0; | 2193 | n = 0; |
2359 | return (n); | 2194 | return (n); |
2360 | } | 2195 | } |
2361 | 2196 | ||
2362 | |||
2363 | /* | ||
2364 | int MoxaDumpMem(int port, unsigned char * buffer, int len) | ||
2365 | { | ||
2366 | int i; | ||
2367 | unsigned long baseAddr,ofsAddr,ofs; | ||
2368 | |||
2369 | baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD]; | ||
2370 | ofs = baseAddr + DynPage_addr + pageofs; | ||
2371 | if (len > 0x2000L) | ||
2372 | len = 0x2000L; | ||
2373 | for (i = 0; i < len; i++) | ||
2374 | buffer[i] = readb(ofs+i); | ||
2375 | } | ||
2376 | */ | ||
2377 | |||
2378 | |||
2379 | int MoxaPortWriteData(int port, unsigned char * buffer, int len) | 2197 | int MoxaPortWriteData(int port, unsigned char * buffer, int len) |
2380 | { | 2198 | { |
2381 | int c, total, i; | 2199 | int c, total, i; |
@@ -2385,8 +2203,8 @@ int MoxaPortWriteData(int port, unsigned char * buffer, int len) | |||
2385 | ushort pageno, pageofs, bufhead; | 2203 | ushort pageno, pageofs, bufhead; |
2386 | void __iomem *baseAddr, *ofsAddr, *ofs; | 2204 | void __iomem *baseAddr, *ofsAddr, *ofs; |
2387 | 2205 | ||
2388 | ofsAddr = moxaTableAddr[port]; | 2206 | ofsAddr = moxa_ports[port].tableAddr; |
2389 | baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD]; | 2207 | baseAddr = moxa_boards[port / MAX_PORTS_PER_BOARD].basemem; |
2390 | tx_mask = readw(ofsAddr + TX_mask); | 2208 | tx_mask = readw(ofsAddr + TX_mask); |
2391 | spage = readw(ofsAddr + Page_txb); | 2209 | spage = readw(ofsAddr + Page_txb); |
2392 | epage = readw(ofsAddr + EndPage_txb); | 2210 | epage = readw(ofsAddr + EndPage_txb); |
@@ -2448,8 +2266,8 @@ int MoxaPortReadData(int port, struct tty_struct *tty) | |||
2448 | ushort pageno, bufhead; | 2266 | ushort pageno, bufhead; |
2449 | void __iomem *baseAddr, *ofsAddr, *ofs; | 2267 | void __iomem *baseAddr, *ofsAddr, *ofs; |
2450 | 2268 | ||
2451 | ofsAddr = moxaTableAddr[port]; | 2269 | ofsAddr = moxa_ports[port].tableAddr; |
2452 | baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD]; | 2270 | baseAddr = moxa_boards[port / MAX_PORTS_PER_BOARD].basemem; |
2453 | head = readw(ofsAddr + RXrptr); | 2271 | head = readw(ofsAddr + RXrptr); |
2454 | tail = readw(ofsAddr + RXwptr); | 2272 | tail = readw(ofsAddr + RXwptr); |
2455 | rx_mask = readw(ofsAddr + RX_mask); | 2273 | rx_mask = readw(ofsAddr + RX_mask); |
@@ -2504,7 +2322,7 @@ int MoxaPortReadData(int port, struct tty_struct *tty) | |||
2504 | } | 2322 | } |
2505 | if ((readb(ofsAddr + FlagStat) & Xoff_state) && (remain < LowWater)) { | 2323 | if ((readb(ofsAddr + FlagStat) & Xoff_state) && (remain < LowWater)) { |
2506 | moxaLowWaterChk = 1; | 2324 | moxaLowWaterChk = 1; |
2507 | moxaLowChkFlag[port] = 1; | 2325 | moxa_ports[port].lowChkFlag = 1; |
2508 | } | 2326 | } |
2509 | return (total); | 2327 | return (total); |
2510 | } | 2328 | } |
@@ -2516,7 +2334,7 @@ int MoxaPortTxQueue(int port) | |||
2516 | ushort rptr, wptr, mask; | 2334 | ushort rptr, wptr, mask; |
2517 | int len; | 2335 | int len; |
2518 | 2336 | ||
2519 | ofsAddr = moxaTableAddr[port]; | 2337 | ofsAddr = moxa_ports[port].tableAddr; |
2520 | rptr = readw(ofsAddr + TXrptr); | 2338 | rptr = readw(ofsAddr + TXrptr); |
2521 | wptr = readw(ofsAddr + TXwptr); | 2339 | wptr = readw(ofsAddr + TXwptr); |
2522 | mask = readw(ofsAddr + TX_mask); | 2340 | mask = readw(ofsAddr + TX_mask); |
@@ -2530,7 +2348,7 @@ int MoxaPortTxFree(int port) | |||
2530 | ushort rptr, wptr, mask; | 2348 | ushort rptr, wptr, mask; |
2531 | int len; | 2349 | int len; |
2532 | 2350 | ||
2533 | ofsAddr = moxaTableAddr[port]; | 2351 | ofsAddr = moxa_ports[port].tableAddr; |
2534 | rptr = readw(ofsAddr + TXrptr); | 2352 | rptr = readw(ofsAddr + TXrptr); |
2535 | wptr = readw(ofsAddr + TXwptr); | 2353 | wptr = readw(ofsAddr + TXwptr); |
2536 | mask = readw(ofsAddr + TX_mask); | 2354 | mask = readw(ofsAddr + TX_mask); |
@@ -2544,7 +2362,7 @@ int MoxaPortRxQueue(int port) | |||
2544 | ushort rptr, wptr, mask; | 2362 | ushort rptr, wptr, mask; |
2545 | int len; | 2363 | int len; |
2546 | 2364 | ||
2547 | ofsAddr = moxaTableAddr[port]; | 2365 | ofsAddr = moxa_ports[port].tableAddr; |
2548 | rptr = readw(ofsAddr + RXrptr); | 2366 | rptr = readw(ofsAddr + RXrptr); |
2549 | wptr = readw(ofsAddr + RXwptr); | 2367 | wptr = readw(ofsAddr + RXwptr); |
2550 | mask = readw(ofsAddr + RX_mask); | 2368 | mask = readw(ofsAddr + RX_mask); |
@@ -2557,7 +2375,7 @@ void MoxaPortTxDisable(int port) | |||
2557 | { | 2375 | { |
2558 | void __iomem *ofsAddr; | 2376 | void __iomem *ofsAddr; |
2559 | 2377 | ||
2560 | ofsAddr = moxaTableAddr[port]; | 2378 | ofsAddr = moxa_ports[port].tableAddr; |
2561 | moxafunc(ofsAddr, FC_SetXoffState, Magic_code); | 2379 | moxafunc(ofsAddr, FC_SetXoffState, Magic_code); |
2562 | } | 2380 | } |
2563 | 2381 | ||
@@ -2565,7 +2383,7 @@ void MoxaPortTxEnable(int port) | |||
2565 | { | 2383 | { |
2566 | void __iomem *ofsAddr; | 2384 | void __iomem *ofsAddr; |
2567 | 2385 | ||
2568 | ofsAddr = moxaTableAddr[port]; | 2386 | ofsAddr = moxa_ports[port].tableAddr; |
2569 | moxafunc(ofsAddr, FC_SetXonState, Magic_code); | 2387 | moxafunc(ofsAddr, FC_SetXonState, Magic_code); |
2570 | } | 2388 | } |
2571 | 2389 | ||
@@ -2573,8 +2391,8 @@ void MoxaPortTxEnable(int port) | |||
2573 | int MoxaPortResetBrkCnt(int port) | 2391 | int MoxaPortResetBrkCnt(int port) |
2574 | { | 2392 | { |
2575 | ushort cnt; | 2393 | ushort cnt; |
2576 | cnt = moxaBreakCnt[port]; | 2394 | cnt = moxa_ports[port].breakCnt; |
2577 | moxaBreakCnt[port] = 0; | 2395 | moxa_ports[port].breakCnt = 0; |
2578 | return (cnt); | 2396 | return (cnt); |
2579 | } | 2397 | } |
2580 | 2398 | ||
@@ -2583,7 +2401,7 @@ void MoxaPortSendBreak(int port, int ms100) | |||
2583 | { | 2401 | { |
2584 | void __iomem *ofsAddr; | 2402 | void __iomem *ofsAddr; |
2585 | 2403 | ||
2586 | ofsAddr = moxaTableAddr[port]; | 2404 | ofsAddr = moxa_ports[port].tableAddr; |
2587 | if (ms100) { | 2405 | if (ms100) { |
2588 | moxafunc(ofsAddr, FC_SendBreak, Magic_code); | 2406 | moxafunc(ofsAddr, FC_SendBreak, Magic_code); |
2589 | moxadelay(ms100 * (HZ / 10)); | 2407 | moxadelay(ms100 * (HZ / 10)); |
@@ -2594,7 +2412,7 @@ void MoxaPortSendBreak(int port, int ms100) | |||
2594 | moxafunc(ofsAddr, FC_StopBreak, Magic_code); | 2412 | moxafunc(ofsAddr, FC_StopBreak, Magic_code); |
2595 | } | 2413 | } |
2596 | 2414 | ||
2597 | static int moxa_get_serial_info(struct moxa_str *info, | 2415 | static int moxa_get_serial_info(struct moxa_port *info, |
2598 | struct serial_struct __user *retinfo) | 2416 | struct serial_struct __user *retinfo) |
2599 | { | 2417 | { |
2600 | struct serial_struct tmp; | 2418 | struct serial_struct tmp; |
@@ -2616,7 +2434,7 @@ static int moxa_get_serial_info(struct moxa_str *info, | |||
2616 | } | 2434 | } |
2617 | 2435 | ||
2618 | 2436 | ||
2619 | static int moxa_set_serial_info(struct moxa_str *info, | 2437 | static int moxa_set_serial_info(struct moxa_port *info, |
2620 | struct serial_struct __user *new_info) | 2438 | struct serial_struct __user *new_info) |
2621 | { | 2439 | { |
2622 | struct serial_struct new_serial; | 2440 | struct serial_struct new_serial; |
@@ -2713,7 +2531,7 @@ static int moxaloadbios(int cardno, unsigned char __user *tmp, int len) | |||
2713 | 2531 | ||
2714 | if(copy_from_user(moxaBuff, tmp, len)) | 2532 | if(copy_from_user(moxaBuff, tmp, len)) |
2715 | return -EFAULT; | 2533 | return -EFAULT; |
2716 | baseAddr = moxaBaseAddr[cardno]; | 2534 | baseAddr = moxa_boards[cardno].basemem; |
2717 | writeb(HW_reset, baseAddr + Control_reg); /* reset */ | 2535 | writeb(HW_reset, baseAddr + Control_reg); /* reset */ |
2718 | moxadelay(1); /* delay 10 ms */ | 2536 | moxadelay(1); /* delay 10 ms */ |
2719 | for (i = 0; i < 4096; i++) | 2537 | for (i = 0; i < 4096; i++) |
@@ -2729,7 +2547,7 @@ static int moxafindcard(int cardno) | |||
2729 | void __iomem *baseAddr; | 2547 | void __iomem *baseAddr; |
2730 | ushort tmp; | 2548 | ushort tmp; |
2731 | 2549 | ||
2732 | baseAddr = moxaBaseAddr[cardno]; | 2550 | baseAddr = moxa_boards[cardno].basemem; |
2733 | switch (moxa_boards[cardno].boardType) { | 2551 | switch (moxa_boards[cardno].boardType) { |
2734 | case MOXA_BOARD_C218_ISA: | 2552 | case MOXA_BOARD_C218_ISA: |
2735 | case MOXA_BOARD_C218_PCI: | 2553 | case MOXA_BOARD_C218_PCI: |
@@ -2762,7 +2580,7 @@ static int moxaload320b(int cardno, unsigned char __user *tmp, int len) | |||
2762 | return -EINVAL; | 2580 | return -EINVAL; |
2763 | if(copy_from_user(moxaBuff, tmp, len)) | 2581 | if(copy_from_user(moxaBuff, tmp, len)) |
2764 | return -EFAULT; | 2582 | return -EFAULT; |
2765 | baseAddr = moxaBaseAddr[cardno]; | 2583 | baseAddr = moxa_boards[cardno].basemem; |
2766 | writew(len - 7168 - 2, baseAddr + C320bapi_len); | 2584 | writew(len - 7168 - 2, baseAddr + C320bapi_len); |
2767 | writeb(1, baseAddr + Control_reg); /* Select Page 1 */ | 2585 | writeb(1, baseAddr + Control_reg); /* Select Page 1 */ |
2768 | for (i = 0; i < 7168; i++) | 2586 | for (i = 0; i < 7168; i++) |
@@ -2780,7 +2598,7 @@ static int moxaloadcode(int cardno, unsigned char __user *tmp, int len) | |||
2780 | 2598 | ||
2781 | if(copy_from_user(moxaBuff, tmp, len)) | 2599 | if(copy_from_user(moxaBuff, tmp, len)) |
2782 | return -EFAULT; | 2600 | return -EFAULT; |
2783 | baseAddr = moxaBaseAddr[cardno]; | 2601 | baseAddr = moxa_boards[cardno].basemem; |
2784 | switch (moxa_boards[cardno].boardType) { | 2602 | switch (moxa_boards[cardno].boardType) { |
2785 | case MOXA_BOARD_C218_ISA: | 2603 | case MOXA_BOARD_C218_ISA: |
2786 | case MOXA_BOARD_C218_PCI: | 2604 | case MOXA_BOARD_C218_PCI: |
@@ -2790,11 +2608,13 @@ static int moxaloadcode(int cardno, unsigned char __user *tmp, int len) | |||
2790 | return (retval); | 2608 | return (retval); |
2791 | port = cardno * MAX_PORTS_PER_BOARD; | 2609 | port = cardno * MAX_PORTS_PER_BOARD; |
2792 | for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) { | 2610 | for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) { |
2793 | moxaChkPort[port] = 1; | 2611 | struct moxa_port *p = &moxa_ports[port]; |
2794 | moxaCurBaud[port] = 9600L; | 2612 | |
2795 | moxaDCDState[port] = 0; | 2613 | p->chkPort = 1; |
2796 | moxaTableAddr[port] = baseAddr + Extern_table + Extern_size * i; | 2614 | p->curBaud = 9600L; |
2797 | ofsAddr = moxaTableAddr[port]; | 2615 | p->DCDState = 0; |
2616 | p->tableAddr = baseAddr + Extern_table + Extern_size * i; | ||
2617 | ofsAddr = p->tableAddr; | ||
2798 | writew(C218rx_mask, ofsAddr + RX_mask); | 2618 | writew(C218rx_mask, ofsAddr + RX_mask); |
2799 | writew(C218tx_mask, ofsAddr + TX_mask); | 2619 | writew(C218tx_mask, ofsAddr + TX_mask); |
2800 | writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb); | 2620 | writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb); |
@@ -2812,11 +2632,13 @@ static int moxaloadcode(int cardno, unsigned char __user *tmp, int len) | |||
2812 | return (retval); | 2632 | return (retval); |
2813 | port = cardno * MAX_PORTS_PER_BOARD; | 2633 | port = cardno * MAX_PORTS_PER_BOARD; |
2814 | for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) { | 2634 | for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) { |
2815 | moxaChkPort[port] = 1; | 2635 | struct moxa_port *p = &moxa_ports[port]; |
2816 | moxaCurBaud[port] = 9600L; | 2636 | |
2817 | moxaDCDState[port] = 0; | 2637 | p->chkPort = 1; |
2818 | moxaTableAddr[port] = baseAddr + Extern_table + Extern_size * i; | 2638 | p->curBaud = 9600L; |
2819 | ofsAddr = moxaTableAddr[port]; | 2639 | p->DCDState = 0; |
2640 | p->tableAddr = baseAddr + Extern_table + Extern_size * i; | ||
2641 | ofsAddr = p->tableAddr; | ||
2820 | if (moxa_boards[cardno].numPorts == 8) { | 2642 | if (moxa_boards[cardno].numPorts == 8) { |
2821 | writew(C320p8rx_mask, ofsAddr + RX_mask); | 2643 | writew(C320p8rx_mask, ofsAddr + RX_mask); |
2822 | writew(C320p8tx_mask, ofsAddr + TX_mask); | 2644 | writew(C320p8tx_mask, ofsAddr + TX_mask); |
@@ -2852,7 +2674,7 @@ static int moxaloadcode(int cardno, unsigned char __user *tmp, int len) | |||
2852 | } | 2674 | } |
2853 | break; | 2675 | break; |
2854 | } | 2676 | } |
2855 | loadstat[cardno] = 1; | 2677 | moxa_boards[cardno].loadstat = 1; |
2856 | return (0); | 2678 | return (0); |
2857 | } | 2679 | } |
2858 | 2680 | ||
@@ -2926,9 +2748,9 @@ static int moxaloadc218(int cardno, void __iomem *baseAddr, int len) | |||
2926 | return (-1); | 2748 | return (-1); |
2927 | } | 2749 | } |
2928 | moxaCard = 1; | 2750 | moxaCard = 1; |
2929 | moxaIntNdx[cardno] = baseAddr + IRQindex; | 2751 | moxa_boards[cardno].intNdx = baseAddr + IRQindex; |
2930 | moxaIntPend[cardno] = baseAddr + IRQpending; | 2752 | moxa_boards[cardno].intPend = baseAddr + IRQpending; |
2931 | moxaIntTable[cardno] = baseAddr + IRQtable; | 2753 | moxa_boards[cardno].intTable = baseAddr + IRQtable; |
2932 | return (0); | 2754 | return (0); |
2933 | } | 2755 | } |
2934 | 2756 | ||
@@ -3021,25 +2843,15 @@ static int moxaloadc320(int cardno, void __iomem *baseAddr, int len, int *numPor | |||
3021 | if (readw(baseAddr + Magic_no) != Magic_code) | 2843 | if (readw(baseAddr + Magic_no) != Magic_code) |
3022 | return (-102); | 2844 | return (-102); |
3023 | moxaCard = 1; | 2845 | moxaCard = 1; |
3024 | moxaIntNdx[cardno] = baseAddr + IRQindex; | 2846 | moxa_boards[cardno].intNdx = baseAddr + IRQindex; |
3025 | moxaIntPend[cardno] = baseAddr + IRQpending; | 2847 | moxa_boards[cardno].intPend = baseAddr + IRQpending; |
3026 | moxaIntTable[cardno] = baseAddr + IRQtable; | 2848 | moxa_boards[cardno].intTable = baseAddr + IRQtable; |
3027 | return (0); | 2849 | return (0); |
3028 | } | 2850 | } |
3029 | 2851 | ||
3030 | #if 0 | ||
3031 | long MoxaPortGetCurBaud(int port) | ||
3032 | { | ||
3033 | |||
3034 | if (moxaChkPort[port] == 0) | ||
3035 | return (0); | ||
3036 | return (moxaCurBaud[port]); | ||
3037 | } | ||
3038 | #endif /* 0 */ | ||
3039 | |||
3040 | static void MoxaSetFifo(int port, int enable) | 2852 | static void MoxaSetFifo(int port, int enable) |
3041 | { | 2853 | { |
3042 | void __iomem *ofsAddr = moxaTableAddr[port]; | 2854 | void __iomem *ofsAddr = moxa_ports[port].tableAddr; |
3043 | 2855 | ||
3044 | if (!enable) { | 2856 | if (!enable) { |
3045 | moxafunc(ofsAddr, FC_SetRxFIFOTrig, 0); | 2857 | moxafunc(ofsAddr, FC_SetRxFIFOTrig, 0); |
@@ -3049,132 +2861,3 @@ static void MoxaSetFifo(int port, int enable) | |||
3049 | moxafunc(ofsAddr, FC_SetTxFIFOCnt, 16); | 2861 | moxafunc(ofsAddr, FC_SetTxFIFOCnt, 16); |
3050 | } | 2862 | } |
3051 | } | 2863 | } |
3052 | |||
3053 | #if 0 | ||
3054 | int MoxaPortSetMode(int port, int databits, int stopbits, int parity) | ||
3055 | { | ||
3056 | void __iomem *ofsAddr; | ||
3057 | int val; | ||
3058 | |||
3059 | val = 0; | ||
3060 | switch (databits) { | ||
3061 | case 5: | ||
3062 | val |= 0; | ||
3063 | break; | ||
3064 | case 6: | ||
3065 | val |= 1; | ||
3066 | break; | ||
3067 | case 7: | ||
3068 | val |= 2; | ||
3069 | break; | ||
3070 | case 8: | ||
3071 | val |= 3; | ||
3072 | break; | ||
3073 | default: | ||
3074 | return (-1); | ||
3075 | } | ||
3076 | switch (stopbits) { | ||
3077 | case 0: | ||
3078 | val |= 0; | ||
3079 | break; /* stop bits 1.5 */ | ||
3080 | case 1: | ||
3081 | val |= 0; | ||
3082 | break; | ||
3083 | case 2: | ||
3084 | val |= 4; | ||
3085 | break; | ||
3086 | default: | ||
3087 | return (-1); | ||
3088 | } | ||
3089 | switch (parity) { | ||
3090 | case 0: | ||
3091 | val |= 0x00; | ||
3092 | break; /* None */ | ||
3093 | case 1: | ||
3094 | val |= 0x08; | ||
3095 | break; /* Odd */ | ||
3096 | case 2: | ||
3097 | val |= 0x18; | ||
3098 | break; /* Even */ | ||
3099 | case 3: | ||
3100 | val |= 0x28; | ||
3101 | break; /* Mark */ | ||
3102 | case 4: | ||
3103 | val |= 0x38; | ||
3104 | break; /* Space */ | ||
3105 | default: | ||
3106 | return (-1); | ||
3107 | } | ||
3108 | ofsAddr = moxaTableAddr[port]; | ||
3109 | moxafunc(ofsAddr, FC_SetMode, val); | ||
3110 | return (0); | ||
3111 | } | ||
3112 | |||
3113 | int MoxaPortTxBufSize(int port) | ||
3114 | { | ||
3115 | void __iomem *ofsAddr; | ||
3116 | int size; | ||
3117 | |||
3118 | ofsAddr = moxaTableAddr[port]; | ||
3119 | size = readw(ofsAddr + TX_mask); | ||
3120 | return (size); | ||
3121 | } | ||
3122 | |||
3123 | int MoxaPortRxBufSize(int port) | ||
3124 | { | ||
3125 | void __iomem *ofsAddr; | ||
3126 | int size; | ||
3127 | |||
3128 | ofsAddr = moxaTableAddr[port]; | ||
3129 | size = readw(ofsAddr + RX_mask); | ||
3130 | return (size); | ||
3131 | } | ||
3132 | |||
3133 | int MoxaPortRxFree(int port) | ||
3134 | { | ||
3135 | void __iomem *ofsAddr; | ||
3136 | ushort rptr, wptr, mask; | ||
3137 | int len; | ||
3138 | |||
3139 | ofsAddr = moxaTableAddr[port]; | ||
3140 | rptr = readw(ofsAddr + RXrptr); | ||
3141 | wptr = readw(ofsAddr + RXwptr); | ||
3142 | mask = readw(ofsAddr + RX_mask); | ||
3143 | len = mask - ((wptr - rptr) & mask); | ||
3144 | return (len); | ||
3145 | } | ||
3146 | int MoxaPortGetBrkCnt(int port) | ||
3147 | { | ||
3148 | return (moxaBreakCnt[port]); | ||
3149 | } | ||
3150 | |||
3151 | void MoxaPortSetXonXoff(int port, int xonValue, int xoffValue) | ||
3152 | { | ||
3153 | void __iomem *ofsAddr; | ||
3154 | |||
3155 | ofsAddr = moxaTableAddr[port]; | ||
3156 | writew(xonValue, ofsAddr + FuncArg); | ||
3157 | writew(xoffValue, ofsAddr + FuncArg1); | ||
3158 | writew(FC_SetXonXoff, ofsAddr + FuncCode); | ||
3159 | wait_finish(ofsAddr); | ||
3160 | } | ||
3161 | |||
3162 | int MoxaPortIsTxHold(int port) | ||
3163 | { | ||
3164 | void __iomem *ofsAddr; | ||
3165 | int val; | ||
3166 | |||
3167 | ofsAddr = moxaTableAddr[port]; | ||
3168 | if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) || | ||
3169 | (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) { | ||
3170 | moxafunc(ofsAddr, FC_GetCCSR, 0); | ||
3171 | val = readw(ofsAddr + FuncArg); | ||
3172 | if (val & 0x04) | ||
3173 | return (1); | ||
3174 | } else { | ||
3175 | if (readw(ofsAddr + FlagStat) & Tx_flowOff) | ||
3176 | return (1); | ||
3177 | } | ||
3178 | return (0); | ||
3179 | } | ||
3180 | #endif | ||
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c index 235e89226112..7ac30612068b 100644 --- a/drivers/char/mspec.c +++ b/drivers/char/mspec.c | |||
@@ -291,7 +291,7 @@ uncached_mmap(struct file *file, struct vm_area_struct *vma) | |||
291 | return mspec_mmap(file, vma, MSPEC_UNCACHED); | 291 | return mspec_mmap(file, vma, MSPEC_UNCACHED); |
292 | } | 292 | } |
293 | 293 | ||
294 | static struct file_operations fetchop_fops = { | 294 | static const struct file_operations fetchop_fops = { |
295 | .owner = THIS_MODULE, | 295 | .owner = THIS_MODULE, |
296 | .mmap = fetchop_mmap | 296 | .mmap = fetchop_mmap |
297 | }; | 297 | }; |
@@ -302,7 +302,7 @@ static struct miscdevice fetchop_miscdev = { | |||
302 | .fops = &fetchop_fops | 302 | .fops = &fetchop_fops |
303 | }; | 303 | }; |
304 | 304 | ||
305 | static struct file_operations cached_fops = { | 305 | static const struct file_operations cached_fops = { |
306 | .owner = THIS_MODULE, | 306 | .owner = THIS_MODULE, |
307 | .mmap = cached_mmap | 307 | .mmap = cached_mmap |
308 | }; | 308 | }; |
@@ -313,7 +313,7 @@ static struct miscdevice cached_miscdev = { | |||
313 | .fops = &cached_fops | 313 | .fops = &cached_fops |
314 | }; | 314 | }; |
315 | 315 | ||
316 | static struct file_operations uncached_fops = { | 316 | static const struct file_operations uncached_fops = { |
317 | .owner = THIS_MODULE, | 317 | .owner = THIS_MODULE, |
318 | .mmap = uncached_mmap | 318 | .mmap = uncached_mmap |
319 | }; | 319 | }; |
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 83f604b19290..a61fb6da5d03 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -321,8 +321,6 @@ struct mxser_struct { | |||
321 | unsigned long event; | 321 | unsigned long event; |
322 | int count; /* # of fd on device */ | 322 | int count; /* # of fd on device */ |
323 | int blocked_open; /* # of blocked opens */ | 323 | int blocked_open; /* # of blocked opens */ |
324 | long session; /* Session of opening process */ | ||
325 | long pgrp; /* pgrp of opening process */ | ||
326 | unsigned char *xmit_buf; | 324 | unsigned char *xmit_buf; |
327 | int xmit_head; | 325 | int xmit_head; |
328 | int xmit_tail; | 326 | int xmit_tail; |
@@ -1001,15 +999,12 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) | |||
1001 | mxser_change_speed(info, NULL); | 999 | mxser_change_speed(info, NULL); |
1002 | } | 1000 | } |
1003 | 1001 | ||
1004 | info->session = process_session(current); | ||
1005 | info->pgrp = process_group(current); | ||
1006 | |||
1007 | /* | 1002 | /* |
1008 | status = mxser_get_msr(info->base, 0, info->port); | 1003 | status = mxser_get_msr(info->base, 0, info->port); |
1009 | mxser_check_modem_status(info, status); | 1004 | mxser_check_modem_status(info, status); |
1010 | */ | 1005 | */ |
1011 | 1006 | ||
1012 | /* unmark here for very high baud rate (ex. 921600 bps) used */ | 1007 | /* unmark here for very high baud rate (ex. 921600 bps) used */ |
1013 | tty->low_latency = 1; | 1008 | tty->low_latency = 1; |
1014 | return 0; | 1009 | return 0; |
1015 | } | 1010 | } |
@@ -1254,9 +1249,7 @@ static void mxser_flush_buffer(struct tty_struct *tty) | |||
1254 | spin_unlock_irqrestore(&info->slock, flags); | 1249 | spin_unlock_irqrestore(&info->slock, flags); |
1255 | /* above added by shinhay */ | 1250 | /* above added by shinhay */ |
1256 | 1251 | ||
1257 | wake_up_interruptible(&tty->write_wait); | 1252 | tty_wakeup(tty); |
1258 | if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) | ||
1259 | (tty->ldisc.write_wakeup) (tty); | ||
1260 | } | 1253 | } |
1261 | 1254 | ||
1262 | static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) | 1255 | static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) |
diff --git a/drivers/char/mxser.h b/drivers/char/mxser.h index 7e188a4d602a..9fe28497eae9 100644 --- a/drivers/char/mxser.h +++ b/drivers/char/mxser.h | |||
@@ -439,12 +439,4 @@ | |||
439 | 439 | ||
440 | #define READ_MOXA_MUST_GDL(baseio) inb((baseio)+MOXA_MUST_GDL_REGISTER) | 440 | #define READ_MOXA_MUST_GDL(baseio) inb((baseio)+MOXA_MUST_GDL_REGISTER) |
441 | 441 | ||
442 | |||
443 | #ifndef INIT_WORK | ||
444 | #define INIT_WORK(_work, _func, _data){ \ | ||
445 | _data->tqueue.routine = _func;\ | ||
446 | _data->tqueue.data = _data;\ | ||
447 | } | ||
448 | #endif | ||
449 | |||
450 | #endif | 442 | #endif |
diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c index 1bb030b3a51a..9af07e4999d5 100644 --- a/drivers/char/mxser_new.c +++ b/drivers/char/mxser_new.c | |||
@@ -49,22 +49,25 @@ | |||
49 | 49 | ||
50 | #include "mxser_new.h" | 50 | #include "mxser_new.h" |
51 | 51 | ||
52 | #define MXSER_VERSION "2.0" | 52 | #define MXSER_VERSION "2.0.1" /* 1.9.15 */ |
53 | #define MXSERMAJOR 174 | 53 | #define MXSERMAJOR 174 |
54 | #define MXSERCUMAJOR 175 | 54 | #define MXSERCUMAJOR 175 |
55 | 55 | ||
56 | #define MXSER_EVENT_TXLOW 1 | ||
57 | |||
58 | #define MXSER_BOARDS 4 /* Max. boards */ | 56 | #define MXSER_BOARDS 4 /* Max. boards */ |
59 | #define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */ | 57 | #define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */ |
60 | #define MXSER_PORTS (MXSER_BOARDS * MXSER_PORTS_PER_BOARD) | 58 | #define MXSER_PORTS (MXSER_BOARDS * MXSER_PORTS_PER_BOARD) |
61 | #define MXSER_ISR_PASS_LIMIT 99999L | 59 | #define MXSER_ISR_PASS_LIMIT 100 |
62 | 60 | ||
63 | #define MXSER_ERR_IOADDR -1 | 61 | #define MXSER_ERR_IOADDR -1 |
64 | #define MXSER_ERR_IRQ -2 | 62 | #define MXSER_ERR_IRQ -2 |
65 | #define MXSER_ERR_IRQ_CONFLIT -3 | 63 | #define MXSER_ERR_IRQ_CONFLIT -3 |
66 | #define MXSER_ERR_VECTOR -4 | 64 | #define MXSER_ERR_VECTOR -4 |
67 | 65 | ||
66 | /*CheckIsMoxaMust return value*/ | ||
67 | #define MOXA_OTHER_UART 0x00 | ||
68 | #define MOXA_MUST_MU150_HWID 0x01 | ||
69 | #define MOXA_MUST_MU860_HWID 0x02 | ||
70 | |||
68 | #define WAKEUP_CHARS 256 | 71 | #define WAKEUP_CHARS 256 |
69 | 72 | ||
70 | #define UART_MCR_AFE 0x20 | 73 | #define UART_MCR_AFE 0x20 |
@@ -176,6 +179,18 @@ static struct pci_device_id mxser_pcibrds[] = { | |||
176 | }; | 179 | }; |
177 | MODULE_DEVICE_TABLE(pci, mxser_pcibrds); | 180 | MODULE_DEVICE_TABLE(pci, mxser_pcibrds); |
178 | 181 | ||
182 | static int mxvar_baud_table[] = { | ||
183 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, | ||
184 | 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 | ||
185 | }; | ||
186 | static unsigned int mxvar_baud_table1[] = { | ||
187 | 0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400, | ||
188 | B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800, B921600 | ||
189 | }; | ||
190 | #define BAUD_TABLE_NO ARRAY_SIZE(mxvar_baud_table) | ||
191 | |||
192 | #define B_SPEC B2000000 | ||
193 | |||
179 | static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 }; | 194 | static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 }; |
180 | static int ttymajor = MXSERMAJOR; | 195 | static int ttymajor = MXSERMAJOR; |
181 | static int calloutmajor = MXSERCUMAJOR; | 196 | static int calloutmajor = MXSERCUMAJOR; |
@@ -237,8 +252,7 @@ struct mxser_port { | |||
237 | long realbaud; | 252 | long realbaud; |
238 | int type; /* UART type */ | 253 | int type; /* UART type */ |
239 | int flags; /* defined in tty.h */ | 254 | int flags; /* defined in tty.h */ |
240 | long session; /* Session of opening process */ | 255 | int speed; |
241 | long pgrp; /* pgrp of opening process */ | ||
242 | 256 | ||
243 | int x_char; /* xon/xoff character */ | 257 | int x_char; /* xon/xoff character */ |
244 | int IER; /* Interrupt Enable Register */ | 258 | int IER; /* Interrupt Enable Register */ |
@@ -267,14 +281,11 @@ struct mxser_port { | |||
267 | int xmit_cnt; | 281 | int xmit_cnt; |
268 | 282 | ||
269 | struct ktermios normal_termios; | 283 | struct ktermios normal_termios; |
270 | struct ktermios callout_termios; | ||
271 | 284 | ||
272 | struct mxser_mon mon_data; | 285 | struct mxser_mon mon_data; |
273 | 286 | ||
274 | spinlock_t slock; | 287 | spinlock_t slock; |
275 | struct work_struct tqueue; | ||
276 | wait_queue_head_t open_wait; | 288 | wait_queue_head_t open_wait; |
277 | wait_queue_head_t close_wait; | ||
278 | wait_queue_head_t delta_msr_wait; | 289 | wait_queue_head_t delta_msr_wait; |
279 | }; | 290 | }; |
280 | 291 | ||
@@ -313,10 +324,9 @@ static int mxvar_diagflag; | |||
313 | static unsigned char mxser_msr[MXSER_PORTS + 1]; | 324 | static unsigned char mxser_msr[MXSER_PORTS + 1]; |
314 | static struct mxser_mon_ext mon_data_ext; | 325 | static struct mxser_mon_ext mon_data_ext; |
315 | static int mxser_set_baud_method[MXSER_PORTS + 1]; | 326 | static int mxser_set_baud_method[MXSER_PORTS + 1]; |
316 | static spinlock_t gm_lock; | ||
317 | 327 | ||
318 | #ifdef CONFIG_PCI | 328 | #ifdef CONFIG_PCI |
319 | static int CheckIsMoxaMust(int io) | 329 | static int __devinit CheckIsMoxaMust(int io) |
320 | { | 330 | { |
321 | u8 oldmcr, hwid; | 331 | u8 oldmcr, hwid; |
322 | int i; | 332 | int i; |
@@ -360,15 +370,6 @@ static void process_txrx_fifo(struct mxser_port *info) | |||
360 | } | 370 | } |
361 | } | 371 | } |
362 | 372 | ||
363 | static void mxser_do_softint(struct work_struct *work) | ||
364 | { | ||
365 | struct mxser_port *info = container_of(work, struct mxser_port, tqueue); | ||
366 | struct tty_struct *tty = info->tty; | ||
367 | |||
368 | if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event)) | ||
369 | tty_wakeup(tty); | ||
370 | } | ||
371 | |||
372 | static unsigned char mxser_get_msr(int baseaddr, int mode, int port) | 373 | static unsigned char mxser_get_msr(int baseaddr, int mode, int port) |
373 | { | 374 | { |
374 | unsigned char status = 0; | 375 | unsigned char status = 0; |
@@ -456,10 +457,10 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, | |||
456 | 457 | ||
457 | static int mxser_set_baud(struct mxser_port *info, long newspd) | 458 | static int mxser_set_baud(struct mxser_port *info, long newspd) |
458 | { | 459 | { |
460 | unsigned int i; | ||
459 | int quot = 0; | 461 | int quot = 0; |
460 | unsigned char cval; | 462 | unsigned char cval; |
461 | int ret = 0; | 463 | int ret = 0; |
462 | unsigned long flags; | ||
463 | 464 | ||
464 | if (!info->tty || !info->tty->termios) | 465 | if (!info->tty || !info->tty->termios) |
465 | return ret; | 466 | return ret; |
@@ -471,29 +472,34 @@ static int mxser_set_baud(struct mxser_port *info, long newspd) | |||
471 | return 0; | 472 | return 0; |
472 | 473 | ||
473 | info->realbaud = newspd; | 474 | info->realbaud = newspd; |
474 | if (newspd == 134) { | 475 | for (i = 0; i < BAUD_TABLE_NO; i++) |
475 | quot = (2 * info->baud_base / 269); | 476 | if (newspd == mxvar_baud_table[i]) |
476 | } else if (newspd) { | 477 | break; |
477 | quot = info->baud_base / newspd; | 478 | if (i == BAUD_TABLE_NO) { |
478 | if (quot == 0) | 479 | quot = info->baud_base / info->speed; |
479 | quot = 1; | 480 | if (info->speed <= 0 || info->speed > info->max_baud) |
481 | quot = 0; | ||
480 | } else { | 482 | } else { |
481 | quot = 0; | 483 | if (newspd == 134) { |
484 | quot = (2 * info->baud_base / 269); | ||
485 | } else if (newspd) { | ||
486 | quot = info->baud_base / newspd; | ||
487 | if (quot == 0) | ||
488 | quot = 1; | ||
489 | } else { | ||
490 | quot = 0; | ||
491 | } | ||
482 | } | 492 | } |
483 | 493 | ||
484 | info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base); | 494 | info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base); |
485 | info->timeout += HZ / 50; /* Add .02 seconds of slop */ | 495 | info->timeout += HZ / 50; /* Add .02 seconds of slop */ |
486 | 496 | ||
487 | if (quot) { | 497 | if (quot) { |
488 | spin_lock_irqsave(&info->slock, flags); | ||
489 | info->MCR |= UART_MCR_DTR; | 498 | info->MCR |= UART_MCR_DTR; |
490 | outb(info->MCR, info->ioaddr + UART_MCR); | 499 | outb(info->MCR, info->ioaddr + UART_MCR); |
491 | spin_unlock_irqrestore(&info->slock, flags); | ||
492 | } else { | 500 | } else { |
493 | spin_lock_irqsave(&info->slock, flags); | ||
494 | info->MCR &= ~UART_MCR_DTR; | 501 | info->MCR &= ~UART_MCR_DTR; |
495 | outb(info->MCR, info->ioaddr + UART_MCR); | 502 | outb(info->MCR, info->ioaddr + UART_MCR); |
496 | spin_unlock_irqrestore(&info->slock, flags); | ||
497 | return ret; | 503 | return ret; |
498 | } | 504 | } |
499 | 505 | ||
@@ -505,6 +511,18 @@ static int mxser_set_baud(struct mxser_port *info, long newspd) | |||
505 | outb(quot >> 8, info->ioaddr + UART_DLM); /* MS of divisor */ | 511 | outb(quot >> 8, info->ioaddr + UART_DLM); /* MS of divisor */ |
506 | outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */ | 512 | outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */ |
507 | 513 | ||
514 | if (i == BAUD_TABLE_NO) { | ||
515 | quot = info->baud_base % info->speed; | ||
516 | quot *= 8; | ||
517 | if ((quot % info->speed) > (info->speed / 2)) { | ||
518 | quot /= info->speed; | ||
519 | quot++; | ||
520 | } else { | ||
521 | quot /= info->speed; | ||
522 | } | ||
523 | SET_MOXA_MUST_ENUM_VALUE(info->ioaddr, quot); | ||
524 | } else | ||
525 | SET_MOXA_MUST_ENUM_VALUE(info->ioaddr, 0); | ||
508 | 526 | ||
509 | return ret; | 527 | return ret; |
510 | } | 528 | } |
@@ -520,7 +538,6 @@ static int mxser_change_speed(struct mxser_port *info, | |||
520 | int ret = 0; | 538 | int ret = 0; |
521 | unsigned char status; | 539 | unsigned char status; |
522 | long baud; | 540 | long baud; |
523 | unsigned long flags; | ||
524 | 541 | ||
525 | if (!info->tty || !info->tty->termios) | 542 | if (!info->tty || !info->tty->termios) |
526 | return ret; | 543 | return ret; |
@@ -529,7 +546,10 @@ static int mxser_change_speed(struct mxser_port *info, | |||
529 | return ret; | 546 | return ret; |
530 | 547 | ||
531 | if (mxser_set_baud_method[info->tty->index] == 0) { | 548 | if (mxser_set_baud_method[info->tty->index] == 0) { |
532 | baud = tty_get_baud_rate(info->tty); | 549 | if ((cflag & CBAUD) == B_SPEC) |
550 | baud = info->speed; | ||
551 | else | ||
552 | baud = tty_get_baud_rate(info->tty); | ||
533 | mxser_set_baud(info, baud); | 553 | mxser_set_baud(info, baud); |
534 | } | 554 | } |
535 | 555 | ||
@@ -612,8 +632,8 @@ static int mxser_change_speed(struct mxser_port *info, | |||
612 | outb(info->IER, info->ioaddr + | 632 | outb(info->IER, info->ioaddr + |
613 | UART_IER); | 633 | UART_IER); |
614 | } | 634 | } |
615 | set_bit(MXSER_EVENT_TXLOW, &info->event); | 635 | tty_wakeup(info->tty); |
616 | schedule_work(&info->tqueue); } | 636 | } |
617 | } else { | 637 | } else { |
618 | if (!(status & UART_MSR_CTS)) { | 638 | if (!(status & UART_MSR_CTS)) { |
619 | info->tty->hw_stopped = 1; | 639 | info->tty->hw_stopped = 1; |
@@ -668,7 +688,6 @@ static int mxser_change_speed(struct mxser_port *info, | |||
668 | } | 688 | } |
669 | } | 689 | } |
670 | if (info->board->chip_flag) { | 690 | if (info->board->chip_flag) { |
671 | spin_lock_irqsave(&info->slock, flags); | ||
672 | SET_MOXA_MUST_XON1_VALUE(info->ioaddr, START_CHAR(info->tty)); | 691 | SET_MOXA_MUST_XON1_VALUE(info->ioaddr, START_CHAR(info->tty)); |
673 | SET_MOXA_MUST_XOFF1_VALUE(info->ioaddr, STOP_CHAR(info->tty)); | 692 | SET_MOXA_MUST_XOFF1_VALUE(info->ioaddr, STOP_CHAR(info->tty)); |
674 | if (I_IXON(info->tty)) { | 693 | if (I_IXON(info->tty)) { |
@@ -681,7 +700,6 @@ static int mxser_change_speed(struct mxser_port *info, | |||
681 | } else { | 700 | } else { |
682 | DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr); | 701 | DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr); |
683 | } | 702 | } |
684 | spin_unlock_irqrestore(&info->slock, flags); | ||
685 | } | 703 | } |
686 | 704 | ||
687 | 705 | ||
@@ -708,7 +726,6 @@ static void mxser_check_modem_status(struct mxser_port *port, int status) | |||
708 | if ((port->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { | 726 | if ((port->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { |
709 | if (status & UART_MSR_DCD) | 727 | if (status & UART_MSR_DCD) |
710 | wake_up_interruptible(&port->open_wait); | 728 | wake_up_interruptible(&port->open_wait); |
711 | schedule_work(&port->tqueue); | ||
712 | } | 729 | } |
713 | 730 | ||
714 | if (port->flags & ASYNC_CTS_FLOW) { | 731 | if (port->flags & ASYNC_CTS_FLOW) { |
@@ -724,8 +741,7 @@ static void mxser_check_modem_status(struct mxser_port *port, int status) | |||
724 | outb(port->IER, port->ioaddr + | 741 | outb(port->IER, port->ioaddr + |
725 | UART_IER); | 742 | UART_IER); |
726 | } | 743 | } |
727 | set_bit(MXSER_EVENT_TXLOW, &port->event); | 744 | tty_wakeup(port->tty); |
728 | schedule_work(&port->tqueue); | ||
729 | } | 745 | } |
730 | } else { | 746 | } else { |
731 | if (!(status & UART_MSR_CTS)) { | 747 | if (!(status & UART_MSR_CTS)) { |
@@ -836,10 +852,10 @@ static int mxser_startup(struct mxser_port *info) | |||
836 | /* | 852 | /* |
837 | * and set the speed of the serial port | 853 | * and set the speed of the serial port |
838 | */ | 854 | */ |
839 | spin_unlock_irqrestore(&info->slock, flags); | ||
840 | mxser_change_speed(info, NULL); | 855 | mxser_change_speed(info, NULL); |
841 | |||
842 | info->flags |= ASYNC_INITIALIZED; | 856 | info->flags |= ASYNC_INITIALIZED; |
857 | spin_unlock_irqrestore(&info->slock, flags); | ||
858 | |||
843 | return 0; | 859 | return 0; |
844 | } | 860 | } |
845 | 861 | ||
@@ -909,11 +925,9 @@ static void mxser_shutdown(struct mxser_port *info) | |||
909 | static int mxser_open(struct tty_struct *tty, struct file *filp) | 925 | static int mxser_open(struct tty_struct *tty, struct file *filp) |
910 | { | 926 | { |
911 | struct mxser_port *info; | 927 | struct mxser_port *info; |
928 | unsigned long flags; | ||
912 | int retval, line; | 929 | int retval, line; |
913 | 930 | ||
914 | /* initialize driver_data in case something fails */ | ||
915 | tty->driver_data = NULL; | ||
916 | |||
917 | line = tty->index; | 931 | line = tty->index; |
918 | if (line == MXSER_PORTS) | 932 | if (line == MXSER_PORTS) |
919 | return 0; | 933 | return 0; |
@@ -928,7 +942,9 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) | |||
928 | /* | 942 | /* |
929 | * Start up serial port | 943 | * Start up serial port |
930 | */ | 944 | */ |
945 | spin_lock_irqsave(&info->slock, flags); | ||
931 | info->count++; | 946 | info->count++; |
947 | spin_unlock_irqrestore(&info->slock, flags); | ||
932 | retval = mxser_startup(info); | 948 | retval = mxser_startup(info); |
933 | if (retval) | 949 | if (retval) |
934 | return retval; | 950 | return retval; |
@@ -937,17 +953,6 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) | |||
937 | if (retval) | 953 | if (retval) |
938 | return retval; | 954 | return retval; |
939 | 955 | ||
940 | if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) { | ||
941 | if (tty->driver->subtype == SERIAL_TYPE_NORMAL) | ||
942 | *tty->termios = info->normal_termios; | ||
943 | else | ||
944 | *tty->termios = info->callout_termios; | ||
945 | mxser_change_speed(info, NULL); | ||
946 | } | ||
947 | |||
948 | info->session = process_session(current); | ||
949 | info->pgrp = process_group(current); | ||
950 | |||
951 | /* unmark here for very high baud rate (ex. 921600 bps) used */ | 956 | /* unmark here for very high baud rate (ex. 921600 bps) used */ |
952 | tty->low_latency = 1; | 957 | tty->low_latency = 1; |
953 | return 0; | 958 | return 0; |
@@ -1054,8 +1059,6 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) | |||
1054 | } | 1059 | } |
1055 | 1060 | ||
1056 | info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); | 1061 | info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); |
1057 | wake_up_interruptible(&info->close_wait); | ||
1058 | |||
1059 | } | 1062 | } |
1060 | 1063 | ||
1061 | static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count) | 1064 | static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count) |
@@ -1222,6 +1225,7 @@ static int mxser_set_serial_info(struct mxser_port *info, | |||
1222 | struct serial_struct __user *new_info) | 1225 | struct serial_struct __user *new_info) |
1223 | { | 1226 | { |
1224 | struct serial_struct new_serial; | 1227 | struct serial_struct new_serial; |
1228 | unsigned long sl_flags; | ||
1225 | unsigned int flags; | 1229 | unsigned int flags; |
1226 | int retval = 0; | 1230 | int retval = 0; |
1227 | 1231 | ||
@@ -1264,8 +1268,11 @@ static int mxser_set_serial_info(struct mxser_port *info, | |||
1264 | process_txrx_fifo(info); | 1268 | process_txrx_fifo(info); |
1265 | 1269 | ||
1266 | if (info->flags & ASYNC_INITIALIZED) { | 1270 | if (info->flags & ASYNC_INITIALIZED) { |
1267 | if (flags != (info->flags & ASYNC_SPD_MASK)) | 1271 | if (flags != (info->flags & ASYNC_SPD_MASK)) { |
1272 | spin_lock_irqsave(&info->slock, sl_flags); | ||
1268 | mxser_change_speed(info, NULL); | 1273 | mxser_change_speed(info, NULL); |
1274 | spin_unlock_irqrestore(&info->slock, sl_flags); | ||
1275 | } | ||
1269 | } else | 1276 | } else |
1270 | retval = mxser_startup(info); | 1277 | retval = mxser_startup(info); |
1271 | 1278 | ||
@@ -1373,11 +1380,10 @@ static int mxser_tiocmset(struct tty_struct *tty, struct file *file, | |||
1373 | return 0; | 1380 | return 0; |
1374 | } | 1381 | } |
1375 | 1382 | ||
1376 | static int mxser_program_mode(int port) | 1383 | static int __init mxser_program_mode(int port) |
1377 | { | 1384 | { |
1378 | int id, i, j, n; | 1385 | int id, i, j, n; |
1379 | 1386 | ||
1380 | spin_lock(&gm_lock); | ||
1381 | outb(0, port); | 1387 | outb(0, port); |
1382 | outb(0, port); | 1388 | outb(0, port); |
1383 | outb(0, port); | 1389 | outb(0, port); |
@@ -1385,7 +1391,6 @@ static int mxser_program_mode(int port) | |||
1385 | (void)inb(port); | 1391 | (void)inb(port); |
1386 | outb(0, port); | 1392 | outb(0, port); |
1387 | (void)inb(port); | 1393 | (void)inb(port); |
1388 | spin_unlock(&gm_lock); | ||
1389 | 1394 | ||
1390 | id = inb(port + 1) & 0x1F; | 1395 | id = inb(port + 1) & 0x1F; |
1391 | if ((id != C168_ASIC_ID) && | 1396 | if ((id != C168_ASIC_ID) && |
@@ -1410,7 +1415,7 @@ static int mxser_program_mode(int port) | |||
1410 | return id; | 1415 | return id; |
1411 | } | 1416 | } |
1412 | 1417 | ||
1413 | static void mxser_normal_mode(int port) | 1418 | static void __init mxser_normal_mode(int port) |
1414 | { | 1419 | { |
1415 | int i, n; | 1420 | int i, n; |
1416 | 1421 | ||
@@ -1443,7 +1448,7 @@ static void mxser_normal_mode(int port) | |||
1443 | #define EN0_PORT 0x010 /* Rcv missed frame error counter RD */ | 1448 | #define EN0_PORT 0x010 /* Rcv missed frame error counter RD */ |
1444 | #define ENC_PAGE0 0x000 /* Select page 0 of chip registers */ | 1449 | #define ENC_PAGE0 0x000 /* Select page 0 of chip registers */ |
1445 | #define ENC_PAGE3 0x0C0 /* Select page 3 of chip registers */ | 1450 | #define ENC_PAGE3 0x0C0 /* Select page 3 of chip registers */ |
1446 | static int mxser_read_register(int port, unsigned short *regs) | 1451 | static int __init mxser_read_register(int port, unsigned short *regs) |
1447 | { | 1452 | { |
1448 | int i, k, value, id; | 1453 | int i, k, value, id; |
1449 | unsigned int j; | 1454 | unsigned int j; |
@@ -1644,6 +1649,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1644 | struct serial_icounter_struct __user *p_cuser; | 1649 | struct serial_icounter_struct __user *p_cuser; |
1645 | unsigned long templ; | 1650 | unsigned long templ; |
1646 | unsigned long flags; | 1651 | unsigned long flags; |
1652 | unsigned int i; | ||
1647 | void __user *argp = (void __user *)arg; | 1653 | void __user *argp = (void __user *)arg; |
1648 | int retval; | 1654 | int retval; |
1649 | 1655 | ||
@@ -1682,6 +1688,36 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1682 | return 0; | 1688 | return 0; |
1683 | } | 1689 | } |
1684 | 1690 | ||
1691 | if (cmd == MOXA_SET_SPECIAL_BAUD_RATE) { | ||
1692 | int speed; | ||
1693 | |||
1694 | if (get_user(speed, (int __user *)argp)) | ||
1695 | return -EFAULT; | ||
1696 | if (speed <= 0 || speed > info->max_baud) | ||
1697 | return -EFAULT; | ||
1698 | if (!info->tty || !info->tty->termios || !info->ioaddr) | ||
1699 | return 0; | ||
1700 | info->tty->termios->c_cflag &= ~(CBAUD | CBAUDEX); | ||
1701 | for (i = 0; i < BAUD_TABLE_NO; i++) | ||
1702 | if (speed == mxvar_baud_table[i]) | ||
1703 | break; | ||
1704 | if (i == BAUD_TABLE_NO) { | ||
1705 | info->tty->termios->c_cflag |= B_SPEC; | ||
1706 | } else if (speed != 0) | ||
1707 | info->tty->termios->c_cflag |= mxvar_baud_table1[i]; | ||
1708 | |||
1709 | info->speed = speed; | ||
1710 | spin_lock_irqsave(&info->slock, flags); | ||
1711 | mxser_change_speed(info, NULL); | ||
1712 | spin_unlock_irqrestore(&info->slock, flags); | ||
1713 | |||
1714 | return 0; | ||
1715 | } else if (cmd == MOXA_GET_SPECIAL_BAUD_RATE) { | ||
1716 | if (copy_to_user(argp, &info->speed, sizeof(int))) | ||
1717 | return -EFAULT; | ||
1718 | return 0; | ||
1719 | } | ||
1720 | |||
1685 | if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT && | 1721 | if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT && |
1686 | test_bit(TTY_IO_ERROR, &tty->flags)) | 1722 | test_bit(TTY_IO_ERROR, &tty->flags)) |
1687 | return -EIO; | 1723 | return -EIO; |
@@ -1799,7 +1835,9 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1799 | long baud; | 1835 | long baud; |
1800 | if (get_user(baud, (long __user *)argp)) | 1836 | if (get_user(baud, (long __user *)argp)) |
1801 | return -EFAULT; | 1837 | return -EFAULT; |
1838 | spin_lock_irqsave(&info->slock, flags); | ||
1802 | mxser_set_baud(info, baud); | 1839 | mxser_set_baud(info, baud); |
1840 | spin_unlock_irqrestore(&info->slock, flags); | ||
1803 | return 0; | 1841 | return 0; |
1804 | } | 1842 | } |
1805 | case MOXA_ASPP_GETBAUD: | 1843 | case MOXA_ASPP_GETBAUD: |
@@ -1976,7 +2014,9 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi | |||
1976 | if ((tty->termios->c_cflag != old_termios->c_cflag) || | 2014 | if ((tty->termios->c_cflag != old_termios->c_cflag) || |
1977 | (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) { | 2015 | (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) { |
1978 | 2016 | ||
2017 | spin_lock_irqsave(&info->slock, flags); | ||
1979 | mxser_change_speed(info, old_termios); | 2018 | mxser_change_speed(info, old_termios); |
2019 | spin_unlock_irqrestore(&info->slock, flags); | ||
1980 | 2020 | ||
1981 | if ((old_termios->c_cflag & CRTSCTS) && | 2021 | if ((old_termios->c_cflag & CRTSCTS) && |
1982 | !(tty->termios->c_cflag & CRTSCTS)) { | 2022 | !(tty->termios->c_cflag & CRTSCTS)) { |
@@ -2066,7 +2106,7 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) | |||
2066 | /* | 2106 | /* |
2067 | * This routine is called by tty_hangup() when a hangup is signaled. | 2107 | * This routine is called by tty_hangup() when a hangup is signaled. |
2068 | */ | 2108 | */ |
2069 | void mxser_hangup(struct tty_struct *tty) | 2109 | static void mxser_hangup(struct tty_struct *tty) |
2070 | { | 2110 | { |
2071 | struct mxser_port *info = tty->driver_data; | 2111 | struct mxser_port *info = tty->driver_data; |
2072 | 2112 | ||
@@ -2105,9 +2145,6 @@ static void mxser_receive_chars(struct mxser_port *port, int *status) | |||
2105 | int cnt = 0; | 2145 | int cnt = 0; |
2106 | int recv_room; | 2146 | int recv_room; |
2107 | int max = 256; | 2147 | int max = 256; |
2108 | unsigned long flags; | ||
2109 | |||
2110 | spin_lock_irqsave(&port->slock, flags); | ||
2111 | 2148 | ||
2112 | recv_room = tty->receive_room; | 2149 | recv_room = tty->receive_room; |
2113 | if ((recv_room == 0) && (!port->ldisc_stop_rx)) | 2150 | if ((recv_room == 0) && (!port->ldisc_stop_rx)) |
@@ -2169,7 +2206,8 @@ intr_old: | |||
2169 | } else if (*status & UART_LSR_OE) { | 2206 | } else if (*status & UART_LSR_OE) { |
2170 | flag = TTY_OVERRUN; | 2207 | flag = TTY_OVERRUN; |
2171 | port->icount.overrun++; | 2208 | port->icount.overrun++; |
2172 | } | 2209 | } else |
2210 | flag = TTY_BREAK; | ||
2173 | } | 2211 | } |
2174 | tty_insert_flip_char(tty, ch, flag); | 2212 | tty_insert_flip_char(tty, ch, flag); |
2175 | cnt++; | 2213 | cnt++; |
@@ -2191,7 +2229,6 @@ end_intr: | |||
2191 | mxvar_log.rxcnt[port->tty->index] += cnt; | 2229 | mxvar_log.rxcnt[port->tty->index] += cnt; |
2192 | port->mon_data.rxcnt += cnt; | 2230 | port->mon_data.rxcnt += cnt; |
2193 | port->mon_data.up_rxcnt += cnt; | 2231 | port->mon_data.up_rxcnt += cnt; |
2194 | spin_unlock_irqrestore(&port->slock, flags); | ||
2195 | 2232 | ||
2196 | tty_flip_buffer_push(tty); | 2233 | tty_flip_buffer_push(tty); |
2197 | } | 2234 | } |
@@ -2199,9 +2236,6 @@ end_intr: | |||
2199 | static void mxser_transmit_chars(struct mxser_port *port) | 2236 | static void mxser_transmit_chars(struct mxser_port *port) |
2200 | { | 2237 | { |
2201 | int count, cnt; | 2238 | int count, cnt; |
2202 | unsigned long flags; | ||
2203 | |||
2204 | spin_lock_irqsave(&port->slock, flags); | ||
2205 | 2239 | ||
2206 | if (port->x_char) { | 2240 | if (port->x_char) { |
2207 | outb(port->x_char, port->ioaddr + UART_TX); | 2241 | outb(port->x_char, port->ioaddr + UART_TX); |
@@ -2210,11 +2244,11 @@ static void mxser_transmit_chars(struct mxser_port *port) | |||
2210 | port->mon_data.txcnt++; | 2244 | port->mon_data.txcnt++; |
2211 | port->mon_data.up_txcnt++; | 2245 | port->mon_data.up_txcnt++; |
2212 | port->icount.tx++; | 2246 | port->icount.tx++; |
2213 | goto unlock; | 2247 | return; |
2214 | } | 2248 | } |
2215 | 2249 | ||
2216 | if (port->xmit_buf == 0) | 2250 | if (port->xmit_buf == 0) |
2217 | goto unlock; | 2251 | return; |
2218 | 2252 | ||
2219 | if ((port->xmit_cnt <= 0) || port->tty->stopped || | 2253 | if ((port->xmit_cnt <= 0) || port->tty->stopped || |
2220 | (port->tty->hw_stopped && | 2254 | (port->tty->hw_stopped && |
@@ -2222,7 +2256,7 @@ static void mxser_transmit_chars(struct mxser_port *port) | |||
2222 | (!port->board->chip_flag))) { | 2256 | (!port->board->chip_flag))) { |
2223 | port->IER &= ~UART_IER_THRI; | 2257 | port->IER &= ~UART_IER_THRI; |
2224 | outb(port->IER, port->ioaddr + UART_IER); | 2258 | outb(port->IER, port->ioaddr + UART_IER); |
2225 | goto unlock; | 2259 | return; |
2226 | } | 2260 | } |
2227 | 2261 | ||
2228 | cnt = port->xmit_cnt; | 2262 | cnt = port->xmit_cnt; |
@@ -2240,16 +2274,13 @@ static void mxser_transmit_chars(struct mxser_port *port) | |||
2240 | port->mon_data.up_txcnt += (cnt - port->xmit_cnt); | 2274 | port->mon_data.up_txcnt += (cnt - port->xmit_cnt); |
2241 | port->icount.tx += (cnt - port->xmit_cnt); | 2275 | port->icount.tx += (cnt - port->xmit_cnt); |
2242 | 2276 | ||
2243 | if (port->xmit_cnt < WAKEUP_CHARS) { | 2277 | if (port->xmit_cnt < WAKEUP_CHARS) |
2244 | set_bit(MXSER_EVENT_TXLOW, &port->event); | 2278 | tty_wakeup(port->tty); |
2245 | schedule_work(&port->tqueue); | 2279 | |
2246 | } | ||
2247 | if (port->xmit_cnt <= 0) { | 2280 | if (port->xmit_cnt <= 0) { |
2248 | port->IER &= ~UART_IER_THRI; | 2281 | port->IER &= ~UART_IER_THRI; |
2249 | outb(port->IER, port->ioaddr + UART_IER); | 2282 | outb(port->IER, port->ioaddr + UART_IER); |
2250 | } | 2283 | } |
2251 | unlock: | ||
2252 | spin_unlock_irqrestore(&port->slock, flags); | ||
2253 | } | 2284 | } |
2254 | 2285 | ||
2255 | /* | 2286 | /* |
@@ -2261,8 +2292,7 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id) | |||
2261 | struct mxser_board *brd = NULL; | 2292 | struct mxser_board *brd = NULL; |
2262 | struct mxser_port *port; | 2293 | struct mxser_port *port; |
2263 | int max, irqbits, bits, msr; | 2294 | int max, irqbits, bits, msr; |
2264 | int pass_counter = 0; | 2295 | unsigned int int_cnt, pass_counter = 0; |
2265 | unsigned int int_cnt; | ||
2266 | int handled = IRQ_NONE; | 2296 | int handled = IRQ_NONE; |
2267 | 2297 | ||
2268 | for (i = 0; i < MXSER_BOARDS; i++) | 2298 | for (i = 0; i < MXSER_BOARDS; i++) |
@@ -2276,7 +2306,7 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id) | |||
2276 | if (brd == NULL) | 2306 | if (brd == NULL) |
2277 | goto irq_stop; | 2307 | goto irq_stop; |
2278 | max = brd->info->nports; | 2308 | max = brd->info->nports; |
2279 | while (1) { | 2309 | while (pass_counter++ < MXSER_ISR_PASS_LIMIT) { |
2280 | irqbits = inb(brd->vector) & brd->vector_mask; | 2310 | irqbits = inb(brd->vector) & brd->vector_mask; |
2281 | if (irqbits == brd->vector_mask) | 2311 | if (irqbits == brd->vector_mask) |
2282 | break; | 2312 | break; |
@@ -2290,12 +2320,16 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id) | |||
2290 | port = &brd->ports[i]; | 2320 | port = &brd->ports[i]; |
2291 | 2321 | ||
2292 | int_cnt = 0; | 2322 | int_cnt = 0; |
2323 | spin_lock(&port->slock); | ||
2293 | do { | 2324 | do { |
2294 | iir = inb(port->ioaddr + UART_IIR); | 2325 | iir = inb(port->ioaddr + UART_IIR); |
2295 | if (iir & UART_IIR_NO_INT) | 2326 | if (iir & UART_IIR_NO_INT) |
2296 | break; | 2327 | break; |
2297 | iir &= MOXA_MUST_IIR_MASK; | 2328 | iir &= MOXA_MUST_IIR_MASK; |
2298 | if (!port->tty) { | 2329 | if (!port->tty || |
2330 | (port->flags & ASYNC_CLOSING) || | ||
2331 | !(port->flags & | ||
2332 | ASYNC_INITIALIZED)) { | ||
2299 | status = inb(port->ioaddr + UART_LSR); | 2333 | status = inb(port->ioaddr + UART_LSR); |
2300 | outb(0x27, port->ioaddr + UART_FCR); | 2334 | outb(0x27, port->ioaddr + UART_FCR); |
2301 | inb(port->ioaddr + UART_MSR); | 2335 | inb(port->ioaddr + UART_MSR); |
@@ -2341,9 +2375,8 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id) | |||
2341 | mxser_transmit_chars(port); | 2375 | mxser_transmit_chars(port); |
2342 | } | 2376 | } |
2343 | } while (int_cnt++ < MXSER_ISR_PASS_LIMIT); | 2377 | } while (int_cnt++ < MXSER_ISR_PASS_LIMIT); |
2378 | spin_unlock(&port->slock); | ||
2344 | } | 2379 | } |
2345 | if (pass_counter++ > MXSER_ISR_PASS_LIMIT) | ||
2346 | break; /* Prevent infinite loops */ | ||
2347 | } | 2380 | } |
2348 | 2381 | ||
2349 | irq_stop: | 2382 | irq_stop: |
@@ -2385,7 +2418,6 @@ static void mxser_release_res(struct mxser_board *brd, struct pci_dev *pdev, | |||
2385 | #ifdef CONFIG_PCI | 2418 | #ifdef CONFIG_PCI |
2386 | pci_release_region(pdev, 2); | 2419 | pci_release_region(pdev, 2); |
2387 | pci_release_region(pdev, 3); | 2420 | pci_release_region(pdev, 3); |
2388 | pci_dev_put(pdev); | ||
2389 | #endif | 2421 | #endif |
2390 | } else { | 2422 | } else { |
2391 | release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); | 2423 | release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); |
@@ -2420,11 +2452,10 @@ static int __devinit mxser_initbrd(struct mxser_board *brd, | |||
2420 | info->custom_divisor = info->baud_base * 16; | 2452 | info->custom_divisor = info->baud_base * 16; |
2421 | info->close_delay = 5 * HZ / 10; | 2453 | info->close_delay = 5 * HZ / 10; |
2422 | info->closing_wait = 30 * HZ; | 2454 | info->closing_wait = 30 * HZ; |
2423 | INIT_WORK(&info->tqueue, mxser_do_softint); | ||
2424 | info->normal_termios = mxvar_sdriver->init_termios; | 2455 | info->normal_termios = mxvar_sdriver->init_termios; |
2425 | init_waitqueue_head(&info->open_wait); | 2456 | init_waitqueue_head(&info->open_wait); |
2426 | init_waitqueue_head(&info->close_wait); | ||
2427 | init_waitqueue_head(&info->delta_msr_wait); | 2457 | init_waitqueue_head(&info->delta_msr_wait); |
2458 | info->speed = 9600; | ||
2428 | memset(&info->mon_data, 0, sizeof(struct mxser_mon)); | 2459 | memset(&info->mon_data, 0, sizeof(struct mxser_mon)); |
2429 | info->err_shadow = 0; | 2460 | info->err_shadow = 0; |
2430 | spin_lock_init(&info->slock); | 2461 | spin_lock_init(&info->slock); |
@@ -2433,22 +2464,17 @@ static int __devinit mxser_initbrd(struct mxser_board *brd, | |||
2433 | outb(inb(info->ioaddr + UART_IER) & 0xf0, | 2464 | outb(inb(info->ioaddr + UART_IER) & 0xf0, |
2434 | info->ioaddr + UART_IER); | 2465 | info->ioaddr + UART_IER); |
2435 | } | 2466 | } |
2436 | /* | ||
2437 | * Allocate the IRQ if necessary | ||
2438 | */ | ||
2439 | 2467 | ||
2440 | retval = request_irq(brd->irq, mxser_interrupt, | 2468 | retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser", |
2441 | (brd->ports[0].flags & ASYNC_SHARE_IRQ) ? IRQF_SHARED : | 2469 | brd); |
2442 | IRQF_DISABLED, "mxser", brd); | ||
2443 | if (retval) { | 2470 | if (retval) { |
2444 | printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may " | 2471 | printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may " |
2445 | "conflict with another device.\n", | 2472 | "conflict with another device.\n", |
2446 | brd->info->name, brd->irq); | 2473 | brd->info->name, brd->irq); |
2447 | /* We hold resources, we need to release them. */ | 2474 | /* We hold resources, we need to release them. */ |
2448 | mxser_release_res(brd, pdev, 0); | 2475 | mxser_release_res(brd, pdev, 0); |
2449 | return retval; | ||
2450 | } | 2476 | } |
2451 | return 0; | 2477 | return retval; |
2452 | } | 2478 | } |
2453 | 2479 | ||
2454 | static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) | 2480 | static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) |
@@ -2633,8 +2659,9 @@ static int __devinit mxser_probe(struct pci_dev *pdev, | |||
2633 | } | 2659 | } |
2634 | 2660 | ||
2635 | /* mxser_initbrd will hook ISR. */ | 2661 | /* mxser_initbrd will hook ISR. */ |
2636 | if (mxser_initbrd(brd, pdev) < 0) | 2662 | retval = mxser_initbrd(brd, pdev); |
2637 | goto err_relvec; | 2663 | if (retval) |
2664 | goto err_null; | ||
2638 | 2665 | ||
2639 | for (i = 0; i < brd->info->nports; i++) | 2666 | for (i = 0; i < brd->info->nports; i++) |
2640 | tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev); | 2667 | tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev); |
@@ -2642,10 +2669,9 @@ static int __devinit mxser_probe(struct pci_dev *pdev, | |||
2642 | pci_set_drvdata(pdev, brd); | 2669 | pci_set_drvdata(pdev, brd); |
2643 | 2670 | ||
2644 | return 0; | 2671 | return 0; |
2645 | err_relvec: | ||
2646 | pci_release_region(pdev, 3); | ||
2647 | err_relio: | 2672 | err_relio: |
2648 | pci_release_region(pdev, 2); | 2673 | pci_release_region(pdev, 2); |
2674 | err_null: | ||
2649 | brd->info = NULL; | 2675 | brd->info = NULL; |
2650 | err: | 2676 | err: |
2651 | return retval; | 2677 | return retval; |
@@ -2663,6 +2689,7 @@ static void __devexit mxser_remove(struct pci_dev *pdev) | |||
2663 | tty_unregister_device(mxvar_sdriver, brd->idx + i); | 2689 | tty_unregister_device(mxvar_sdriver, brd->idx + i); |
2664 | 2690 | ||
2665 | mxser_release_res(brd, pdev, 1); | 2691 | mxser_release_res(brd, pdev, 1); |
2692 | brd->info = NULL; | ||
2666 | } | 2693 | } |
2667 | 2694 | ||
2668 | static struct pci_driver mxser_driver = { | 2695 | static struct pci_driver mxser_driver = { |
@@ -2684,7 +2711,6 @@ static int __init mxser_module_init(void) | |||
2684 | mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1); | 2711 | mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1); |
2685 | if (!mxvar_sdriver) | 2712 | if (!mxvar_sdriver) |
2686 | return -ENOMEM; | 2713 | return -ENOMEM; |
2687 | spin_lock_init(&gm_lock); | ||
2688 | 2714 | ||
2689 | printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n", | 2715 | printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n", |
2690 | MXSER_VERSION); | 2716 | MXSER_VERSION); |
diff --git a/drivers/char/mxser_new.h b/drivers/char/mxser_new.h index a08f0ecb09ba..d42f7766c652 100644 --- a/drivers/char/mxser_new.h +++ b/drivers/char/mxser_new.h | |||
@@ -26,18 +26,8 @@ | |||
26 | #define RS422_MODE 2 | 26 | #define RS422_MODE 2 |
27 | #define RS485_4WIRE_MODE 3 | 27 | #define RS485_4WIRE_MODE 3 |
28 | #define OP_MODE_MASK 3 | 28 | #define OP_MODE_MASK 3 |
29 | // above add by Victor Yu. 01-05-2004 | ||
30 | |||
31 | #define TTY_THRESHOLD_THROTTLE 128 | ||
32 | |||
33 | #define LO_WATER (TTY_FLIPBUF_SIZE) | ||
34 | #define HI_WATER (TTY_FLIPBUF_SIZE*2*3/4) | ||
35 | |||
36 | // added by James. 03-11-2004. | ||
37 | #define MOXA_SDS_GETICOUNTER (MOXA + 68) | ||
38 | #define MOXA_SDS_RSTICOUNTER (MOXA + 69) | ||
39 | // (above) added by James. | ||
40 | 29 | ||
30 | #define MOXA_SDS_RSTICOUNTER (MOXA + 69) | ||
41 | #define MOXA_ASPP_OQUEUE (MOXA + 70) | 31 | #define MOXA_ASPP_OQUEUE (MOXA + 70) |
42 | #define MOXA_ASPP_SETBAUD (MOXA + 71) | 32 | #define MOXA_ASPP_SETBAUD (MOXA + 71) |
43 | #define MOXA_ASPP_GETBAUD (MOXA + 72) | 33 | #define MOXA_ASPP_GETBAUD (MOXA + 72) |
@@ -45,7 +35,8 @@ | |||
45 | #define MOXA_ASPP_LSTATUS (MOXA + 74) | 35 | #define MOXA_ASPP_LSTATUS (MOXA + 74) |
46 | #define MOXA_ASPP_MON_EXT (MOXA + 75) | 36 | #define MOXA_ASPP_MON_EXT (MOXA + 75) |
47 | #define MOXA_SET_BAUD_METHOD (MOXA + 76) | 37 | #define MOXA_SET_BAUD_METHOD (MOXA + 76) |
48 | 38 | #define MOXA_SET_SPECIAL_BAUD_RATE (MOXA + 77) | |
39 | #define MOXA_GET_SPECIAL_BAUD_RATE (MOXA + 78) | ||
49 | 40 | ||
50 | /* --------------------------------------------------- */ | 41 | /* --------------------------------------------------- */ |
51 | 42 | ||
@@ -55,51 +46,46 @@ | |||
55 | #define NPPI_NOTIFY_SW_OVERRUN 0x08 | 46 | #define NPPI_NOTIFY_SW_OVERRUN 0x08 |
56 | #define NPPI_NOTIFY_BREAK 0x10 | 47 | #define NPPI_NOTIFY_BREAK 0x10 |
57 | 48 | ||
58 | #define NPPI_NOTIFY_CTSHOLD 0x01 // Tx hold by CTS low | 49 | #define NPPI_NOTIFY_CTSHOLD 0x01 /* Tx hold by CTS low */ |
59 | #define NPPI_NOTIFY_DSRHOLD 0x02 // Tx hold by DSR low | 50 | #define NPPI_NOTIFY_DSRHOLD 0x02 /* Tx hold by DSR low */ |
60 | #define NPPI_NOTIFY_XOFFHOLD 0x08 // Tx hold by Xoff received | 51 | #define NPPI_NOTIFY_XOFFHOLD 0x08 /* Tx hold by Xoff received */ |
61 | #define NPPI_NOTIFY_XOFFXENT 0x10 // Xoff Sent | 52 | #define NPPI_NOTIFY_XOFFXENT 0x10 /* Xoff Sent */ |
62 | 53 | ||
63 | //CheckIsMoxaMust return value | 54 | /* follow just for Moxa Must chip define. */ |
64 | #define MOXA_OTHER_UART 0x00 | 55 | /* */ |
65 | #define MOXA_MUST_MU150_HWID 0x01 | 56 | /* when LCR register (offset 0x03) write following value, */ |
66 | #define MOXA_MUST_MU860_HWID 0x02 | 57 | /* the Must chip will enter enchance mode. And write value */ |
67 | 58 | /* on EFR (offset 0x02) bit 6,7 to change bank. */ | |
68 | // follow just for Moxa Must chip define. | ||
69 | // | ||
70 | // when LCR register (offset 0x03) write following value, | ||
71 | // the Must chip will enter enchance mode. And write value | ||
72 | // on EFR (offset 0x02) bit 6,7 to change bank. | ||
73 | #define MOXA_MUST_ENTER_ENCHANCE 0xBF | 59 | #define MOXA_MUST_ENTER_ENCHANCE 0xBF |
74 | 60 | ||
75 | // when enhance mode enable, access on general bank register | 61 | /* when enhance mode enable, access on general bank register */ |
76 | #define MOXA_MUST_GDL_REGISTER 0x07 | 62 | #define MOXA_MUST_GDL_REGISTER 0x07 |
77 | #define MOXA_MUST_GDL_MASK 0x7F | 63 | #define MOXA_MUST_GDL_MASK 0x7F |
78 | #define MOXA_MUST_GDL_HAS_BAD_DATA 0x80 | 64 | #define MOXA_MUST_GDL_HAS_BAD_DATA 0x80 |
79 | 65 | ||
80 | #define MOXA_MUST_LSR_RERR 0x80 // error in receive FIFO | 66 | #define MOXA_MUST_LSR_RERR 0x80 /* error in receive FIFO */ |
81 | // enchance register bank select and enchance mode setting register | 67 | /* enchance register bank select and enchance mode setting register */ |
82 | // when LCR register equal to 0xBF | 68 | /* when LCR register equal to 0xBF */ |
83 | #define MOXA_MUST_EFR_REGISTER 0x02 | 69 | #define MOXA_MUST_EFR_REGISTER 0x02 |
84 | // enchance mode enable | 70 | /* enchance mode enable */ |
85 | #define MOXA_MUST_EFR_EFRB_ENABLE 0x10 | 71 | #define MOXA_MUST_EFR_EFRB_ENABLE 0x10 |
86 | // enchance reister bank set 0, 1, 2 | 72 | /* enchance reister bank set 0, 1, 2 */ |
87 | #define MOXA_MUST_EFR_BANK0 0x00 | 73 | #define MOXA_MUST_EFR_BANK0 0x00 |
88 | #define MOXA_MUST_EFR_BANK1 0x40 | 74 | #define MOXA_MUST_EFR_BANK1 0x40 |
89 | #define MOXA_MUST_EFR_BANK2 0x80 | 75 | #define MOXA_MUST_EFR_BANK2 0x80 |
90 | #define MOXA_MUST_EFR_BANK3 0xC0 | 76 | #define MOXA_MUST_EFR_BANK3 0xC0 |
91 | #define MOXA_MUST_EFR_BANK_MASK 0xC0 | 77 | #define MOXA_MUST_EFR_BANK_MASK 0xC0 |
92 | 78 | ||
93 | // set XON1 value register, when LCR=0xBF and change to bank0 | 79 | /* set XON1 value register, when LCR=0xBF and change to bank0 */ |
94 | #define MOXA_MUST_XON1_REGISTER 0x04 | 80 | #define MOXA_MUST_XON1_REGISTER 0x04 |
95 | 81 | ||
96 | // set XON2 value register, when LCR=0xBF and change to bank0 | 82 | /* set XON2 value register, when LCR=0xBF and change to bank0 */ |
97 | #define MOXA_MUST_XON2_REGISTER 0x05 | 83 | #define MOXA_MUST_XON2_REGISTER 0x05 |
98 | 84 | ||
99 | // set XOFF1 value register, when LCR=0xBF and change to bank0 | 85 | /* set XOFF1 value register, when LCR=0xBF and change to bank0 */ |
100 | #define MOXA_MUST_XOFF1_REGISTER 0x06 | 86 | #define MOXA_MUST_XOFF1_REGISTER 0x06 |
101 | 87 | ||
102 | // set XOFF2 value register, when LCR=0xBF and change to bank0 | 88 | /* set XOFF2 value register, when LCR=0xBF and change to bank0 */ |
103 | #define MOXA_MUST_XOFF2_REGISTER 0x07 | 89 | #define MOXA_MUST_XOFF2_REGISTER 0x07 |
104 | 90 | ||
105 | #define MOXA_MUST_RBRTL_REGISTER 0x04 | 91 | #define MOXA_MUST_RBRTL_REGISTER 0x04 |
@@ -111,32 +97,32 @@ | |||
111 | #define MOXA_MUST_ECR_REGISTER 0x06 | 97 | #define MOXA_MUST_ECR_REGISTER 0x06 |
112 | #define MOXA_MUST_CSR_REGISTER 0x07 | 98 | #define MOXA_MUST_CSR_REGISTER 0x07 |
113 | 99 | ||
114 | // good data mode enable | 100 | /* good data mode enable */ |
115 | #define MOXA_MUST_FCR_GDA_MODE_ENABLE 0x20 | 101 | #define MOXA_MUST_FCR_GDA_MODE_ENABLE 0x20 |
116 | // only good data put into RxFIFO | 102 | /* only good data put into RxFIFO */ |
117 | #define MOXA_MUST_FCR_GDA_ONLY_ENABLE 0x10 | 103 | #define MOXA_MUST_FCR_GDA_ONLY_ENABLE 0x10 |
118 | 104 | ||
119 | // enable CTS interrupt | 105 | /* enable CTS interrupt */ |
120 | #define MOXA_MUST_IER_ECTSI 0x80 | 106 | #define MOXA_MUST_IER_ECTSI 0x80 |
121 | // enable RTS interrupt | 107 | /* enable RTS interrupt */ |
122 | #define MOXA_MUST_IER_ERTSI 0x40 | 108 | #define MOXA_MUST_IER_ERTSI 0x40 |
123 | // enable Xon/Xoff interrupt | 109 | /* enable Xon/Xoff interrupt */ |
124 | #define MOXA_MUST_IER_XINT 0x20 | 110 | #define MOXA_MUST_IER_XINT 0x20 |
125 | // enable GDA interrupt | 111 | /* enable GDA interrupt */ |
126 | #define MOXA_MUST_IER_EGDAI 0x10 | 112 | #define MOXA_MUST_IER_EGDAI 0x10 |
127 | 113 | ||
128 | #define MOXA_MUST_RECV_ISR (UART_IER_RDI | MOXA_MUST_IER_EGDAI) | 114 | #define MOXA_MUST_RECV_ISR (UART_IER_RDI | MOXA_MUST_IER_EGDAI) |
129 | 115 | ||
130 | // GDA interrupt pending | 116 | /* GDA interrupt pending */ |
131 | #define MOXA_MUST_IIR_GDA 0x1C | 117 | #define MOXA_MUST_IIR_GDA 0x1C |
132 | #define MOXA_MUST_IIR_RDA 0x04 | 118 | #define MOXA_MUST_IIR_RDA 0x04 |
133 | #define MOXA_MUST_IIR_RTO 0x0C | 119 | #define MOXA_MUST_IIR_RTO 0x0C |
134 | #define MOXA_MUST_IIR_LSR 0x06 | 120 | #define MOXA_MUST_IIR_LSR 0x06 |
135 | 121 | ||
136 | // recieved Xon/Xoff or specical interrupt pending | 122 | /* recieved Xon/Xoff or specical interrupt pending */ |
137 | #define MOXA_MUST_IIR_XSC 0x10 | 123 | #define MOXA_MUST_IIR_XSC 0x10 |
138 | 124 | ||
139 | // RTS/CTS change state interrupt pending | 125 | /* RTS/CTS change state interrupt pending */ |
140 | #define MOXA_MUST_IIR_RTSCTS 0x20 | 126 | #define MOXA_MUST_IIR_RTSCTS 0x20 |
141 | #define MOXA_MUST_IIR_MASK 0x3E | 127 | #define MOXA_MUST_IIR_MASK 0x3E |
142 | 128 | ||
@@ -144,307 +130,164 @@ | |||
144 | #define MOXA_MUST_MCR_XON_ANY 0x80 | 130 | #define MOXA_MUST_MCR_XON_ANY 0x80 |
145 | #define MOXA_MUST_MCR_TX_XON 0x08 | 131 | #define MOXA_MUST_MCR_TX_XON 0x08 |
146 | 132 | ||
147 | 133 | /* software flow control on chip mask value */ | |
148 | // software flow control on chip mask value | ||
149 | #define MOXA_MUST_EFR_SF_MASK 0x0F | 134 | #define MOXA_MUST_EFR_SF_MASK 0x0F |
150 | // send Xon1/Xoff1 | 135 | /* send Xon1/Xoff1 */ |
151 | #define MOXA_MUST_EFR_SF_TX1 0x08 | 136 | #define MOXA_MUST_EFR_SF_TX1 0x08 |
152 | // send Xon2/Xoff2 | 137 | /* send Xon2/Xoff2 */ |
153 | #define MOXA_MUST_EFR_SF_TX2 0x04 | 138 | #define MOXA_MUST_EFR_SF_TX2 0x04 |
154 | // send Xon1,Xon2/Xoff1,Xoff2 | 139 | /* send Xon1,Xon2/Xoff1,Xoff2 */ |
155 | #define MOXA_MUST_EFR_SF_TX12 0x0C | 140 | #define MOXA_MUST_EFR_SF_TX12 0x0C |
156 | // don't send Xon/Xoff | 141 | /* don't send Xon/Xoff */ |
157 | #define MOXA_MUST_EFR_SF_TX_NO 0x00 | 142 | #define MOXA_MUST_EFR_SF_TX_NO 0x00 |
158 | // Tx software flow control mask | 143 | /* Tx software flow control mask */ |
159 | #define MOXA_MUST_EFR_SF_TX_MASK 0x0C | 144 | #define MOXA_MUST_EFR_SF_TX_MASK 0x0C |
160 | // don't receive Xon/Xoff | 145 | /* don't receive Xon/Xoff */ |
161 | #define MOXA_MUST_EFR_SF_RX_NO 0x00 | 146 | #define MOXA_MUST_EFR_SF_RX_NO 0x00 |
162 | // receive Xon1/Xoff1 | 147 | /* receive Xon1/Xoff1 */ |
163 | #define MOXA_MUST_EFR_SF_RX1 0x02 | 148 | #define MOXA_MUST_EFR_SF_RX1 0x02 |
164 | // receive Xon2/Xoff2 | 149 | /* receive Xon2/Xoff2 */ |
165 | #define MOXA_MUST_EFR_SF_RX2 0x01 | 150 | #define MOXA_MUST_EFR_SF_RX2 0x01 |
166 | // receive Xon1,Xon2/Xoff1,Xoff2 | 151 | /* receive Xon1,Xon2/Xoff1,Xoff2 */ |
167 | #define MOXA_MUST_EFR_SF_RX12 0x03 | 152 | #define MOXA_MUST_EFR_SF_RX12 0x03 |
168 | // Rx software flow control mask | 153 | /* Rx software flow control mask */ |
169 | #define MOXA_MUST_EFR_SF_RX_MASK 0x03 | 154 | #define MOXA_MUST_EFR_SF_RX_MASK 0x03 |
170 | 155 | ||
171 | //#define MOXA_MUST_MIN_XOFFLIMIT 66 | 156 | #define ENABLE_MOXA_MUST_ENCHANCE_MODE(baseio) do { \ |
172 | //#define MOXA_MUST_MIN_XONLIMIT 20 | 157 | u8 __oldlcr, __efr; \ |
173 | //#define ID1_RX_TRIG 120 | 158 | __oldlcr = inb((baseio)+UART_LCR); \ |
174 | |||
175 | |||
176 | #define CHECK_MOXA_MUST_XOFFLIMIT(info) { \ | ||
177 | if ( (info)->IsMoxaMustChipFlag && \ | ||
178 | (info)->HandFlow.XoffLimit < MOXA_MUST_MIN_XOFFLIMIT ) { \ | ||
179 | (info)->HandFlow.XoffLimit = MOXA_MUST_MIN_XOFFLIMIT; \ | ||
180 | (info)->HandFlow.XonLimit = MOXA_MUST_MIN_XONLIMIT; \ | ||
181 | } \ | ||
182 | } | ||
183 | |||
184 | #define ENABLE_MOXA_MUST_ENCHANCE_MODE(baseio) { \ | ||
185 | u8 __oldlcr, __efr; \ | ||
186 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
187 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 159 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ |
188 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 160 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ |
189 | __efr |= MOXA_MUST_EFR_EFRB_ENABLE; \ | 161 | __efr |= MOXA_MUST_EFR_EFRB_ENABLE; \ |
190 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 162 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ |
191 | outb(__oldlcr, (baseio)+UART_LCR); \ | 163 | outb(__oldlcr, (baseio)+UART_LCR); \ |
192 | } | 164 | } while (0) |
193 | 165 | ||
194 | #define DISABLE_MOXA_MUST_ENCHANCE_MODE(baseio) { \ | 166 | #define DISABLE_MOXA_MUST_ENCHANCE_MODE(baseio) do { \ |
195 | u8 __oldlcr, __efr; \ | 167 | u8 __oldlcr, __efr; \ |
196 | __oldlcr = inb((baseio)+UART_LCR); \ | 168 | __oldlcr = inb((baseio)+UART_LCR); \ |
197 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 169 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ |
198 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 170 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ |
199 | __efr &= ~MOXA_MUST_EFR_EFRB_ENABLE; \ | 171 | __efr &= ~MOXA_MUST_EFR_EFRB_ENABLE; \ |
200 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 172 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ |
201 | outb(__oldlcr, (baseio)+UART_LCR); \ | 173 | outb(__oldlcr, (baseio)+UART_LCR); \ |
202 | } | 174 | } while (0) |
203 | 175 | ||
204 | #define SET_MOXA_MUST_XON1_VALUE(baseio, Value) { \ | 176 | #define SET_MOXA_MUST_XON1_VALUE(baseio, Value) do { \ |
205 | u8 __oldlcr, __efr; \ | 177 | u8 __oldlcr, __efr; \ |
206 | __oldlcr = inb((baseio)+UART_LCR); \ | 178 | __oldlcr = inb((baseio)+UART_LCR); \ |
207 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 179 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ |
208 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 180 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ |
209 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | 181 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ |
210 | __efr |= MOXA_MUST_EFR_BANK0; \ | 182 | __efr |= MOXA_MUST_EFR_BANK0; \ |
211 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 183 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ |
212 | outb((u8)(Value), (baseio)+MOXA_MUST_XON1_REGISTER); \ | 184 | outb((u8)(Value), (baseio)+MOXA_MUST_XON1_REGISTER); \ |
213 | outb(__oldlcr, (baseio)+UART_LCR); \ | 185 | outb(__oldlcr, (baseio)+UART_LCR); \ |
214 | } | 186 | } while (0) |
215 | 187 | ||
216 | #define SET_MOXA_MUST_XON2_VALUE(baseio, Value) { \ | 188 | #define SET_MOXA_MUST_XOFF1_VALUE(baseio, Value) do { \ |
217 | u8 __oldlcr, __efr; \ | 189 | u8 __oldlcr, __efr; \ |
218 | __oldlcr = inb((baseio)+UART_LCR); \ | 190 | __oldlcr = inb((baseio)+UART_LCR); \ |
219 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 191 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ |
220 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 192 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ |
221 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | 193 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ |
222 | __efr |= MOXA_MUST_EFR_BANK0; \ | 194 | __efr |= MOXA_MUST_EFR_BANK0; \ |
223 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 195 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ |
224 | outb((u8)(Value), (baseio)+MOXA_MUST_XON2_REGISTER); \ | ||
225 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
226 | } | ||
227 | |||
228 | #define SET_MOXA_MUST_XOFF1_VALUE(baseio, Value) { \ | ||
229 | u8 __oldlcr, __efr; \ | ||
230 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
231 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
232 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
233 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | ||
234 | __efr |= MOXA_MUST_EFR_BANK0; \ | ||
235 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
236 | outb((u8)(Value), (baseio)+MOXA_MUST_XOFF1_REGISTER); \ | 196 | outb((u8)(Value), (baseio)+MOXA_MUST_XOFF1_REGISTER); \ |
237 | outb(__oldlcr, (baseio)+UART_LCR); \ | 197 | outb(__oldlcr, (baseio)+UART_LCR); \ |
238 | } | 198 | } while (0) |
239 | 199 | ||
240 | #define SET_MOXA_MUST_XOFF2_VALUE(baseio, Value) { \ | 200 | #define SET_MOXA_MUST_FIFO_VALUE(info) do { \ |
241 | u8 __oldlcr, __efr; \ | 201 | u8 __oldlcr, __efr; \ |
242 | __oldlcr = inb((baseio)+UART_LCR); \ | 202 | __oldlcr = inb((info)->ioaddr+UART_LCR); \ |
243 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 203 | outb(MOXA_MUST_ENTER_ENCHANCE, (info)->ioaddr+UART_LCR);\ |
244 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
245 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | ||
246 | __efr |= MOXA_MUST_EFR_BANK0; \ | ||
247 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
248 | outb((u8)(Value), (baseio)+MOXA_MUST_XOFF2_REGISTER); \ | ||
249 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
250 | } | ||
251 | |||
252 | #define SET_MOXA_MUST_RBRTL_VALUE(baseio, Value) { \ | ||
253 | u8 __oldlcr, __efr; \ | ||
254 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
255 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
256 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
257 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | ||
258 | __efr |= MOXA_MUST_EFR_BANK1; \ | ||
259 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
260 | outb((u8)(Value), (baseio)+MOXA_MUST_RBRTL_REGISTER); \ | ||
261 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
262 | } | ||
263 | |||
264 | #define SET_MOXA_MUST_RBRTH_VALUE(baseio, Value) { \ | ||
265 | u8 __oldlcr, __efr; \ | ||
266 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
267 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
268 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
269 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | ||
270 | __efr |= MOXA_MUST_EFR_BANK1; \ | ||
271 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
272 | outb((u8)(Value), (baseio)+MOXA_MUST_RBRTH_REGISTER); \ | ||
273 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
274 | } | ||
275 | |||
276 | #define SET_MOXA_MUST_RBRTI_VALUE(baseio, Value) { \ | ||
277 | u8 __oldlcr, __efr; \ | ||
278 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
279 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
280 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
281 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | ||
282 | __efr |= MOXA_MUST_EFR_BANK1; \ | ||
283 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
284 | outb((u8)(Value), (baseio)+MOXA_MUST_RBRTI_REGISTER); \ | ||
285 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
286 | } | ||
287 | |||
288 | #define SET_MOXA_MUST_THRTL_VALUE(baseio, Value) { \ | ||
289 | u8 __oldlcr, __efr; \ | ||
290 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
291 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
292 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
293 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | ||
294 | __efr |= MOXA_MUST_EFR_BANK1; \ | ||
295 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
296 | outb((u8)(Value), (baseio)+MOXA_MUST_THRTL_REGISTER); \ | ||
297 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
298 | } | ||
299 | |||
300 | //#define MOXA_MUST_RBRL_VALUE 4 | ||
301 | #define SET_MOXA_MUST_FIFO_VALUE(info) { \ | ||
302 | u8 __oldlcr, __efr; \ | ||
303 | __oldlcr = inb((info)->ioaddr+UART_LCR); \ | ||
304 | outb(MOXA_MUST_ENTER_ENCHANCE, (info)->ioaddr+UART_LCR); \ | ||
305 | __efr = inb((info)->ioaddr+MOXA_MUST_EFR_REGISTER); \ | 204 | __efr = inb((info)->ioaddr+MOXA_MUST_EFR_REGISTER); \ |
306 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | 205 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ |
307 | __efr |= MOXA_MUST_EFR_BANK1; \ | 206 | __efr |= MOXA_MUST_EFR_BANK1; \ |
308 | outb(__efr, (info)->ioaddr+MOXA_MUST_EFR_REGISTER); \ | 207 | outb(__efr, (info)->ioaddr+MOXA_MUST_EFR_REGISTER); \ |
309 | outb((u8)((info)->rx_high_water), (info)->ioaddr+MOXA_MUST_RBRTH_REGISTER); \ | 208 | outb((u8)((info)->rx_high_water), (info)->ioaddr+ \ |
310 | outb((u8)((info)->rx_trigger), (info)->ioaddr+MOXA_MUST_RBRTI_REGISTER); \ | 209 | MOXA_MUST_RBRTH_REGISTER); \ |
311 | outb((u8)((info)->rx_low_water), (info)->ioaddr+MOXA_MUST_RBRTL_REGISTER); \ | 210 | outb((u8)((info)->rx_trigger), (info)->ioaddr+ \ |
312 | outb(__oldlcr, (info)->ioaddr+UART_LCR); \ | 211 | MOXA_MUST_RBRTI_REGISTER); \ |
313 | } | 212 | outb((u8)((info)->rx_low_water), (info)->ioaddr+ \ |
314 | 213 | MOXA_MUST_RBRTL_REGISTER); \ | |
315 | 214 | outb(__oldlcr, (info)->ioaddr+UART_LCR); \ | |
316 | 215 | } while (0) | |
317 | #define SET_MOXA_MUST_ENUM_VALUE(baseio, Value) { \ | 216 | |
318 | u8 __oldlcr, __efr; \ | 217 | #define SET_MOXA_MUST_ENUM_VALUE(baseio, Value) do { \ |
319 | __oldlcr = inb((baseio)+UART_LCR); \ | 218 | u8 __oldlcr, __efr; \ |
219 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
320 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 220 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ |
321 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 221 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ |
322 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | 222 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ |
323 | __efr |= MOXA_MUST_EFR_BANK2; \ | 223 | __efr |= MOXA_MUST_EFR_BANK2; \ |
324 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 224 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ |
325 | outb((u8)(Value), (baseio)+MOXA_MUST_ENUM_REGISTER); \ | 225 | outb((u8)(Value), (baseio)+MOXA_MUST_ENUM_REGISTER); \ |
326 | outb(__oldlcr, (baseio)+UART_LCR); \ | 226 | outb(__oldlcr, (baseio)+UART_LCR); \ |
327 | } | 227 | } while (0) |
328 | 228 | ||
329 | #define GET_MOXA_MUST_HARDWARE_ID(baseio, pId) { \ | 229 | #define GET_MOXA_MUST_HARDWARE_ID(baseio, pId) do { \ |
330 | u8 __oldlcr, __efr; \ | 230 | u8 __oldlcr, __efr; \ |
331 | __oldlcr = inb((baseio)+UART_LCR); \ | 231 | __oldlcr = inb((baseio)+UART_LCR); \ |
332 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
333 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
334 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | ||
335 | __efr |= MOXA_MUST_EFR_BANK2; \ | ||
336 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
337 | *pId = inb((baseio)+MOXA_MUST_HWID_REGISTER); \ | ||
338 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
339 | } | ||
340 | |||
341 | #define SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(baseio) { \ | ||
342 | u8 __oldlcr, __efr; \ | ||
343 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
344 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
345 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
346 | __efr &= ~MOXA_MUST_EFR_SF_MASK; \ | ||
347 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
348 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
349 | } | ||
350 | |||
351 | #define SET_MOXA_MUST_JUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \ | ||
352 | u8 __oldlcr, __efr; \ | ||
353 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
354 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 232 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ |
355 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 233 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ |
356 | __efr &= ~MOXA_MUST_EFR_SF_MASK; \ | 234 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ |
357 | __efr |= MOXA_MUST_EFR_SF_TX1; \ | 235 | __efr |= MOXA_MUST_EFR_BANK2; \ |
358 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 236 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ |
359 | outb(__oldlcr, (baseio)+UART_LCR); \ | 237 | *pId = inb((baseio)+MOXA_MUST_HWID_REGISTER); \ |
360 | } | 238 | outb(__oldlcr, (baseio)+UART_LCR); \ |
361 | 239 | } while (0) | |
362 | #define ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \ | 240 | |
363 | u8 __oldlcr, __efr; \ | 241 | #define SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(baseio) do { \ |
364 | __oldlcr = inb((baseio)+UART_LCR); \ | 242 | u8 __oldlcr, __efr; \ |
243 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
365 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 244 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ |
366 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 245 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ |
367 | __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \ | 246 | __efr &= ~MOXA_MUST_EFR_SF_MASK; \ |
368 | __efr |= MOXA_MUST_EFR_SF_TX1; \ | 247 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ |
369 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 248 | outb(__oldlcr, (baseio)+UART_LCR); \ |
370 | outb(__oldlcr, (baseio)+UART_LCR); \ | 249 | } while (0) |
371 | } | 250 | |
372 | 251 | #define ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) do { \ | |
373 | #define DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \ | 252 | u8 __oldlcr, __efr; \ |
374 | u8 __oldlcr, __efr; \ | 253 | __oldlcr = inb((baseio)+UART_LCR); \ |
375 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
376 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 254 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ |
377 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 255 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ |
378 | __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \ | 256 | __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \ |
379 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 257 | __efr |= MOXA_MUST_EFR_SF_TX1; \ |
380 | outb(__oldlcr, (baseio)+UART_LCR); \ | 258 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ |
381 | } | 259 | outb(__oldlcr, (baseio)+UART_LCR); \ |
382 | 260 | } while (0) | |
383 | #define SET_MOXA_MUST_JUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \ | 261 | |
384 | u8 __oldlcr, __efr; \ | 262 | #define DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) do { \ |
385 | __oldlcr = inb((baseio)+UART_LCR); \ | 263 | u8 __oldlcr, __efr; \ |
264 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
386 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 265 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ |
387 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 266 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ |
388 | __efr &= ~MOXA_MUST_EFR_SF_MASK; \ | 267 | __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \ |
389 | __efr |= MOXA_MUST_EFR_SF_RX1; \ | 268 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ |
390 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 269 | outb(__oldlcr, (baseio)+UART_LCR); \ |
391 | outb(__oldlcr, (baseio)+UART_LCR); \ | 270 | } while (0) |
392 | } | 271 | |
393 | 272 | #define ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) do { \ | |
394 | #define ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \ | 273 | u8 __oldlcr, __efr; \ |
395 | u8 __oldlcr, __efr; \ | 274 | __oldlcr = inb((baseio)+UART_LCR); \ |
396 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
397 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 275 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ |
398 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 276 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ |
399 | __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \ | 277 | __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \ |
400 | __efr |= MOXA_MUST_EFR_SF_RX1; \ | 278 | __efr |= MOXA_MUST_EFR_SF_RX1; \ |
401 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 279 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ |
402 | outb(__oldlcr, (baseio)+UART_LCR); \ | 280 | outb(__oldlcr, (baseio)+UART_LCR); \ |
403 | } | 281 | } while (0) |
404 | 282 | ||
405 | #define DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \ | 283 | #define DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) do { \ |
406 | u8 __oldlcr, __efr; \ | 284 | u8 __oldlcr, __efr; \ |
407 | __oldlcr = inb((baseio)+UART_LCR); \ | 285 | __oldlcr = inb((baseio)+UART_LCR); \ |
408 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 286 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ |
409 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 287 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ |
410 | __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \ | 288 | __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \ |
411 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 289 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ |
412 | outb(__oldlcr, (baseio)+UART_LCR); \ | 290 | outb(__oldlcr, (baseio)+UART_LCR); \ |
413 | } | 291 | } while (0) |
414 | |||
415 | #define ENABLE_MOXA_MUST_TX_RX_SOFTWARE_FLOW_CONTROL(baseio) { \ | ||
416 | u8 __oldlcr, __efr; \ | ||
417 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
418 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
419 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
420 | __efr &= ~MOXA_MUST_EFR_SF_MASK; \ | ||
421 | __efr |= (MOXA_MUST_EFR_SF_RX1|MOXA_MUST_EFR_SF_TX1); \ | ||
422 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
423 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
424 | } | ||
425 | |||
426 | #define ENABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(baseio) { \ | ||
427 | u8 __oldmcr; \ | ||
428 | __oldmcr = inb((baseio)+UART_MCR); \ | ||
429 | __oldmcr |= MOXA_MUST_MCR_XON_ANY; \ | ||
430 | outb(__oldmcr, (baseio)+UART_MCR); \ | ||
431 | } | ||
432 | |||
433 | #define DISABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(baseio) { \ | ||
434 | u8 __oldmcr; \ | ||
435 | __oldmcr = inb((baseio)+UART_MCR); \ | ||
436 | __oldmcr &= ~MOXA_MUST_MCR_XON_ANY; \ | ||
437 | outb(__oldmcr, (baseio)+UART_MCR); \ | ||
438 | } | ||
439 | |||
440 | #define READ_MOXA_MUST_GDL(baseio) inb((baseio)+MOXA_MUST_GDL_REGISTER) | ||
441 | |||
442 | |||
443 | #ifndef INIT_WORK | ||
444 | #define INIT_WORK(_work, _func, _data){ \ | ||
445 | _data->tqueue.routine = _func;\ | ||
446 | _data->tqueue.data = _data;\ | ||
447 | } | ||
448 | #endif | ||
449 | 292 | ||
450 | #endif | 293 | #endif |
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index dc6d41841457..65f2d3a96b85 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c | |||
@@ -60,62 +60,56 @@ | |||
60 | #include <linux/slab.h> | 60 | #include <linux/slab.h> |
61 | #include <linux/tty.h> | 61 | #include <linux/tty.h> |
62 | #include <linux/errno.h> | 62 | #include <linux/errno.h> |
63 | #include <linux/string.h> /* used in new tty drivers */ | 63 | #include <linux/string.h> /* used in new tty drivers */ |
64 | #include <linux/signal.h> /* used in new tty drivers */ | 64 | #include <linux/signal.h> /* used in new tty drivers */ |
65 | #include <linux/ioctl.h> | 65 | #include <linux/ioctl.h> |
66 | #include <linux/n_r3964.h> | 66 | #include <linux/n_r3964.h> |
67 | #include <linux/poll.h> | 67 | #include <linux/poll.h> |
68 | #include <linux/init.h> | 68 | #include <linux/init.h> |
69 | #include <asm/uaccess.h> | 69 | #include <asm/uaccess.h> |
70 | 70 | ||
71 | 71 | /*#define DEBUG_QUEUE*/ | |
72 | //#define DEBUG_QUEUE | ||
73 | 72 | ||
74 | /* Log successful handshake and protocol operations */ | 73 | /* Log successful handshake and protocol operations */ |
75 | //#define DEBUG_PROTO_S | 74 | /*#define DEBUG_PROTO_S*/ |
76 | 75 | ||
77 | /* Log handshake and protocol errors: */ | 76 | /* Log handshake and protocol errors: */ |
78 | //#define DEBUG_PROTO_E | 77 | /*#define DEBUG_PROTO_E*/ |
79 | 78 | ||
80 | /* Log Linediscipline operations (open, close, read, write...): */ | 79 | /* Log Linediscipline operations (open, close, read, write...): */ |
81 | //#define DEBUG_LDISC | 80 | /*#define DEBUG_LDISC*/ |
82 | 81 | ||
83 | /* Log module and memory operations (init, cleanup; kmalloc, kfree): */ | 82 | /* Log module and memory operations (init, cleanup; kmalloc, kfree): */ |
84 | //#define DEBUG_MODUL | 83 | /*#define DEBUG_MODUL*/ |
85 | 84 | ||
86 | /* Macro helpers for debug output: */ | 85 | /* Macro helpers for debug output: */ |
87 | #define TRACE(format, args...) printk("r3964: " format "\n" , ## args); | 86 | #define TRACE(format, args...) printk("r3964: " format "\n" , ## args) |
88 | 87 | ||
89 | #ifdef DEBUG_MODUL | 88 | #ifdef DEBUG_MODUL |
90 | #define TRACE_M(format, args...) printk("r3964: " format "\n" , ## args); | 89 | #define TRACE_M(format, args...) printk("r3964: " format "\n" , ## args) |
91 | #else | 90 | #else |
92 | #define TRACE_M(fmt, arg...) /**/ | 91 | #define TRACE_M(fmt, arg...) do {} while (0) |
93 | #endif | 92 | #endif |
94 | |||
95 | #ifdef DEBUG_PROTO_S | 93 | #ifdef DEBUG_PROTO_S |
96 | #define TRACE_PS(format, args...) printk("r3964: " format "\n" , ## args); | 94 | #define TRACE_PS(format, args...) printk("r3964: " format "\n" , ## args) |
97 | #else | 95 | #else |
98 | #define TRACE_PS(fmt, arg...) /**/ | 96 | #define TRACE_PS(fmt, arg...) do {} while (0) |
99 | #endif | 97 | #endif |
100 | |||
101 | #ifdef DEBUG_PROTO_E | 98 | #ifdef DEBUG_PROTO_E |
102 | #define TRACE_PE(format, args...) printk("r3964: " format "\n" , ## args); | 99 | #define TRACE_PE(format, args...) printk("r3964: " format "\n" , ## args) |
103 | #else | 100 | #else |
104 | #define TRACE_PE(fmt, arg...) /**/ | 101 | #define TRACE_PE(fmt, arg...) do {} while (0) |
105 | #endif | 102 | #endif |
106 | |||
107 | #ifdef DEBUG_LDISC | 103 | #ifdef DEBUG_LDISC |
108 | #define TRACE_L(format, args...) printk("r3964: " format "\n" , ## args); | 104 | #define TRACE_L(format, args...) printk("r3964: " format "\n" , ## args) |
109 | #else | 105 | #else |
110 | #define TRACE_L(fmt, arg...) /**/ | 106 | #define TRACE_L(fmt, arg...) do {} while (0) |
111 | #endif | 107 | #endif |
112 | |||
113 | #ifdef DEBUG_QUEUE | 108 | #ifdef DEBUG_QUEUE |
114 | #define TRACE_Q(format, args...) printk("r3964: " format "\n" , ## args); | 109 | #define TRACE_Q(format, args...) printk("r3964: " format "\n" , ## args) |
115 | #else | 110 | #else |
116 | #define TRACE_Q(fmt, arg...) /**/ | 111 | #define TRACE_Q(fmt, arg...) do {} while (0) |
117 | #endif | 112 | #endif |
118 | |||
119 | static void add_tx_queue(struct r3964_info *, struct r3964_block_header *); | 113 | static void add_tx_queue(struct r3964_info *, struct r3964_block_header *); |
120 | static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code); | 114 | static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code); |
121 | static void put_char(struct r3964_info *pInfo, unsigned char ch); | 115 | static void put_char(struct r3964_info *pInfo, unsigned char ch); |
@@ -126,937 +120,830 @@ static void receive_char(struct r3964_info *pInfo, const unsigned char c); | |||
126 | static void receive_error(struct r3964_info *pInfo, const char flag); | 120 | static void receive_error(struct r3964_info *pInfo, const char flag); |
127 | static void on_timeout(unsigned long priv); | 121 | static void on_timeout(unsigned long priv); |
128 | static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg); | 122 | static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg); |
129 | static int read_telegram(struct r3964_info *pInfo, struct pid *pid, unsigned char __user *buf); | 123 | static int read_telegram(struct r3964_info *pInfo, struct pid *pid, |
124 | unsigned char __user * buf); | ||
130 | static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg, | 125 | static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg, |
131 | int error_code, struct r3964_block_header *pBlock); | 126 | int error_code, struct r3964_block_header *pBlock); |
132 | static struct r3964_message* remove_msg(struct r3964_info *pInfo, | 127 | static struct r3964_message *remove_msg(struct r3964_info *pInfo, |
133 | struct r3964_client_info *pClient); | 128 | struct r3964_client_info *pClient); |
134 | static void remove_client_block(struct r3964_info *pInfo, | 129 | static void remove_client_block(struct r3964_info *pInfo, |
135 | struct r3964_client_info *pClient); | 130 | struct r3964_client_info *pClient); |
136 | 131 | ||
137 | static int r3964_open(struct tty_struct *tty); | 132 | static int r3964_open(struct tty_struct *tty); |
138 | static void r3964_close(struct tty_struct *tty); | 133 | static void r3964_close(struct tty_struct *tty); |
139 | static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | 134 | static ssize_t r3964_read(struct tty_struct *tty, struct file *file, |
140 | unsigned char __user *buf, size_t nr); | 135 | unsigned char __user * buf, size_t nr); |
141 | static ssize_t r3964_write(struct tty_struct * tty, struct file * file, | 136 | static ssize_t r3964_write(struct tty_struct *tty, struct file *file, |
142 | const unsigned char * buf, size_t nr); | 137 | const unsigned char *buf, size_t nr); |
143 | static int r3964_ioctl(struct tty_struct * tty, struct file * file, | 138 | static int r3964_ioctl(struct tty_struct *tty, struct file *file, |
144 | unsigned int cmd, unsigned long arg); | 139 | unsigned int cmd, unsigned long arg); |
145 | static void r3964_set_termios(struct tty_struct *tty, struct ktermios * old); | 140 | static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old); |
146 | static unsigned int r3964_poll(struct tty_struct * tty, struct file * file, | 141 | static unsigned int r3964_poll(struct tty_struct *tty, struct file *file, |
147 | struct poll_table_struct *wait); | 142 | struct poll_table_struct *wait); |
148 | static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, | 143 | static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, |
149 | char *fp, int count); | 144 | char *fp, int count); |
150 | 145 | ||
151 | static struct tty_ldisc tty_ldisc_N_R3964 = { | 146 | static struct tty_ldisc tty_ldisc_N_R3964 = { |
152 | .owner = THIS_MODULE, | 147 | .owner = THIS_MODULE, |
153 | .magic = TTY_LDISC_MAGIC, | 148 | .magic = TTY_LDISC_MAGIC, |
154 | .name = "R3964", | 149 | .name = "R3964", |
155 | .open = r3964_open, | 150 | .open = r3964_open, |
156 | .close = r3964_close, | 151 | .close = r3964_close, |
157 | .read = r3964_read, | 152 | .read = r3964_read, |
158 | .write = r3964_write, | 153 | .write = r3964_write, |
159 | .ioctl = r3964_ioctl, | 154 | .ioctl = r3964_ioctl, |
160 | .set_termios = r3964_set_termios, | 155 | .set_termios = r3964_set_termios, |
161 | .poll = r3964_poll, | 156 | .poll = r3964_poll, |
162 | .receive_buf = r3964_receive_buf, | 157 | .receive_buf = r3964_receive_buf, |
163 | }; | 158 | }; |
164 | 159 | ||
165 | |||
166 | |||
167 | static void dump_block(const unsigned char *block, unsigned int length) | 160 | static void dump_block(const unsigned char *block, unsigned int length) |
168 | { | 161 | { |
169 | unsigned int i,j; | 162 | unsigned int i, j; |
170 | char linebuf[16*3+1]; | 163 | char linebuf[16 * 3 + 1]; |
171 | 164 | ||
172 | for(i=0;i<length;i+=16) | 165 | for (i = 0; i < length; i += 16) { |
173 | { | 166 | for (j = 0; (j < 16) && (j + i < length); j++) { |
174 | for(j=0;(j<16) && (j+i<length);j++) | 167 | sprintf(linebuf + 3 * j, "%02x ", block[i + j]); |
175 | { | 168 | } |
176 | sprintf(linebuf+3*j,"%02x ",block[i+j]); | 169 | linebuf[3 * j] = '\0'; |
177 | } | 170 | TRACE_PS("%s", linebuf); |
178 | linebuf[3*j]='\0'; | 171 | } |
179 | TRACE_PS("%s",linebuf); | ||
180 | } | ||
181 | } | 172 | } |
182 | 173 | ||
183 | |||
184 | |||
185 | |||
186 | /************************************************************* | 174 | /************************************************************* |
187 | * Driver initialisation | 175 | * Driver initialisation |
188 | *************************************************************/ | 176 | *************************************************************/ |
189 | 177 | ||
190 | |||
191 | /************************************************************* | 178 | /************************************************************* |
192 | * Module support routines | 179 | * Module support routines |
193 | *************************************************************/ | 180 | *************************************************************/ |
194 | 181 | ||
195 | static void __exit r3964_exit(void) | 182 | static void __exit r3964_exit(void) |
196 | { | 183 | { |
197 | int status; | 184 | int status; |
198 | 185 | ||
199 | TRACE_M ("cleanup_module()"); | 186 | TRACE_M("cleanup_module()"); |
200 | 187 | ||
201 | status=tty_unregister_ldisc(N_R3964); | 188 | status = tty_unregister_ldisc(N_R3964); |
202 | 189 | ||
203 | if(status!=0) | 190 | if (status != 0) { |
204 | { | 191 | printk(KERN_ERR "r3964: error unregistering linediscipline: " |
205 | printk(KERN_ERR "r3964: error unregistering linediscipline: %d\n", status); | 192 | "%d\n", status); |
206 | } | 193 | } else { |
207 | else | 194 | TRACE_L("linediscipline successfully unregistered"); |
208 | { | 195 | } |
209 | TRACE_L("linediscipline successfully unregistered"); | ||
210 | } | ||
211 | |||
212 | } | 196 | } |
213 | 197 | ||
214 | static int __init r3964_init(void) | 198 | static int __init r3964_init(void) |
215 | { | 199 | { |
216 | int status; | 200 | int status; |
217 | 201 | ||
218 | printk ("r3964: Philips r3964 Driver $Revision: 1.10 $\n"); | 202 | printk("r3964: Philips r3964 Driver $Revision: 1.10 $\n"); |
219 | 203 | ||
220 | /* | 204 | /* |
221 | * Register the tty line discipline | 205 | * Register the tty line discipline |
222 | */ | 206 | */ |
223 | 207 | ||
224 | status = tty_register_ldisc (N_R3964, &tty_ldisc_N_R3964); | 208 | status = tty_register_ldisc(N_R3964, &tty_ldisc_N_R3964); |
225 | if (status == 0) | 209 | if (status == 0) { |
226 | { | 210 | TRACE_L("line discipline %d registered", N_R3964); |
227 | TRACE_L("line discipline %d registered", N_R3964); | 211 | TRACE_L("flags=%x num=%x", tty_ldisc_N_R3964.flags, |
228 | TRACE_L("flags=%x num=%x", tty_ldisc_N_R3964.flags, | 212 | tty_ldisc_N_R3964.num); |
229 | tty_ldisc_N_R3964.num); | 213 | TRACE_L("open=%p", tty_ldisc_N_R3964.open); |
230 | TRACE_L("open=%p", tty_ldisc_N_R3964.open); | 214 | TRACE_L("tty_ldisc_N_R3964 = %p", &tty_ldisc_N_R3964); |
231 | TRACE_L("tty_ldisc_N_R3964 = %p", &tty_ldisc_N_R3964); | 215 | } else { |
232 | } | 216 | printk(KERN_ERR "r3964: error registering line discipline: " |
233 | else | 217 | "%d\n", status); |
234 | { | 218 | } |
235 | printk (KERN_ERR "r3964: error registering line discipline: %d\n", status); | 219 | return status; |
236 | } | ||
237 | return status; | ||
238 | } | 220 | } |
239 | 221 | ||
240 | module_init(r3964_init); | 222 | module_init(r3964_init); |
241 | module_exit(r3964_exit); | 223 | module_exit(r3964_exit); |
242 | 224 | ||
243 | |||
244 | /************************************************************* | 225 | /************************************************************* |
245 | * Protocol implementation routines | 226 | * Protocol implementation routines |
246 | *************************************************************/ | 227 | *************************************************************/ |
247 | 228 | ||
248 | static void add_tx_queue(struct r3964_info *pInfo, struct r3964_block_header *pHeader) | 229 | static void add_tx_queue(struct r3964_info *pInfo, |
230 | struct r3964_block_header *pHeader) | ||
249 | { | 231 | { |
250 | unsigned long flags; | 232 | unsigned long flags; |
251 | 233 | ||
252 | spin_lock_irqsave(&pInfo->lock, flags); | 234 | spin_lock_irqsave(&pInfo->lock, flags); |
253 | 235 | ||
254 | pHeader->next = NULL; | 236 | pHeader->next = NULL; |
255 | 237 | ||
256 | if(pInfo->tx_last == NULL) | 238 | if (pInfo->tx_last == NULL) { |
257 | { | 239 | pInfo->tx_first = pInfo->tx_last = pHeader; |
258 | pInfo->tx_first = pInfo->tx_last = pHeader; | 240 | } else { |
259 | } | 241 | pInfo->tx_last->next = pHeader; |
260 | else | 242 | pInfo->tx_last = pHeader; |
261 | { | 243 | } |
262 | pInfo->tx_last->next = pHeader; | 244 | |
263 | pInfo->tx_last = pHeader; | 245 | spin_unlock_irqrestore(&pInfo->lock, flags); |
264 | } | 246 | |
265 | 247 | TRACE_Q("add_tx_queue %p, length %d, tx_first = %p", | |
266 | spin_unlock_irqrestore(&pInfo->lock, flags); | 248 | pHeader, pHeader->length, pInfo->tx_first); |
267 | |||
268 | TRACE_Q("add_tx_queue %p, length %d, tx_first = %p", | ||
269 | pHeader, pHeader->length, pInfo->tx_first ); | ||
270 | } | 249 | } |
271 | 250 | ||
272 | static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code) | 251 | static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code) |
273 | { | 252 | { |
274 | struct r3964_block_header *pHeader; | 253 | struct r3964_block_header *pHeader; |
275 | unsigned long flags; | 254 | unsigned long flags; |
276 | #ifdef DEBUG_QUEUE | 255 | #ifdef DEBUG_QUEUE |
277 | struct r3964_block_header *pDump; | 256 | struct r3964_block_header *pDump; |
278 | #endif | 257 | #endif |
279 | |||
280 | pHeader = pInfo->tx_first; | ||
281 | 258 | ||
282 | if(pHeader==NULL) | 259 | pHeader = pInfo->tx_first; |
283 | return; | 260 | |
261 | if (pHeader == NULL) | ||
262 | return; | ||
284 | 263 | ||
285 | #ifdef DEBUG_QUEUE | 264 | #ifdef DEBUG_QUEUE |
286 | printk("r3964: remove_from_tx_queue: %p, length %u - ", | 265 | printk("r3964: remove_from_tx_queue: %p, length %u - ", |
287 | pHeader, pHeader->length ); | 266 | pHeader, pHeader->length); |
288 | for(pDump=pHeader;pDump;pDump=pDump->next) | 267 | for (pDump = pHeader; pDump; pDump = pDump->next) |
289 | printk("%p ", pDump); | 268 | printk("%p ", pDump); |
290 | printk("\n"); | 269 | printk("\n"); |
291 | #endif | 270 | #endif |
292 | 271 | ||
272 | if (pHeader->owner) { | ||
273 | if (error_code) { | ||
274 | add_msg(pHeader->owner, R3964_MSG_ACK, 0, | ||
275 | error_code, NULL); | ||
276 | } else { | ||
277 | add_msg(pHeader->owner, R3964_MSG_ACK, pHeader->length, | ||
278 | error_code, NULL); | ||
279 | } | ||
280 | wake_up_interruptible(&pInfo->read_wait); | ||
281 | } | ||
282 | |||
283 | spin_lock_irqsave(&pInfo->lock, flags); | ||
284 | |||
285 | pInfo->tx_first = pHeader->next; | ||
286 | if (pInfo->tx_first == NULL) { | ||
287 | pInfo->tx_last = NULL; | ||
288 | } | ||
289 | |||
290 | spin_unlock_irqrestore(&pInfo->lock, flags); | ||
291 | |||
292 | kfree(pHeader); | ||
293 | TRACE_M("remove_from_tx_queue - kfree %p", pHeader); | ||
293 | 294 | ||
294 | if(pHeader->owner) | 295 | TRACE_Q("remove_from_tx_queue: tx_first = %p, tx_last = %p", |
295 | { | 296 | pInfo->tx_first, pInfo->tx_last); |
296 | if(error_code) | ||
297 | { | ||
298 | add_msg(pHeader->owner, R3964_MSG_ACK, 0, | ||
299 | error_code, NULL); | ||
300 | } | ||
301 | else | ||
302 | { | ||
303 | add_msg(pHeader->owner, R3964_MSG_ACK, pHeader->length, | ||
304 | error_code, NULL); | ||
305 | } | ||
306 | wake_up_interruptible (&pInfo->read_wait); | ||
307 | } | ||
308 | |||
309 | spin_lock_irqsave(&pInfo->lock, flags); | ||
310 | |||
311 | pInfo->tx_first = pHeader->next; | ||
312 | if(pInfo->tx_first==NULL) | ||
313 | { | ||
314 | pInfo->tx_last = NULL; | ||
315 | } | ||
316 | |||
317 | spin_unlock_irqrestore(&pInfo->lock, flags); | ||
318 | |||
319 | kfree(pHeader); | ||
320 | TRACE_M("remove_from_tx_queue - kfree %p",pHeader); | ||
321 | |||
322 | TRACE_Q("remove_from_tx_queue: tx_first = %p, tx_last = %p", | ||
323 | pInfo->tx_first, pInfo->tx_last ); | ||
324 | } | 297 | } |
325 | 298 | ||
326 | static void add_rx_queue(struct r3964_info *pInfo, struct r3964_block_header *pHeader) | 299 | static void add_rx_queue(struct r3964_info *pInfo, |
300 | struct r3964_block_header *pHeader) | ||
327 | { | 301 | { |
328 | unsigned long flags; | 302 | unsigned long flags; |
329 | 303 | ||
330 | spin_lock_irqsave(&pInfo->lock, flags); | 304 | spin_lock_irqsave(&pInfo->lock, flags); |
331 | 305 | ||
332 | pHeader->next = NULL; | 306 | pHeader->next = NULL; |
333 | 307 | ||
334 | if(pInfo->rx_last == NULL) | 308 | if (pInfo->rx_last == NULL) { |
335 | { | 309 | pInfo->rx_first = pInfo->rx_last = pHeader; |
336 | pInfo->rx_first = pInfo->rx_last = pHeader; | 310 | } else { |
337 | } | 311 | pInfo->rx_last->next = pHeader; |
338 | else | 312 | pInfo->rx_last = pHeader; |
339 | { | 313 | } |
340 | pInfo->rx_last->next = pHeader; | 314 | pInfo->blocks_in_rx_queue++; |
341 | pInfo->rx_last = pHeader; | 315 | |
342 | } | 316 | spin_unlock_irqrestore(&pInfo->lock, flags); |
343 | pInfo->blocks_in_rx_queue++; | 317 | |
344 | 318 | TRACE_Q("add_rx_queue: %p, length = %d, rx_first = %p, count = %d", | |
345 | spin_unlock_irqrestore(&pInfo->lock, flags); | 319 | pHeader, pHeader->length, |
346 | 320 | pInfo->rx_first, pInfo->blocks_in_rx_queue); | |
347 | TRACE_Q("add_rx_queue: %p, length = %d, rx_first = %p, count = %d", | ||
348 | pHeader, pHeader->length, | ||
349 | pInfo->rx_first, pInfo->blocks_in_rx_queue); | ||
350 | } | 321 | } |
351 | 322 | ||
352 | static void remove_from_rx_queue(struct r3964_info *pInfo, | 323 | static void remove_from_rx_queue(struct r3964_info *pInfo, |
353 | struct r3964_block_header *pHeader) | 324 | struct r3964_block_header *pHeader) |
354 | { | 325 | { |
355 | unsigned long flags; | 326 | unsigned long flags; |
356 | struct r3964_block_header *pFind; | 327 | struct r3964_block_header *pFind; |
357 | 328 | ||
358 | if(pHeader==NULL) | 329 | if (pHeader == NULL) |
359 | return; | 330 | return; |
360 | 331 | ||
361 | TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d", | 332 | TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d", |
362 | pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue ); | 333 | pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue); |
363 | TRACE_Q("remove_from_rx_queue: %p, length %u", | 334 | TRACE_Q("remove_from_rx_queue: %p, length %u", |
364 | pHeader, pHeader->length ); | 335 | pHeader, pHeader->length); |
365 | 336 | ||
366 | spin_lock_irqsave(&pInfo->lock, flags); | 337 | spin_lock_irqsave(&pInfo->lock, flags); |
367 | 338 | ||
368 | if(pInfo->rx_first == pHeader) | 339 | if (pInfo->rx_first == pHeader) { |
369 | { | 340 | /* Remove the first block in the linked list: */ |
370 | /* Remove the first block in the linked list: */ | 341 | pInfo->rx_first = pHeader->next; |
371 | pInfo->rx_first = pHeader->next; | 342 | |
372 | 343 | if (pInfo->rx_first == NULL) { | |
373 | if(pInfo->rx_first==NULL) | 344 | pInfo->rx_last = NULL; |
374 | { | 345 | } |
375 | pInfo->rx_last = NULL; | 346 | pInfo->blocks_in_rx_queue--; |
376 | } | 347 | } else { |
377 | pInfo->blocks_in_rx_queue--; | 348 | /* Find block to remove: */ |
378 | } | 349 | for (pFind = pInfo->rx_first; pFind; pFind = pFind->next) { |
379 | else | 350 | if (pFind->next == pHeader) { |
380 | { | 351 | /* Got it. */ |
381 | /* Find block to remove: */ | 352 | pFind->next = pHeader->next; |
382 | for(pFind=pInfo->rx_first; pFind; pFind=pFind->next) | 353 | pInfo->blocks_in_rx_queue--; |
383 | { | 354 | if (pFind->next == NULL) { |
384 | if(pFind->next == pHeader) | 355 | /* Oh, removed the last one! */ |
385 | { | 356 | pInfo->rx_last = pFind; |
386 | /* Got it. */ | 357 | } |
387 | pFind->next = pHeader->next; | 358 | break; |
388 | pInfo->blocks_in_rx_queue--; | 359 | } |
389 | if(pFind->next==NULL) | 360 | } |
390 | { | 361 | } |
391 | /* Oh, removed the last one! */ | 362 | |
392 | pInfo->rx_last = pFind; | 363 | spin_unlock_irqrestore(&pInfo->lock, flags); |
393 | } | 364 | |
394 | break; | 365 | kfree(pHeader); |
395 | } | 366 | TRACE_M("remove_from_rx_queue - kfree %p", pHeader); |
396 | } | 367 | |
397 | } | 368 | TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d", |
398 | 369 | pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue); | |
399 | spin_unlock_irqrestore(&pInfo->lock, flags); | ||
400 | |||
401 | kfree(pHeader); | ||
402 | TRACE_M("remove_from_rx_queue - kfree %p",pHeader); | ||
403 | |||
404 | TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d", | ||
405 | pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue ); | ||
406 | } | 370 | } |
407 | 371 | ||
408 | static void put_char(struct r3964_info *pInfo, unsigned char ch) | 372 | static void put_char(struct r3964_info *pInfo, unsigned char ch) |
409 | { | 373 | { |
410 | struct tty_struct *tty = pInfo->tty; | 374 | struct tty_struct *tty = pInfo->tty; |
411 | 375 | ||
412 | if(tty==NULL) | 376 | if (tty == NULL) |
413 | return; | 377 | return; |
414 | 378 | ||
415 | if(tty->driver->put_char) | 379 | if (tty->driver->put_char) { |
416 | { | 380 | tty->driver->put_char(tty, ch); |
417 | tty->driver->put_char(tty, ch); | 381 | } |
418 | } | 382 | pInfo->bcc ^= ch; |
419 | pInfo->bcc ^= ch; | ||
420 | } | 383 | } |
421 | 384 | ||
422 | static void flush(struct r3964_info *pInfo) | 385 | static void flush(struct r3964_info *pInfo) |
423 | { | 386 | { |
424 | struct tty_struct *tty = pInfo->tty; | 387 | struct tty_struct *tty = pInfo->tty; |
425 | 388 | ||
426 | if(tty==NULL) | 389 | if (tty == NULL) |
427 | return; | 390 | return; |
428 | 391 | ||
429 | if(tty->driver->flush_chars) | 392 | if (tty->driver->flush_chars) { |
430 | { | 393 | tty->driver->flush_chars(tty); |
431 | tty->driver->flush_chars(tty); | 394 | } |
432 | } | ||
433 | } | 395 | } |
434 | 396 | ||
435 | static void trigger_transmit(struct r3964_info *pInfo) | 397 | static void trigger_transmit(struct r3964_info *pInfo) |
436 | { | 398 | { |
437 | unsigned long flags; | 399 | unsigned long flags; |
438 | |||
439 | 400 | ||
440 | spin_lock_irqsave(&pInfo->lock, flags); | 401 | spin_lock_irqsave(&pInfo->lock, flags); |
441 | 402 | ||
442 | if((pInfo->state == R3964_IDLE) && (pInfo->tx_first!=NULL)) | 403 | if ((pInfo->state == R3964_IDLE) && (pInfo->tx_first != NULL)) { |
443 | { | 404 | pInfo->state = R3964_TX_REQUEST; |
444 | pInfo->state = R3964_TX_REQUEST; | 405 | pInfo->nRetry = 0; |
445 | pInfo->nRetry=0; | 406 | pInfo->flags &= ~R3964_ERROR; |
446 | pInfo->flags &= ~R3964_ERROR; | 407 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); |
447 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); | ||
448 | 408 | ||
449 | spin_unlock_irqrestore(&pInfo->lock, flags); | 409 | spin_unlock_irqrestore(&pInfo->lock, flags); |
450 | 410 | ||
451 | TRACE_PS("trigger_transmit - sent STX"); | 411 | TRACE_PS("trigger_transmit - sent STX"); |
452 | 412 | ||
453 | put_char(pInfo, STX); | 413 | put_char(pInfo, STX); |
454 | flush(pInfo); | 414 | flush(pInfo); |
455 | 415 | ||
456 | pInfo->bcc = 0; | 416 | pInfo->bcc = 0; |
457 | } | 417 | } else { |
458 | else | 418 | spin_unlock_irqrestore(&pInfo->lock, flags); |
459 | { | 419 | } |
460 | spin_unlock_irqrestore(&pInfo->lock, flags); | ||
461 | } | ||
462 | } | 420 | } |
463 | 421 | ||
464 | static void retry_transmit(struct r3964_info *pInfo) | 422 | static void retry_transmit(struct r3964_info *pInfo) |
465 | { | 423 | { |
466 | if(pInfo->nRetry<R3964_MAX_RETRIES) | 424 | if (pInfo->nRetry < R3964_MAX_RETRIES) { |
467 | { | 425 | TRACE_PE("transmission failed. Retry #%d", pInfo->nRetry); |
468 | TRACE_PE("transmission failed. Retry #%d", | 426 | pInfo->bcc = 0; |
469 | pInfo->nRetry); | 427 | put_char(pInfo, STX); |
470 | pInfo->bcc = 0; | 428 | flush(pInfo); |
471 | put_char(pInfo, STX); | 429 | pInfo->state = R3964_TX_REQUEST; |
472 | flush(pInfo); | 430 | pInfo->nRetry++; |
473 | pInfo->state = R3964_TX_REQUEST; | 431 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); |
474 | pInfo->nRetry++; | 432 | } else { |
475 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); | 433 | TRACE_PE("transmission failed after %d retries", |
476 | } | 434 | R3964_MAX_RETRIES); |
477 | else | 435 | |
478 | { | 436 | remove_from_tx_queue(pInfo, R3964_TX_FAIL); |
479 | TRACE_PE("transmission failed after %d retries", | 437 | |
480 | R3964_MAX_RETRIES); | 438 | put_char(pInfo, NAK); |
481 | 439 | flush(pInfo); | |
482 | remove_from_tx_queue(pInfo, R3964_TX_FAIL); | 440 | pInfo->state = R3964_IDLE; |
483 | 441 | ||
484 | put_char(pInfo, NAK); | 442 | trigger_transmit(pInfo); |
485 | flush(pInfo); | 443 | } |
486 | pInfo->state = R3964_IDLE; | ||
487 | |||
488 | trigger_transmit(pInfo); | ||
489 | } | ||
490 | } | 444 | } |
491 | 445 | ||
492 | |||
493 | static void transmit_block(struct r3964_info *pInfo) | 446 | static void transmit_block(struct r3964_info *pInfo) |
494 | { | 447 | { |
495 | struct tty_struct *tty = pInfo->tty; | 448 | struct tty_struct *tty = pInfo->tty; |
496 | struct r3964_block_header *pBlock = pInfo->tx_first; | 449 | struct r3964_block_header *pBlock = pInfo->tx_first; |
497 | int room=0; | 450 | int room = 0; |
498 | 451 | ||
499 | if((tty==NULL) || (pBlock==NULL)) | 452 | if ((tty == NULL) || (pBlock == NULL)) { |
500 | { | 453 | return; |
501 | return; | 454 | } |
502 | } | 455 | |
503 | 456 | if (tty->driver->write_room) | |
504 | if(tty->driver->write_room) | 457 | room = tty->driver->write_room(tty); |
505 | room=tty->driver->write_room(tty); | 458 | |
506 | 459 | TRACE_PS("transmit_block %p, room %d, length %d", | |
507 | TRACE_PS("transmit_block %p, room %d, length %d", | 460 | pBlock, room, pBlock->length); |
508 | pBlock, room, pBlock->length); | 461 | |
509 | 462 | while (pInfo->tx_position < pBlock->length) { | |
510 | while(pInfo->tx_position < pBlock->length) | 463 | if (room < 2) |
511 | { | 464 | break; |
512 | if(room<2) | 465 | |
513 | break; | 466 | if (pBlock->data[pInfo->tx_position] == DLE) { |
514 | 467 | /* send additional DLE char: */ | |
515 | if(pBlock->data[pInfo->tx_position]==DLE) | 468 | put_char(pInfo, DLE); |
516 | { | 469 | } |
517 | /* send additional DLE char: */ | 470 | put_char(pInfo, pBlock->data[pInfo->tx_position++]); |
518 | put_char(pInfo, DLE); | 471 | |
519 | } | 472 | room--; |
520 | put_char(pInfo, pBlock->data[pInfo->tx_position++]); | 473 | } |
521 | 474 | ||
522 | room--; | 475 | if ((pInfo->tx_position == pBlock->length) && (room >= 3)) { |
523 | } | 476 | put_char(pInfo, DLE); |
524 | 477 | put_char(pInfo, ETX); | |
525 | if((pInfo->tx_position == pBlock->length) && (room>=3)) | 478 | if (pInfo->flags & R3964_BCC) { |
526 | { | 479 | put_char(pInfo, pInfo->bcc); |
527 | put_char(pInfo, DLE); | 480 | } |
528 | put_char(pInfo, ETX); | 481 | pInfo->state = R3964_WAIT_FOR_TX_ACK; |
529 | if(pInfo->flags & R3964_BCC) | 482 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); |
530 | { | 483 | } |
531 | put_char(pInfo, pInfo->bcc); | 484 | flush(pInfo); |
532 | } | ||
533 | pInfo->state = R3964_WAIT_FOR_TX_ACK; | ||
534 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); | ||
535 | } | ||
536 | flush(pInfo); | ||
537 | } | 485 | } |
538 | 486 | ||
539 | static void on_receive_block(struct r3964_info *pInfo) | 487 | static void on_receive_block(struct r3964_info *pInfo) |
540 | { | 488 | { |
541 | unsigned int length; | 489 | unsigned int length; |
542 | struct r3964_client_info *pClient; | 490 | struct r3964_client_info *pClient; |
543 | struct r3964_block_header *pBlock; | 491 | struct r3964_block_header *pBlock; |
544 | 492 | ||
545 | length=pInfo->rx_position; | 493 | length = pInfo->rx_position; |
546 | 494 | ||
547 | /* compare byte checksum characters: */ | 495 | /* compare byte checksum characters: */ |
548 | if(pInfo->flags & R3964_BCC) | 496 | if (pInfo->flags & R3964_BCC) { |
549 | { | 497 | if (pInfo->bcc != pInfo->last_rx) { |
550 | if(pInfo->bcc!=pInfo->last_rx) | 498 | TRACE_PE("checksum error - got %x but expected %x", |
551 | { | 499 | pInfo->last_rx, pInfo->bcc); |
552 | TRACE_PE("checksum error - got %x but expected %x", | 500 | pInfo->flags |= R3964_CHECKSUM; |
553 | pInfo->last_rx, pInfo->bcc); | 501 | } |
554 | pInfo->flags |= R3964_CHECKSUM; | 502 | } |
555 | } | 503 | |
556 | } | 504 | /* check for errors (parity, overrun,...): */ |
557 | 505 | if (pInfo->flags & R3964_ERROR) { | |
558 | /* check for errors (parity, overrun,...): */ | 506 | TRACE_PE("on_receive_block - transmission failed error %x", |
559 | if(pInfo->flags & R3964_ERROR) | 507 | pInfo->flags & R3964_ERROR); |
560 | { | 508 | |
561 | TRACE_PE("on_receive_block - transmission failed error %x", | 509 | put_char(pInfo, NAK); |
562 | pInfo->flags & R3964_ERROR); | 510 | flush(pInfo); |
563 | 511 | if (pInfo->nRetry < R3964_MAX_RETRIES) { | |
564 | put_char(pInfo, NAK); | 512 | pInfo->state = R3964_WAIT_FOR_RX_REPEAT; |
565 | flush(pInfo); | 513 | pInfo->nRetry++; |
566 | if(pInfo->nRetry<R3964_MAX_RETRIES) | 514 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_RX_PANIC); |
567 | { | 515 | } else { |
568 | pInfo->state=R3964_WAIT_FOR_RX_REPEAT; | 516 | TRACE_PE("on_receive_block - failed after max retries"); |
569 | pInfo->nRetry++; | 517 | pInfo->state = R3964_IDLE; |
570 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_RX_PANIC); | 518 | } |
571 | } | 519 | return; |
572 | else | 520 | } |
573 | { | 521 | |
574 | TRACE_PE("on_receive_block - failed after max retries"); | 522 | /* received block; submit DLE: */ |
575 | pInfo->state=R3964_IDLE; | 523 | put_char(pInfo, DLE); |
576 | } | 524 | flush(pInfo); |
577 | return; | 525 | del_timer_sync(&pInfo->tmr); |
578 | } | 526 | TRACE_PS(" rx success: got %d chars", length); |
579 | 527 | ||
580 | 528 | /* prepare struct r3964_block_header: */ | |
581 | /* received block; submit DLE: */ | 529 | pBlock = kmalloc(length + sizeof(struct r3964_block_header), |
582 | put_char(pInfo, DLE); | 530 | GFP_KERNEL); |
583 | flush(pInfo); | 531 | TRACE_M("on_receive_block - kmalloc %p", pBlock); |
584 | del_timer_sync(&pInfo->tmr); | 532 | |
585 | TRACE_PS(" rx success: got %d chars", length); | 533 | if (pBlock == NULL) |
586 | 534 | return; | |
587 | /* prepare struct r3964_block_header: */ | 535 | |
588 | pBlock = kmalloc(length+sizeof(struct r3964_block_header), GFP_KERNEL); | 536 | pBlock->length = length; |
589 | TRACE_M("on_receive_block - kmalloc %p",pBlock); | 537 | pBlock->data = ((unsigned char *)pBlock) + |
590 | 538 | sizeof(struct r3964_block_header); | |
591 | if(pBlock==NULL) | 539 | pBlock->locks = 0; |
592 | return; | 540 | pBlock->next = NULL; |
593 | 541 | pBlock->owner = NULL; | |
594 | pBlock->length = length; | 542 | |
595 | pBlock->data = ((unsigned char*)pBlock)+sizeof(struct r3964_block_header); | 543 | memcpy(pBlock->data, pInfo->rx_buf, length); |
596 | pBlock->locks = 0; | 544 | |
597 | pBlock->next = NULL; | 545 | /* queue block into rx_queue: */ |
598 | pBlock->owner = NULL; | 546 | add_rx_queue(pInfo, pBlock); |
599 | 547 | ||
600 | memcpy(pBlock->data, pInfo->rx_buf, length); | 548 | /* notify attached client processes: */ |
601 | 549 | for (pClient = pInfo->firstClient; pClient; pClient = pClient->next) { | |
602 | /* queue block into rx_queue: */ | 550 | if (pClient->sig_flags & R3964_SIG_DATA) { |
603 | add_rx_queue(pInfo, pBlock); | 551 | add_msg(pClient, R3964_MSG_DATA, length, R3964_OK, |
604 | 552 | pBlock); | |
605 | /* notify attached client processes: */ | 553 | } |
606 | for(pClient=pInfo->firstClient; pClient; pClient=pClient->next) | 554 | } |
607 | { | 555 | wake_up_interruptible(&pInfo->read_wait); |
608 | if(pClient->sig_flags & R3964_SIG_DATA) | ||
609 | { | ||
610 | add_msg(pClient, R3964_MSG_DATA, length, R3964_OK, pBlock); | ||
611 | } | ||
612 | } | ||
613 | wake_up_interruptible (&pInfo->read_wait); | ||
614 | |||
615 | pInfo->state = R3964_IDLE; | ||
616 | |||
617 | trigger_transmit(pInfo); | ||
618 | } | ||
619 | 556 | ||
557 | pInfo->state = R3964_IDLE; | ||
558 | |||
559 | trigger_transmit(pInfo); | ||
560 | } | ||
620 | 561 | ||
621 | static void receive_char(struct r3964_info *pInfo, const unsigned char c) | 562 | static void receive_char(struct r3964_info *pInfo, const unsigned char c) |
622 | { | 563 | { |
623 | switch(pInfo->state) | 564 | switch (pInfo->state) { |
624 | { | 565 | case R3964_TX_REQUEST: |
625 | case R3964_TX_REQUEST: | 566 | if (c == DLE) { |
626 | if(c==DLE) | 567 | TRACE_PS("TX_REQUEST - got DLE"); |
627 | { | 568 | |
628 | TRACE_PS("TX_REQUEST - got DLE"); | 569 | pInfo->state = R3964_TRANSMITTING; |
629 | 570 | pInfo->tx_position = 0; | |
630 | pInfo->state = R3964_TRANSMITTING; | 571 | |
631 | pInfo->tx_position = 0; | 572 | transmit_block(pInfo); |
632 | 573 | } else if (c == STX) { | |
633 | transmit_block(pInfo); | 574 | if (pInfo->nRetry == 0) { |
634 | } | 575 | TRACE_PE("TX_REQUEST - init conflict"); |
635 | else if(c==STX) | 576 | if (pInfo->priority == R3964_SLAVE) { |
636 | { | 577 | goto start_receiving; |
637 | if(pInfo->nRetry==0) | 578 | } |
638 | { | 579 | } else { |
639 | TRACE_PE("TX_REQUEST - init conflict"); | 580 | TRACE_PE("TX_REQUEST - secondary init " |
640 | if(pInfo->priority == R3964_SLAVE) | 581 | "conflict!? Switching to SLAVE mode " |
641 | { | 582 | "for next rx."); |
642 | goto start_receiving; | 583 | goto start_receiving; |
643 | } | 584 | } |
644 | } | 585 | } else { |
645 | else | 586 | TRACE_PE("TX_REQUEST - char != DLE: %x", c); |
646 | { | 587 | retry_transmit(pInfo); |
647 | TRACE_PE("TX_REQUEST - secondary init conflict!?" | 588 | } |
648 | " Switching to SLAVE mode for next rx."); | 589 | break; |
649 | goto start_receiving; | 590 | case R3964_TRANSMITTING: |
650 | } | 591 | if (c == NAK) { |
651 | } | 592 | TRACE_PE("TRANSMITTING - got NAK"); |
652 | else | 593 | retry_transmit(pInfo); |
653 | { | 594 | } else { |
654 | TRACE_PE("TX_REQUEST - char != DLE: %x", c); | 595 | TRACE_PE("TRANSMITTING - got invalid char"); |
655 | retry_transmit(pInfo); | 596 | |
656 | } | 597 | pInfo->state = R3964_WAIT_ZVZ_BEFORE_TX_RETRY; |
657 | break; | 598 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); |
658 | case R3964_TRANSMITTING: | 599 | } |
659 | if(c==NAK) | 600 | break; |
660 | { | 601 | case R3964_WAIT_FOR_TX_ACK: |
661 | TRACE_PE("TRANSMITTING - got NAK"); | 602 | if (c == DLE) { |
662 | retry_transmit(pInfo); | 603 | TRACE_PS("WAIT_FOR_TX_ACK - got DLE"); |
663 | } | 604 | remove_from_tx_queue(pInfo, R3964_OK); |
664 | else | 605 | |
665 | { | 606 | pInfo->state = R3964_IDLE; |
666 | TRACE_PE("TRANSMITTING - got invalid char"); | 607 | trigger_transmit(pInfo); |
667 | 608 | } else { | |
668 | pInfo->state = R3964_WAIT_ZVZ_BEFORE_TX_RETRY; | 609 | retry_transmit(pInfo); |
669 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); | 610 | } |
670 | } | 611 | break; |
671 | break; | 612 | case R3964_WAIT_FOR_RX_REPEAT: |
672 | case R3964_WAIT_FOR_TX_ACK: | 613 | /* FALLTROUGH */ |
673 | if(c==DLE) | 614 | case R3964_IDLE: |
674 | { | 615 | if (c == STX) { |
675 | TRACE_PS("WAIT_FOR_TX_ACK - got DLE"); | 616 | /* Prevent rx_queue from overflow: */ |
676 | remove_from_tx_queue(pInfo, R3964_OK); | 617 | if (pInfo->blocks_in_rx_queue >= |
677 | 618 | R3964_MAX_BLOCKS_IN_RX_QUEUE) { | |
678 | pInfo->state = R3964_IDLE; | 619 | TRACE_PE("IDLE - got STX but no space in " |
679 | trigger_transmit(pInfo); | 620 | "rx_queue!"); |
680 | } | 621 | pInfo->state = R3964_WAIT_FOR_RX_BUF; |
681 | else | 622 | mod_timer(&pInfo->tmr, |
682 | { | 623 | jiffies + R3964_TO_NO_BUF); |
683 | retry_transmit(pInfo); | 624 | break; |
684 | } | 625 | } |
685 | break; | ||
686 | case R3964_WAIT_FOR_RX_REPEAT: | ||
687 | /* FALLTROUGH */ | ||
688 | case R3964_IDLE: | ||
689 | if(c==STX) | ||
690 | { | ||
691 | /* Prevent rx_queue from overflow: */ | ||
692 | if(pInfo->blocks_in_rx_queue >= R3964_MAX_BLOCKS_IN_RX_QUEUE) | ||
693 | { | ||
694 | TRACE_PE("IDLE - got STX but no space in rx_queue!"); | ||
695 | pInfo->state=R3964_WAIT_FOR_RX_BUF; | ||
696 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_NO_BUF); | ||
697 | break; | ||
698 | } | ||
699 | start_receiving: | 626 | start_receiving: |
700 | /* Ok, start receiving: */ | 627 | /* Ok, start receiving: */ |
701 | TRACE_PS("IDLE - got STX"); | 628 | TRACE_PS("IDLE - got STX"); |
702 | pInfo->rx_position = 0; | 629 | pInfo->rx_position = 0; |
703 | pInfo->last_rx = 0; | 630 | pInfo->last_rx = 0; |
704 | pInfo->flags &= ~R3964_ERROR; | 631 | pInfo->flags &= ~R3964_ERROR; |
705 | pInfo->state=R3964_RECEIVING; | 632 | pInfo->state = R3964_RECEIVING; |
706 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); | 633 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); |
707 | pInfo->nRetry = 0; | 634 | pInfo->nRetry = 0; |
708 | put_char(pInfo, DLE); | 635 | put_char(pInfo, DLE); |
709 | flush(pInfo); | 636 | flush(pInfo); |
710 | pInfo->bcc = 0; | 637 | pInfo->bcc = 0; |
711 | } | 638 | } |
712 | break; | 639 | break; |
713 | case R3964_RECEIVING: | 640 | case R3964_RECEIVING: |
714 | if(pInfo->rx_position < RX_BUF_SIZE) | 641 | if (pInfo->rx_position < RX_BUF_SIZE) { |
715 | { | 642 | pInfo->bcc ^= c; |
716 | pInfo->bcc ^= c; | 643 | |
717 | 644 | if (c == DLE) { | |
718 | if(c==DLE) | 645 | if (pInfo->last_rx == DLE) { |
719 | { | 646 | pInfo->last_rx = 0; |
720 | if(pInfo->last_rx==DLE) | 647 | goto char_to_buf; |
721 | { | 648 | } |
722 | pInfo->last_rx = 0; | 649 | pInfo->last_rx = DLE; |
723 | goto char_to_buf; | 650 | break; |
724 | } | 651 | } else if ((c == ETX) && (pInfo->last_rx == DLE)) { |
725 | pInfo->last_rx = DLE; | 652 | if (pInfo->flags & R3964_BCC) { |
726 | break; | 653 | pInfo->state = R3964_WAIT_FOR_BCC; |
727 | } | 654 | mod_timer(&pInfo->tmr, |
728 | else if((c==ETX) && (pInfo->last_rx==DLE)) | 655 | jiffies + R3964_TO_ZVZ); |
729 | { | 656 | } else { |
730 | if(pInfo->flags & R3964_BCC) | 657 | on_receive_block(pInfo); |
731 | { | 658 | } |
732 | pInfo->state = R3964_WAIT_FOR_BCC; | 659 | } else { |
733 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); | 660 | pInfo->last_rx = c; |
734 | } | ||
735 | else | ||
736 | { | ||
737 | on_receive_block(pInfo); | ||
738 | } | ||
739 | } | ||
740 | else | ||
741 | { | ||
742 | pInfo->last_rx = c; | ||
743 | char_to_buf: | 661 | char_to_buf: |
744 | pInfo->rx_buf[pInfo->rx_position++] = c; | 662 | pInfo->rx_buf[pInfo->rx_position++] = c; |
745 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); | 663 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); |
746 | } | 664 | } |
747 | } | 665 | } |
748 | /* else: overflow-msg? BUF_SIZE>MTU; should not happen? */ | 666 | /* else: overflow-msg? BUF_SIZE>MTU; should not happen? */ |
749 | break; | 667 | break; |
750 | case R3964_WAIT_FOR_BCC: | 668 | case R3964_WAIT_FOR_BCC: |
751 | pInfo->last_rx = c; | 669 | pInfo->last_rx = c; |
752 | on_receive_block(pInfo); | 670 | on_receive_block(pInfo); |
753 | break; | 671 | break; |
754 | } | 672 | } |
755 | } | 673 | } |
756 | 674 | ||
757 | static void receive_error(struct r3964_info *pInfo, const char flag) | 675 | static void receive_error(struct r3964_info *pInfo, const char flag) |
758 | { | 676 | { |
759 | switch (flag) | 677 | switch (flag) { |
760 | { | 678 | case TTY_NORMAL: |
761 | case TTY_NORMAL: | 679 | break; |
762 | break; | 680 | case TTY_BREAK: |
763 | case TTY_BREAK: | 681 | TRACE_PE("received break"); |
764 | TRACE_PE("received break") | 682 | pInfo->flags |= R3964_BREAK; |
765 | pInfo->flags |= R3964_BREAK; | 683 | break; |
766 | break; | 684 | case TTY_PARITY: |
767 | case TTY_PARITY: | 685 | TRACE_PE("parity error"); |
768 | TRACE_PE("parity error") | 686 | pInfo->flags |= R3964_PARITY; |
769 | pInfo->flags |= R3964_PARITY; | 687 | break; |
770 | break; | 688 | case TTY_FRAME: |
771 | case TTY_FRAME: | 689 | TRACE_PE("frame error"); |
772 | TRACE_PE("frame error") | 690 | pInfo->flags |= R3964_FRAME; |
773 | pInfo->flags |= R3964_FRAME; | 691 | break; |
774 | break; | 692 | case TTY_OVERRUN: |
775 | case TTY_OVERRUN: | 693 | TRACE_PE("frame overrun"); |
776 | TRACE_PE("frame overrun") | 694 | pInfo->flags |= R3964_OVERRUN; |
777 | pInfo->flags |= R3964_OVERRUN; | 695 | break; |
778 | break; | 696 | default: |
779 | default: | 697 | TRACE_PE("receive_error - unknown flag %d", flag); |
780 | TRACE_PE("receive_error - unknown flag %d", flag); | 698 | pInfo->flags |= R3964_UNKNOWN; |
781 | pInfo->flags |= R3964_UNKNOWN; | 699 | break; |
782 | break; | 700 | } |
783 | } | ||
784 | } | 701 | } |
785 | 702 | ||
786 | static void on_timeout(unsigned long priv) | 703 | static void on_timeout(unsigned long priv) |
787 | { | 704 | { |
788 | struct r3964_info *pInfo = (void *)priv; | 705 | struct r3964_info *pInfo = (void *)priv; |
789 | 706 | ||
790 | switch(pInfo->state) | 707 | switch (pInfo->state) { |
791 | { | 708 | case R3964_TX_REQUEST: |
792 | case R3964_TX_REQUEST: | 709 | TRACE_PE("TX_REQUEST - timeout"); |
793 | TRACE_PE("TX_REQUEST - timeout"); | 710 | retry_transmit(pInfo); |
794 | retry_transmit(pInfo); | 711 | break; |
795 | break; | 712 | case R3964_WAIT_ZVZ_BEFORE_TX_RETRY: |
796 | case R3964_WAIT_ZVZ_BEFORE_TX_RETRY: | 713 | put_char(pInfo, NAK); |
797 | put_char(pInfo, NAK); | 714 | flush(pInfo); |
798 | flush(pInfo); | 715 | retry_transmit(pInfo); |
799 | retry_transmit(pInfo); | 716 | break; |
800 | break; | 717 | case R3964_WAIT_FOR_TX_ACK: |
801 | case R3964_WAIT_FOR_TX_ACK: | 718 | TRACE_PE("WAIT_FOR_TX_ACK - timeout"); |
802 | TRACE_PE("WAIT_FOR_TX_ACK - timeout"); | 719 | retry_transmit(pInfo); |
803 | retry_transmit(pInfo); | 720 | break; |
804 | break; | 721 | case R3964_WAIT_FOR_RX_BUF: |
805 | case R3964_WAIT_FOR_RX_BUF: | 722 | TRACE_PE("WAIT_FOR_RX_BUF - timeout"); |
806 | TRACE_PE("WAIT_FOR_RX_BUF - timeout"); | 723 | put_char(pInfo, NAK); |
807 | put_char(pInfo, NAK); | 724 | flush(pInfo); |
808 | flush(pInfo); | 725 | pInfo->state = R3964_IDLE; |
809 | pInfo->state=R3964_IDLE; | 726 | break; |
810 | break; | 727 | case R3964_RECEIVING: |
811 | case R3964_RECEIVING: | 728 | TRACE_PE("RECEIVING - timeout after %d chars", |
812 | TRACE_PE("RECEIVING - timeout after %d chars", | 729 | pInfo->rx_position); |
813 | pInfo->rx_position); | 730 | put_char(pInfo, NAK); |
814 | put_char(pInfo, NAK); | 731 | flush(pInfo); |
815 | flush(pInfo); | 732 | pInfo->state = R3964_IDLE; |
816 | pInfo->state=R3964_IDLE; | 733 | break; |
817 | break; | 734 | case R3964_WAIT_FOR_RX_REPEAT: |
818 | case R3964_WAIT_FOR_RX_REPEAT: | 735 | TRACE_PE("WAIT_FOR_RX_REPEAT - timeout"); |
819 | TRACE_PE("WAIT_FOR_RX_REPEAT - timeout"); | 736 | pInfo->state = R3964_IDLE; |
820 | pInfo->state=R3964_IDLE; | 737 | break; |
821 | break; | 738 | case R3964_WAIT_FOR_BCC: |
822 | case R3964_WAIT_FOR_BCC: | 739 | TRACE_PE("WAIT_FOR_BCC - timeout"); |
823 | TRACE_PE("WAIT_FOR_BCC - timeout"); | 740 | put_char(pInfo, NAK); |
824 | put_char(pInfo, NAK); | 741 | flush(pInfo); |
825 | flush(pInfo); | 742 | pInfo->state = R3964_IDLE; |
826 | pInfo->state=R3964_IDLE; | 743 | break; |
827 | break; | 744 | } |
828 | } | ||
829 | } | 745 | } |
830 | 746 | ||
831 | static struct r3964_client_info *findClient( | 747 | static struct r3964_client_info *findClient(struct r3964_info *pInfo, |
832 | struct r3964_info *pInfo, struct pid *pid) | 748 | struct pid *pid) |
833 | { | 749 | { |
834 | struct r3964_client_info *pClient; | 750 | struct r3964_client_info *pClient; |
835 | 751 | ||
836 | for(pClient=pInfo->firstClient; pClient; pClient=pClient->next) | 752 | for (pClient = pInfo->firstClient; pClient; pClient = pClient->next) { |
837 | { | 753 | if (pClient->pid == pid) { |
838 | if(pClient->pid == pid) | 754 | return pClient; |
839 | { | 755 | } |
840 | return pClient; | 756 | } |
841 | } | 757 | return NULL; |
842 | } | ||
843 | return NULL; | ||
844 | } | 758 | } |
845 | 759 | ||
846 | static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg) | 760 | static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg) |
847 | { | 761 | { |
848 | struct r3964_client_info *pClient; | 762 | struct r3964_client_info *pClient; |
849 | struct r3964_client_info **ppClient; | 763 | struct r3964_client_info **ppClient; |
850 | struct r3964_message *pMsg; | 764 | struct r3964_message *pMsg; |
851 | 765 | ||
852 | if((arg & R3964_SIG_ALL)==0) | 766 | if ((arg & R3964_SIG_ALL) == 0) { |
853 | { | 767 | /* Remove client from client list */ |
854 | /* Remove client from client list */ | 768 | for (ppClient = &pInfo->firstClient; *ppClient; |
855 | for(ppClient=&pInfo->firstClient; *ppClient; ppClient=&(*ppClient)->next) | 769 | ppClient = &(*ppClient)->next) { |
856 | { | 770 | pClient = *ppClient; |
857 | pClient = *ppClient; | 771 | |
858 | 772 | if (pClient->pid == pid) { | |
859 | if(pClient->pid == pid) | 773 | TRACE_PS("removing client %d from client list", |
860 | { | 774 | pid_nr(pid)); |
861 | TRACE_PS("removing client %d from client list", pid_nr(pid)); | 775 | *ppClient = pClient->next; |
862 | *ppClient = pClient->next; | 776 | while (pClient->msg_count) { |
863 | while(pClient->msg_count) | 777 | pMsg = remove_msg(pInfo, pClient); |
864 | { | 778 | if (pMsg) { |
865 | pMsg=remove_msg(pInfo, pClient); | 779 | kfree(pMsg); |
866 | if(pMsg) | 780 | TRACE_M("enable_signals - msg " |
867 | { | 781 | "kfree %p", pMsg); |
868 | kfree(pMsg); | 782 | } |
869 | TRACE_M("enable_signals - msg kfree %p",pMsg); | 783 | } |
870 | } | 784 | put_pid(pClient->pid); |
871 | } | 785 | kfree(pClient); |
872 | put_pid(pClient->pid); | 786 | TRACE_M("enable_signals - kfree %p", pClient); |
873 | kfree(pClient); | 787 | return 0; |
874 | TRACE_M("enable_signals - kfree %p",pClient); | 788 | } |
875 | return 0; | 789 | } |
876 | } | 790 | return -EINVAL; |
877 | } | 791 | } else { |
878 | return -EINVAL; | 792 | pClient = findClient(pInfo, pid); |
879 | } | 793 | if (pClient) { |
880 | else | 794 | /* update signal options */ |
881 | { | 795 | pClient->sig_flags = arg; |
882 | pClient=findClient(pInfo, pid); | 796 | } else { |
883 | if(pClient) | 797 | /* add client to client list */ |
884 | { | 798 | pClient = kmalloc(sizeof(struct r3964_client_info), |
885 | /* update signal options */ | 799 | GFP_KERNEL); |
886 | pClient->sig_flags=arg; | 800 | TRACE_M("enable_signals - kmalloc %p", pClient); |
887 | } | 801 | if (pClient == NULL) |
888 | else | 802 | return -ENOMEM; |
889 | { | 803 | |
890 | /* add client to client list */ | 804 | TRACE_PS("add client %d to client list", pid_nr(pid)); |
891 | pClient=kmalloc(sizeof(struct r3964_client_info), GFP_KERNEL); | 805 | spin_lock_init(&pClient->lock); |
892 | TRACE_M("enable_signals - kmalloc %p",pClient); | 806 | pClient->sig_flags = arg; |
893 | if(pClient==NULL) | 807 | pClient->pid = get_pid(pid); |
894 | return -ENOMEM; | 808 | pClient->next = pInfo->firstClient; |
895 | 809 | pClient->first_msg = NULL; | |
896 | TRACE_PS("add client %d to client list", pid_nr(pid)); | 810 | pClient->last_msg = NULL; |
897 | spin_lock_init(&pClient->lock); | 811 | pClient->next_block_to_read = NULL; |
898 | pClient->sig_flags=arg; | 812 | pClient->msg_count = 0; |
899 | pClient->pid = get_pid(pid); | 813 | pInfo->firstClient = pClient; |
900 | pClient->next=pInfo->firstClient; | 814 | } |
901 | pClient->first_msg = NULL; | 815 | } |
902 | pClient->last_msg = NULL; | 816 | |
903 | pClient->next_block_to_read = NULL; | 817 | return 0; |
904 | pClient->msg_count = 0; | ||
905 | pInfo->firstClient=pClient; | ||
906 | } | ||
907 | } | ||
908 | |||
909 | return 0; | ||
910 | } | 818 | } |
911 | 819 | ||
912 | static int read_telegram(struct r3964_info *pInfo, struct pid *pid, unsigned char __user *buf) | 820 | static int read_telegram(struct r3964_info *pInfo, struct pid *pid, |
821 | unsigned char __user * buf) | ||
913 | { | 822 | { |
914 | struct r3964_client_info *pClient; | 823 | struct r3964_client_info *pClient; |
915 | struct r3964_block_header *block; | 824 | struct r3964_block_header *block; |
916 | 825 | ||
917 | if(!buf) | 826 | if (!buf) { |
918 | { | 827 | return -EINVAL; |
919 | return -EINVAL; | 828 | } |
920 | } | 829 | |
921 | 830 | pClient = findClient(pInfo, pid); | |
922 | pClient=findClient(pInfo,pid); | 831 | if (pClient == NULL) { |
923 | if(pClient==NULL) | 832 | return -EINVAL; |
924 | { | 833 | } |
925 | return -EINVAL; | 834 | |
926 | } | 835 | block = pClient->next_block_to_read; |
927 | 836 | if (!block) { | |
928 | block=pClient->next_block_to_read; | 837 | return 0; |
929 | if(!block) | 838 | } else { |
930 | { | 839 | if (copy_to_user(buf, block->data, block->length)) |
931 | return 0; | 840 | return -EFAULT; |
932 | } | 841 | |
933 | else | 842 | remove_client_block(pInfo, pClient); |
934 | { | 843 | return block->length; |
935 | if (copy_to_user (buf, block->data, block->length)) | 844 | } |
936 | return -EFAULT; | 845 | |
937 | 846 | return -EINVAL; | |
938 | remove_client_block(pInfo, pClient); | ||
939 | return block->length; | ||
940 | } | ||
941 | |||
942 | return -EINVAL; | ||
943 | } | 847 | } |
944 | 848 | ||
945 | static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg, | 849 | static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg, |
946 | int error_code, struct r3964_block_header *pBlock) | 850 | int error_code, struct r3964_block_header *pBlock) |
947 | { | 851 | { |
948 | struct r3964_message *pMsg; | 852 | struct r3964_message *pMsg; |
949 | unsigned long flags; | 853 | unsigned long flags; |
950 | 854 | ||
951 | if(pClient->msg_count<R3964_MAX_MSG_COUNT-1) | 855 | if (pClient->msg_count < R3964_MAX_MSG_COUNT - 1) { |
952 | { | ||
953 | queue_the_message: | 856 | queue_the_message: |
954 | 857 | ||
955 | pMsg = kmalloc(sizeof(struct r3964_message), | 858 | pMsg = kmalloc(sizeof(struct r3964_message), |
956 | error_code?GFP_ATOMIC:GFP_KERNEL); | 859 | error_code ? GFP_ATOMIC : GFP_KERNEL); |
957 | TRACE_M("add_msg - kmalloc %p",pMsg); | 860 | TRACE_M("add_msg - kmalloc %p", pMsg); |
958 | if(pMsg==NULL) { | 861 | if (pMsg == NULL) { |
959 | return; | 862 | return; |
960 | } | 863 | } |
961 | 864 | ||
962 | spin_lock_irqsave(&pClient->lock, flags); | 865 | spin_lock_irqsave(&pClient->lock, flags); |
963 | 866 | ||
964 | pMsg->msg_id = msg_id; | 867 | pMsg->msg_id = msg_id; |
965 | pMsg->arg = arg; | 868 | pMsg->arg = arg; |
966 | pMsg->error_code = error_code; | 869 | pMsg->error_code = error_code; |
967 | pMsg->block = pBlock; | 870 | pMsg->block = pBlock; |
968 | pMsg->next = NULL; | 871 | pMsg->next = NULL; |
969 | 872 | ||
970 | if(pClient->last_msg==NULL) | 873 | if (pClient->last_msg == NULL) { |
971 | { | 874 | pClient->first_msg = pClient->last_msg = pMsg; |
972 | pClient->first_msg=pClient->last_msg=pMsg; | 875 | } else { |
973 | } | 876 | pClient->last_msg->next = pMsg; |
974 | else | 877 | pClient->last_msg = pMsg; |
975 | { | 878 | } |
976 | pClient->last_msg->next = pMsg; | 879 | |
977 | pClient->last_msg=pMsg; | 880 | pClient->msg_count++; |
978 | } | 881 | |
979 | 882 | if (pBlock != NULL) { | |
980 | pClient->msg_count++; | 883 | pBlock->locks++; |
981 | 884 | } | |
982 | if(pBlock!=NULL) | 885 | spin_unlock_irqrestore(&pClient->lock, flags); |
983 | { | 886 | } else { |
984 | pBlock->locks++; | 887 | if ((pClient->last_msg->msg_id == R3964_MSG_ACK) |
985 | } | 888 | && (pClient->last_msg->error_code == R3964_OVERFLOW)) { |
986 | spin_unlock_irqrestore(&pClient->lock, flags); | 889 | pClient->last_msg->arg++; |
987 | } | 890 | TRACE_PE("add_msg - inc prev OVERFLOW-msg"); |
988 | else | 891 | } else { |
989 | { | 892 | msg_id = R3964_MSG_ACK; |
990 | if((pClient->last_msg->msg_id == R3964_MSG_ACK) | 893 | arg = 0; |
991 | && (pClient->last_msg->error_code==R3964_OVERFLOW)) | 894 | error_code = R3964_OVERFLOW; |
992 | { | 895 | pBlock = NULL; |
993 | pClient->last_msg->arg++; | 896 | TRACE_PE("add_msg - queue OVERFLOW-msg"); |
994 | TRACE_PE("add_msg - inc prev OVERFLOW-msg"); | 897 | goto queue_the_message; |
995 | } | 898 | } |
996 | else | 899 | } |
997 | { | 900 | /* Send SIGIO signal to client process: */ |
998 | msg_id = R3964_MSG_ACK; | 901 | if (pClient->sig_flags & R3964_USE_SIGIO) { |
999 | arg = 0; | 902 | kill_pid(pClient->pid, SIGIO, 1); |
1000 | error_code = R3964_OVERFLOW; | 903 | } |
1001 | pBlock = NULL; | ||
1002 | TRACE_PE("add_msg - queue OVERFLOW-msg"); | ||
1003 | goto queue_the_message; | ||
1004 | } | ||
1005 | } | ||
1006 | /* Send SIGIO signal to client process: */ | ||
1007 | if(pClient->sig_flags & R3964_USE_SIGIO) | ||
1008 | { | ||
1009 | kill_pid(pClient->pid, SIGIO, 1); | ||
1010 | } | ||
1011 | } | 904 | } |
1012 | 905 | ||
1013 | static struct r3964_message *remove_msg(struct r3964_info *pInfo, | 906 | static struct r3964_message *remove_msg(struct r3964_info *pInfo, |
1014 | struct r3964_client_info *pClient) | 907 | struct r3964_client_info *pClient) |
1015 | { | 908 | { |
1016 | struct r3964_message *pMsg=NULL; | 909 | struct r3964_message *pMsg = NULL; |
1017 | unsigned long flags; | 910 | unsigned long flags; |
1018 | 911 | ||
1019 | if(pClient->first_msg) | 912 | if (pClient->first_msg) { |
1020 | { | 913 | spin_lock_irqsave(&pClient->lock, flags); |
1021 | spin_lock_irqsave(&pClient->lock, flags); | 914 | |
1022 | 915 | pMsg = pClient->first_msg; | |
1023 | pMsg = pClient->first_msg; | 916 | pClient->first_msg = pMsg->next; |
1024 | pClient->first_msg = pMsg->next; | 917 | if (pClient->first_msg == NULL) { |
1025 | if(pClient->first_msg==NULL) | 918 | pClient->last_msg = NULL; |
1026 | { | 919 | } |
1027 | pClient->last_msg = NULL; | 920 | |
1028 | } | 921 | pClient->msg_count--; |
1029 | 922 | if (pMsg->block) { | |
1030 | pClient->msg_count--; | 923 | remove_client_block(pInfo, pClient); |
1031 | if(pMsg->block) | 924 | pClient->next_block_to_read = pMsg->block; |
1032 | { | 925 | } |
1033 | remove_client_block(pInfo, pClient); | 926 | spin_unlock_irqrestore(&pClient->lock, flags); |
1034 | pClient->next_block_to_read = pMsg->block; | 927 | } |
1035 | } | 928 | return pMsg; |
1036 | spin_unlock_irqrestore(&pClient->lock, flags); | ||
1037 | } | ||
1038 | return pMsg; | ||
1039 | } | 929 | } |
1040 | 930 | ||
1041 | static void remove_client_block(struct r3964_info *pInfo, | 931 | static void remove_client_block(struct r3964_info *pInfo, |
1042 | struct r3964_client_info *pClient) | 932 | struct r3964_client_info *pClient) |
1043 | { | 933 | { |
1044 | struct r3964_block_header *block; | 934 | struct r3964_block_header *block; |
1045 | 935 | ||
1046 | TRACE_PS("remove_client_block PID %d", pid_nr(pClient->pid)); | 936 | TRACE_PS("remove_client_block PID %d", pid_nr(pClient->pid)); |
1047 | |||
1048 | block=pClient->next_block_to_read; | ||
1049 | if(block) | ||
1050 | { | ||
1051 | block->locks--; | ||
1052 | if(block->locks==0) | ||
1053 | { | ||
1054 | remove_from_rx_queue(pInfo, block); | ||
1055 | } | ||
1056 | } | ||
1057 | pClient->next_block_to_read = NULL; | ||
1058 | } | ||
1059 | 937 | ||
938 | block = pClient->next_block_to_read; | ||
939 | if (block) { | ||
940 | block->locks--; | ||
941 | if (block->locks == 0) { | ||
942 | remove_from_rx_queue(pInfo, block); | ||
943 | } | ||
944 | } | ||
945 | pClient->next_block_to_read = NULL; | ||
946 | } | ||
1060 | 947 | ||
1061 | /************************************************************* | 948 | /************************************************************* |
1062 | * Line discipline routines | 949 | * Line discipline routines |
@@ -1064,342 +951,318 @@ static void remove_client_block(struct r3964_info *pInfo, | |||
1064 | 951 | ||
1065 | static int r3964_open(struct tty_struct *tty) | 952 | static int r3964_open(struct tty_struct *tty) |
1066 | { | 953 | { |
1067 | struct r3964_info *pInfo; | 954 | struct r3964_info *pInfo; |
1068 | 955 | ||
1069 | TRACE_L("open"); | 956 | TRACE_L("open"); |
1070 | TRACE_L("tty=%p, PID=%d, disc_data=%p", | 957 | TRACE_L("tty=%p, PID=%d, disc_data=%p", |
1071 | tty, current->pid, tty->disc_data); | 958 | tty, current->pid, tty->disc_data); |
1072 | 959 | ||
1073 | pInfo=kmalloc(sizeof(struct r3964_info), GFP_KERNEL); | 960 | pInfo = kmalloc(sizeof(struct r3964_info), GFP_KERNEL); |
1074 | TRACE_M("r3964_open - info kmalloc %p",pInfo); | 961 | TRACE_M("r3964_open - info kmalloc %p", pInfo); |
1075 | 962 | ||
1076 | if(!pInfo) | 963 | if (!pInfo) { |
1077 | { | 964 | printk(KERN_ERR "r3964: failed to alloc info structure\n"); |
1078 | printk(KERN_ERR "r3964: failed to alloc info structure\n"); | 965 | return -ENOMEM; |
1079 | return -ENOMEM; | 966 | } |
1080 | } | 967 | |
1081 | 968 | pInfo->rx_buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL); | |
1082 | pInfo->rx_buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL); | 969 | TRACE_M("r3964_open - rx_buf kmalloc %p", pInfo->rx_buf); |
1083 | TRACE_M("r3964_open - rx_buf kmalloc %p",pInfo->rx_buf); | 970 | |
1084 | 971 | if (!pInfo->rx_buf) { | |
1085 | if(!pInfo->rx_buf) | 972 | printk(KERN_ERR "r3964: failed to alloc receive buffer\n"); |
1086 | { | 973 | kfree(pInfo); |
1087 | printk(KERN_ERR "r3964: failed to alloc receive buffer\n"); | 974 | TRACE_M("r3964_open - info kfree %p", pInfo); |
1088 | kfree(pInfo); | 975 | return -ENOMEM; |
1089 | TRACE_M("r3964_open - info kfree %p",pInfo); | 976 | } |
1090 | return -ENOMEM; | 977 | |
1091 | } | 978 | pInfo->tx_buf = kmalloc(TX_BUF_SIZE, GFP_KERNEL); |
1092 | 979 | TRACE_M("r3964_open - tx_buf kmalloc %p", pInfo->tx_buf); | |
1093 | pInfo->tx_buf = kmalloc(TX_BUF_SIZE, GFP_KERNEL); | 980 | |
1094 | TRACE_M("r3964_open - tx_buf kmalloc %p",pInfo->tx_buf); | 981 | if (!pInfo->tx_buf) { |
1095 | 982 | printk(KERN_ERR "r3964: failed to alloc transmit buffer\n"); | |
1096 | if(!pInfo->tx_buf) | 983 | kfree(pInfo->rx_buf); |
1097 | { | 984 | TRACE_M("r3964_open - rx_buf kfree %p", pInfo->rx_buf); |
1098 | printk(KERN_ERR "r3964: failed to alloc transmit buffer\n"); | 985 | kfree(pInfo); |
1099 | kfree(pInfo->rx_buf); | 986 | TRACE_M("r3964_open - info kfree %p", pInfo); |
1100 | TRACE_M("r3964_open - rx_buf kfree %p",pInfo->rx_buf); | 987 | return -ENOMEM; |
1101 | kfree(pInfo); | 988 | } |
1102 | TRACE_M("r3964_open - info kfree %p",pInfo); | 989 | |
1103 | return -ENOMEM; | 990 | spin_lock_init(&pInfo->lock); |
1104 | } | 991 | pInfo->tty = tty; |
1105 | 992 | init_waitqueue_head(&pInfo->read_wait); | |
1106 | spin_lock_init(&pInfo->lock); | 993 | pInfo->priority = R3964_MASTER; |
1107 | pInfo->tty = tty; | 994 | pInfo->rx_first = pInfo->rx_last = NULL; |
1108 | init_waitqueue_head (&pInfo->read_wait); | 995 | pInfo->tx_first = pInfo->tx_last = NULL; |
1109 | pInfo->priority = R3964_MASTER; | 996 | pInfo->rx_position = 0; |
1110 | pInfo->rx_first = pInfo->rx_last = NULL; | 997 | pInfo->tx_position = 0; |
1111 | pInfo->tx_first = pInfo->tx_last = NULL; | 998 | pInfo->last_rx = 0; |
1112 | pInfo->rx_position = 0; | 999 | pInfo->blocks_in_rx_queue = 0; |
1113 | pInfo->tx_position = 0; | 1000 | pInfo->firstClient = NULL; |
1114 | pInfo->last_rx = 0; | 1001 | pInfo->state = R3964_IDLE; |
1115 | pInfo->blocks_in_rx_queue = 0; | 1002 | pInfo->flags = R3964_DEBUG; |
1116 | pInfo->firstClient=NULL; | 1003 | pInfo->nRetry = 0; |
1117 | pInfo->state=R3964_IDLE; | 1004 | |
1118 | pInfo->flags = R3964_DEBUG; | 1005 | tty->disc_data = pInfo; |
1119 | pInfo->nRetry = 0; | 1006 | tty->receive_room = 65536; |
1120 | 1007 | ||
1121 | tty->disc_data = pInfo; | 1008 | setup_timer(&pInfo->tmr, on_timeout, (unsigned long)pInfo); |
1122 | tty->receive_room = 65536; | 1009 | |
1123 | 1010 | return 0; | |
1124 | init_timer(&pInfo->tmr); | ||
1125 | pInfo->tmr.data = (unsigned long)pInfo; | ||
1126 | pInfo->tmr.function = on_timeout; | ||
1127 | |||
1128 | return 0; | ||
1129 | } | 1011 | } |
1130 | 1012 | ||
1131 | static void r3964_close(struct tty_struct *tty) | 1013 | static void r3964_close(struct tty_struct *tty) |
1132 | { | 1014 | { |
1133 | struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; | 1015 | struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; |
1134 | struct r3964_client_info *pClient, *pNext; | 1016 | struct r3964_client_info *pClient, *pNext; |
1135 | struct r3964_message *pMsg; | 1017 | struct r3964_message *pMsg; |
1136 | struct r3964_block_header *pHeader, *pNextHeader; | 1018 | struct r3964_block_header *pHeader, *pNextHeader; |
1137 | unsigned long flags; | 1019 | unsigned long flags; |
1138 | 1020 | ||
1139 | TRACE_L("close"); | 1021 | TRACE_L("close"); |
1140 | 1022 | ||
1141 | /* | 1023 | /* |
1142 | * Make sure that our task queue isn't activated. If it | 1024 | * Make sure that our task queue isn't activated. If it |
1143 | * is, take it out of the linked list. | 1025 | * is, take it out of the linked list. |
1144 | */ | 1026 | */ |
1145 | del_timer_sync(&pInfo->tmr); | 1027 | del_timer_sync(&pInfo->tmr); |
1146 | 1028 | ||
1147 | /* Remove client-structs and message queues: */ | 1029 | /* Remove client-structs and message queues: */ |
1148 | pClient=pInfo->firstClient; | 1030 | pClient = pInfo->firstClient; |
1149 | while(pClient) | 1031 | while (pClient) { |
1150 | { | 1032 | pNext = pClient->next; |
1151 | pNext=pClient->next; | 1033 | while (pClient->msg_count) { |
1152 | while(pClient->msg_count) | 1034 | pMsg = remove_msg(pInfo, pClient); |
1153 | { | 1035 | if (pMsg) { |
1154 | pMsg=remove_msg(pInfo, pClient); | 1036 | kfree(pMsg); |
1155 | if(pMsg) | 1037 | TRACE_M("r3964_close - msg kfree %p", pMsg); |
1156 | { | 1038 | } |
1157 | kfree(pMsg); | 1039 | } |
1158 | TRACE_M("r3964_close - msg kfree %p",pMsg); | 1040 | put_pid(pClient->pid); |
1159 | } | 1041 | kfree(pClient); |
1160 | } | 1042 | TRACE_M("r3964_close - client kfree %p", pClient); |
1161 | put_pid(pClient->pid); | 1043 | pClient = pNext; |
1162 | kfree(pClient); | 1044 | } |
1163 | TRACE_M("r3964_close - client kfree %p",pClient); | 1045 | /* Remove jobs from tx_queue: */ |
1164 | pClient=pNext; | 1046 | spin_lock_irqsave(&pInfo->lock, flags); |
1165 | } | 1047 | pHeader = pInfo->tx_first; |
1166 | /* Remove jobs from tx_queue: */ | 1048 | pInfo->tx_first = pInfo->tx_last = NULL; |
1167 | spin_lock_irqsave(&pInfo->lock, flags); | ||
1168 | pHeader=pInfo->tx_first; | ||
1169 | pInfo->tx_first=pInfo->tx_last=NULL; | ||
1170 | spin_unlock_irqrestore(&pInfo->lock, flags); | 1049 | spin_unlock_irqrestore(&pInfo->lock, flags); |
1171 | 1050 | ||
1172 | while(pHeader) | 1051 | while (pHeader) { |
1173 | { | 1052 | pNextHeader = pHeader->next; |
1174 | pNextHeader=pHeader->next; | 1053 | kfree(pHeader); |
1175 | kfree(pHeader); | 1054 | pHeader = pNextHeader; |
1176 | pHeader=pNextHeader; | ||
1177 | } | 1055 | } |
1178 | 1056 | ||
1179 | /* Free buffers: */ | 1057 | /* Free buffers: */ |
1180 | wake_up_interruptible(&pInfo->read_wait); | 1058 | wake_up_interruptible(&pInfo->read_wait); |
1181 | kfree(pInfo->rx_buf); | 1059 | kfree(pInfo->rx_buf); |
1182 | TRACE_M("r3964_close - rx_buf kfree %p",pInfo->rx_buf); | 1060 | TRACE_M("r3964_close - rx_buf kfree %p", pInfo->rx_buf); |
1183 | kfree(pInfo->tx_buf); | 1061 | kfree(pInfo->tx_buf); |
1184 | TRACE_M("r3964_close - tx_buf kfree %p",pInfo->tx_buf); | 1062 | TRACE_M("r3964_close - tx_buf kfree %p", pInfo->tx_buf); |
1185 | kfree(pInfo); | 1063 | kfree(pInfo); |
1186 | TRACE_M("r3964_close - info kfree %p",pInfo); | 1064 | TRACE_M("r3964_close - info kfree %p", pInfo); |
1187 | } | 1065 | } |
1188 | 1066 | ||
1189 | static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | 1067 | static ssize_t r3964_read(struct tty_struct *tty, struct file *file, |
1190 | unsigned char __user *buf, size_t nr) | 1068 | unsigned char __user * buf, size_t nr) |
1191 | { | 1069 | { |
1192 | struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; | 1070 | struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; |
1193 | struct r3964_client_info *pClient; | 1071 | struct r3964_client_info *pClient; |
1194 | struct r3964_message *pMsg; | 1072 | struct r3964_message *pMsg; |
1195 | struct r3964_client_message theMsg; | 1073 | struct r3964_client_message theMsg; |
1196 | DECLARE_WAITQUEUE (wait, current); | 1074 | DECLARE_WAITQUEUE(wait, current); |
1197 | 1075 | ||
1198 | int count; | 1076 | int count; |
1199 | 1077 | ||
1200 | TRACE_L("read()"); | 1078 | TRACE_L("read()"); |
1201 | 1079 | ||
1202 | pClient=findClient(pInfo, task_pid(current)); | 1080 | pClient = findClient(pInfo, task_pid(current)); |
1203 | if(pClient) | 1081 | if (pClient) { |
1204 | { | 1082 | pMsg = remove_msg(pInfo, pClient); |
1205 | pMsg = remove_msg(pInfo, pClient); | 1083 | if (pMsg == NULL) { |
1206 | if(pMsg==NULL) | 1084 | /* no messages available. */ |
1207 | { | 1085 | if (file->f_flags & O_NONBLOCK) { |
1208 | /* no messages available. */ | 1086 | return -EAGAIN; |
1209 | if (file->f_flags & O_NONBLOCK) | 1087 | } |
1210 | { | 1088 | /* block until there is a message: */ |
1211 | return -EAGAIN; | 1089 | add_wait_queue(&pInfo->read_wait, &wait); |
1212 | } | ||
1213 | /* block until there is a message: */ | ||
1214 | add_wait_queue(&pInfo->read_wait, &wait); | ||
1215 | repeat: | 1090 | repeat: |
1216 | current->state = TASK_INTERRUPTIBLE; | 1091 | current->state = TASK_INTERRUPTIBLE; |
1217 | pMsg = remove_msg(pInfo, pClient); | 1092 | pMsg = remove_msg(pInfo, pClient); |
1218 | if (!pMsg && !signal_pending(current)) | 1093 | if (!pMsg && !signal_pending(current)) { |
1219 | { | 1094 | schedule(); |
1220 | schedule(); | 1095 | goto repeat; |
1221 | goto repeat; | 1096 | } |
1222 | } | 1097 | current->state = TASK_RUNNING; |
1223 | current->state = TASK_RUNNING; | 1098 | remove_wait_queue(&pInfo->read_wait, &wait); |
1224 | remove_wait_queue(&pInfo->read_wait, &wait); | 1099 | } |
1225 | } | 1100 | |
1226 | 1101 | /* If we still haven't got a message, we must have been signalled */ | |
1227 | /* If we still haven't got a message, we must have been signalled */ | 1102 | |
1228 | 1103 | if (!pMsg) | |
1229 | if (!pMsg) return -EINTR; | 1104 | return -EINTR; |
1230 | 1105 | ||
1231 | /* deliver msg to client process: */ | 1106 | /* deliver msg to client process: */ |
1232 | theMsg.msg_id = pMsg->msg_id; | 1107 | theMsg.msg_id = pMsg->msg_id; |
1233 | theMsg.arg = pMsg->arg; | 1108 | theMsg.arg = pMsg->arg; |
1234 | theMsg.error_code = pMsg->error_code; | 1109 | theMsg.error_code = pMsg->error_code; |
1235 | count = sizeof(struct r3964_client_message); | 1110 | count = sizeof(struct r3964_client_message); |
1236 | 1111 | ||
1237 | kfree(pMsg); | 1112 | kfree(pMsg); |
1238 | TRACE_M("r3964_read - msg kfree %p",pMsg); | 1113 | TRACE_M("r3964_read - msg kfree %p", pMsg); |
1239 | 1114 | ||
1240 | if (copy_to_user(buf,&theMsg, count)) | 1115 | if (copy_to_user(buf, &theMsg, count)) |
1241 | return -EFAULT; | 1116 | return -EFAULT; |
1242 | 1117 | ||
1243 | TRACE_PS("read - return %d", count); | 1118 | TRACE_PS("read - return %d", count); |
1244 | return count; | 1119 | return count; |
1245 | } | 1120 | } |
1246 | return -EPERM; | 1121 | return -EPERM; |
1247 | } | 1122 | } |
1248 | 1123 | ||
1249 | static ssize_t r3964_write(struct tty_struct * tty, struct file * file, | 1124 | static ssize_t r3964_write(struct tty_struct *tty, struct file *file, |
1250 | const unsigned char *data, size_t count) | 1125 | const unsigned char *data, size_t count) |
1251 | { | 1126 | { |
1252 | struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; | 1127 | struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; |
1253 | struct r3964_block_header *pHeader; | 1128 | struct r3964_block_header *pHeader; |
1254 | struct r3964_client_info *pClient; | 1129 | struct r3964_client_info *pClient; |
1255 | unsigned char *new_data; | 1130 | unsigned char *new_data; |
1256 | 1131 | ||
1257 | TRACE_L("write request, %d characters", count); | 1132 | TRACE_L("write request, %d characters", count); |
1258 | /* | 1133 | /* |
1259 | * Verify the pointers | 1134 | * Verify the pointers |
1260 | */ | 1135 | */ |
1261 | 1136 | ||
1262 | if(!pInfo) | 1137 | if (!pInfo) |
1263 | return -EIO; | 1138 | return -EIO; |
1264 | 1139 | ||
1265 | /* | 1140 | /* |
1266 | * Ensure that the caller does not wish to send too much. | 1141 | * Ensure that the caller does not wish to send too much. |
1267 | */ | 1142 | */ |
1268 | if (count > R3964_MTU) | 1143 | if (count > R3964_MTU) { |
1269 | { | 1144 | if (pInfo->flags & R3964_DEBUG) { |
1270 | if (pInfo->flags & R3964_DEBUG) | 1145 | TRACE_L(KERN_WARNING "r3964_write: truncating user " |
1271 | { | 1146 | "packet from %u to mtu %d", count, R3964_MTU); |
1272 | TRACE_L (KERN_WARNING | 1147 | } |
1273 | "r3964_write: truncating user packet " | 1148 | count = R3964_MTU; |
1274 | "from %u to mtu %d", count, R3964_MTU); | 1149 | } |
1275 | } | ||
1276 | count = R3964_MTU; | ||
1277 | } | ||
1278 | /* | 1150 | /* |
1279 | * Allocate a buffer for the data and copy it from the buffer with header prepended | 1151 | * Allocate a buffer for the data and copy it from the buffer with header prepended |
1280 | */ | 1152 | */ |
1281 | new_data = kmalloc (count+sizeof(struct r3964_block_header), GFP_KERNEL); | 1153 | new_data = kmalloc(count + sizeof(struct r3964_block_header), |
1282 | TRACE_M("r3964_write - kmalloc %p",new_data); | 1154 | GFP_KERNEL); |
1283 | if (new_data == NULL) { | 1155 | TRACE_M("r3964_write - kmalloc %p", new_data); |
1284 | if (pInfo->flags & R3964_DEBUG) | 1156 | if (new_data == NULL) { |
1285 | { | 1157 | if (pInfo->flags & R3964_DEBUG) { |
1286 | printk (KERN_ERR | 1158 | printk(KERN_ERR "r3964_write: no memory\n"); |
1287 | "r3964_write: no memory\n"); | 1159 | } |
1288 | } | 1160 | return -ENOSPC; |
1289 | return -ENOSPC; | 1161 | } |
1290 | } | 1162 | |
1291 | 1163 | pHeader = (struct r3964_block_header *)new_data; | |
1292 | pHeader = (struct r3964_block_header *)new_data; | 1164 | pHeader->data = new_data + sizeof(struct r3964_block_header); |
1293 | pHeader->data = new_data + sizeof(struct r3964_block_header); | 1165 | pHeader->length = count; |
1294 | pHeader->length = count; | 1166 | pHeader->locks = 0; |
1295 | pHeader->locks = 0; | 1167 | pHeader->owner = NULL; |
1296 | pHeader->owner = NULL; | 1168 | |
1297 | 1169 | pClient = findClient(pInfo, task_pid(current)); | |
1298 | pClient=findClient(pInfo, task_pid(current)); | 1170 | if (pClient) { |
1299 | if(pClient) | 1171 | pHeader->owner = pClient; |
1300 | { | 1172 | } |
1301 | pHeader->owner = pClient; | 1173 | |
1302 | } | 1174 | memcpy(pHeader->data, data, count); /* We already verified this */ |
1303 | 1175 | ||
1304 | memcpy(pHeader->data, data, count); /* We already verified this */ | 1176 | if (pInfo->flags & R3964_DEBUG) { |
1305 | 1177 | dump_block(pHeader->data, count); | |
1306 | if(pInfo->flags & R3964_DEBUG) | 1178 | } |
1307 | { | ||
1308 | dump_block(pHeader->data, count); | ||
1309 | } | ||
1310 | 1179 | ||
1311 | /* | 1180 | /* |
1312 | * Add buffer to transmit-queue: | 1181 | * Add buffer to transmit-queue: |
1313 | */ | 1182 | */ |
1314 | add_tx_queue(pInfo, pHeader); | 1183 | add_tx_queue(pInfo, pHeader); |
1315 | trigger_transmit(pInfo); | 1184 | trigger_transmit(pInfo); |
1316 | 1185 | ||
1317 | return 0; | 1186 | return 0; |
1318 | } | 1187 | } |
1319 | 1188 | ||
1320 | static int r3964_ioctl(struct tty_struct * tty, struct file * file, | 1189 | static int r3964_ioctl(struct tty_struct *tty, struct file *file, |
1321 | unsigned int cmd, unsigned long arg) | 1190 | unsigned int cmd, unsigned long arg) |
1322 | { | 1191 | { |
1323 | struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; | 1192 | struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; |
1324 | if(pInfo==NULL) | 1193 | if (pInfo == NULL) |
1325 | return -EINVAL; | 1194 | return -EINVAL; |
1326 | switch(cmd) | 1195 | switch (cmd) { |
1327 | { | 1196 | case R3964_ENABLE_SIGNALS: |
1328 | case R3964_ENABLE_SIGNALS: | 1197 | return enable_signals(pInfo, task_pid(current), arg); |
1329 | return enable_signals(pInfo, task_pid(current), arg); | 1198 | case R3964_SETPRIORITY: |
1330 | case R3964_SETPRIORITY: | 1199 | if (arg < R3964_MASTER || arg > R3964_SLAVE) |
1331 | if(arg<R3964_MASTER || arg>R3964_SLAVE) | 1200 | return -EINVAL; |
1332 | return -EINVAL; | 1201 | pInfo->priority = arg & 0xff; |
1333 | pInfo->priority = arg & 0xff; | 1202 | return 0; |
1334 | return 0; | 1203 | case R3964_USE_BCC: |
1335 | case R3964_USE_BCC: | 1204 | if (arg) |
1336 | if(arg) | 1205 | pInfo->flags |= R3964_BCC; |
1337 | pInfo->flags |= R3964_BCC; | 1206 | else |
1338 | else | 1207 | pInfo->flags &= ~R3964_BCC; |
1339 | pInfo->flags &= ~R3964_BCC; | 1208 | return 0; |
1340 | return 0; | 1209 | case R3964_READ_TELEGRAM: |
1341 | case R3964_READ_TELEGRAM: | 1210 | return read_telegram(pInfo, task_pid(current), |
1342 | return read_telegram(pInfo, task_pid(current), (unsigned char __user *)arg); | 1211 | (unsigned char __user *)arg); |
1343 | default: | 1212 | default: |
1344 | return -ENOIOCTLCMD; | 1213 | return -ENOIOCTLCMD; |
1345 | } | 1214 | } |
1346 | } | 1215 | } |
1347 | 1216 | ||
1348 | static void r3964_set_termios(struct tty_struct *tty, struct ktermios * old) | 1217 | static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old) |
1349 | { | 1218 | { |
1350 | TRACE_L("set_termios"); | 1219 | TRACE_L("set_termios"); |
1351 | } | 1220 | } |
1352 | 1221 | ||
1353 | /* Called without the kernel lock held - fine */ | 1222 | /* Called without the kernel lock held - fine */ |
1354 | static unsigned int r3964_poll(struct tty_struct * tty, struct file * file, | 1223 | static unsigned int r3964_poll(struct tty_struct *tty, struct file *file, |
1355 | struct poll_table_struct *wait) | 1224 | struct poll_table_struct *wait) |
1356 | { | 1225 | { |
1357 | struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; | 1226 | struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; |
1358 | struct r3964_client_info *pClient; | 1227 | struct r3964_client_info *pClient; |
1359 | struct r3964_message *pMsg=NULL; | 1228 | struct r3964_message *pMsg = NULL; |
1360 | unsigned long flags; | 1229 | unsigned long flags; |
1361 | int result = POLLOUT; | 1230 | int result = POLLOUT; |
1362 | 1231 | ||
1363 | TRACE_L("POLL"); | 1232 | TRACE_L("POLL"); |
1364 | 1233 | ||
1365 | pClient=findClient(pInfo, task_pid(current)); | 1234 | pClient = findClient(pInfo, task_pid(current)); |
1366 | if(pClient) | 1235 | if (pClient) { |
1367 | { | 1236 | poll_wait(file, &pInfo->read_wait, wait); |
1368 | poll_wait(file, &pInfo->read_wait, wait); | 1237 | spin_lock_irqsave(&pInfo->lock, flags); |
1369 | spin_lock_irqsave(&pInfo->lock, flags); | 1238 | pMsg = pClient->first_msg; |
1370 | pMsg=pClient->first_msg; | 1239 | spin_unlock_irqrestore(&pInfo->lock, flags); |
1371 | spin_unlock_irqrestore(&pInfo->lock, flags); | 1240 | if (pMsg) |
1372 | if(pMsg) | 1241 | result |= POLLIN | POLLRDNORM; |
1373 | result |= POLLIN | POLLRDNORM; | 1242 | } else { |
1374 | } | 1243 | result = -EINVAL; |
1375 | else | 1244 | } |
1376 | { | 1245 | return result; |
1377 | result = -EINVAL; | ||
1378 | } | ||
1379 | return result; | ||
1380 | } | 1246 | } |
1381 | 1247 | ||
1382 | static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, | 1248 | static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, |
1383 | char *fp, int count) | 1249 | char *fp, int count) |
1384 | { | 1250 | { |
1385 | struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; | 1251 | struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; |
1386 | const unsigned char *p; | 1252 | const unsigned char *p; |
1387 | char *f, flags = 0; | 1253 | char *f, flags = 0; |
1388 | int i; | 1254 | int i; |
1389 | 1255 | ||
1390 | for (i=count, p = cp, f = fp; i; i--, p++) { | 1256 | for (i = count, p = cp, f = fp; i; i--, p++) { |
1391 | if (f) | 1257 | if (f) |
1392 | flags = *f++; | 1258 | flags = *f++; |
1393 | if(flags==TTY_NORMAL) | 1259 | if (flags == TTY_NORMAL) { |
1394 | { | 1260 | receive_char(pInfo, *p); |
1395 | receive_char(pInfo, *p); | 1261 | } else { |
1396 | } | 1262 | receive_error(pInfo, flags); |
1397 | else | 1263 | } |
1398 | { | 1264 | |
1399 | receive_error(pInfo, flags); | 1265 | } |
1400 | } | ||
1401 | |||
1402 | } | ||
1403 | } | 1266 | } |
1404 | 1267 | ||
1405 | MODULE_LICENSE("GPL"); | 1268 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 2bdb0144a22e..6ac3ca4c723c 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c | |||
@@ -579,8 +579,8 @@ static void eraser(unsigned char c, struct tty_struct *tty) | |||
579 | 579 | ||
580 | static inline void isig(int sig, struct tty_struct *tty, int flush) | 580 | static inline void isig(int sig, struct tty_struct *tty, int flush) |
581 | { | 581 | { |
582 | if (tty->pgrp > 0) | 582 | if (tty->pgrp) |
583 | kill_pg(tty->pgrp, sig, 1); | 583 | kill_pgrp(tty->pgrp, sig, 1); |
584 | if (flush || !L_NOFLSH(tty)) { | 584 | if (flush || !L_NOFLSH(tty)) { |
585 | n_tty_flush_buffer(tty); | 585 | n_tty_flush_buffer(tty); |
586 | if (tty->driver->flush_buffer) | 586 | if (tty->driver->flush_buffer) |
@@ -1184,13 +1184,13 @@ static int job_control(struct tty_struct *tty, struct file *file) | |||
1184 | /* don't stop on /dev/console */ | 1184 | /* don't stop on /dev/console */ |
1185 | if (file->f_op->write != redirected_tty_write && | 1185 | if (file->f_op->write != redirected_tty_write && |
1186 | current->signal->tty == tty) { | 1186 | current->signal->tty == tty) { |
1187 | if (tty->pgrp <= 0) | 1187 | if (!tty->pgrp) |
1188 | printk("read_chan: tty->pgrp <= 0!\n"); | 1188 | printk("read_chan: no tty->pgrp!\n"); |
1189 | else if (process_group(current) != tty->pgrp) { | 1189 | else if (task_pgrp(current) != tty->pgrp) { |
1190 | if (is_ignored(SIGTTIN) || | 1190 | if (is_ignored(SIGTTIN) || |
1191 | is_orphaned_pgrp(process_group(current))) | 1191 | is_current_pgrp_orphaned()) |
1192 | return -EIO; | 1192 | return -EIO; |
1193 | kill_pg(process_group(current), SIGTTIN, 1); | 1193 | kill_pgrp(task_pgrp(current), SIGTTIN, 1); |
1194 | return -ERESTARTSYS; | 1194 | return -ERESTARTSYS; |
1195 | } | 1195 | } |
1196 | } | 1196 | } |
diff --git a/drivers/char/nwbutton.c b/drivers/char/nwbutton.c index 2d264971d839..2604246501e4 100644 --- a/drivers/char/nwbutton.c +++ b/drivers/char/nwbutton.c | |||
@@ -23,8 +23,11 @@ | |||
23 | #define __NWBUTTON_C /* Tell the header file who we are */ | 23 | #define __NWBUTTON_C /* Tell the header file who we are */ |
24 | #include "nwbutton.h" | 24 | #include "nwbutton.h" |
25 | 25 | ||
26 | static void button_sequence_finished (unsigned long parameters); | ||
27 | |||
26 | static int button_press_count; /* The count of button presses */ | 28 | static int button_press_count; /* The count of button presses */ |
27 | static struct timer_list button_timer; /* Times for the end of a sequence */ | 29 | /* Times for the end of a sequence */ |
30 | static DEFINE_TIMER(button_timer, button_sequence_finished, 0, 0); | ||
28 | static DECLARE_WAIT_QUEUE_HEAD(button_wait_queue); /* Used for blocking read */ | 31 | static DECLARE_WAIT_QUEUE_HEAD(button_wait_queue); /* Used for blocking read */ |
29 | static char button_output_buffer[32]; /* Stores data to write out of device */ | 32 | static char button_output_buffer[32]; /* Stores data to write out of device */ |
30 | static int bcount; /* The number of bytes in the buffer */ | 33 | static int bcount; /* The number of bytes in the buffer */ |
@@ -146,14 +149,8 @@ static void button_sequence_finished (unsigned long parameters) | |||
146 | 149 | ||
147 | static irqreturn_t button_handler (int irq, void *dev_id) | 150 | static irqreturn_t button_handler (int irq, void *dev_id) |
148 | { | 151 | { |
149 | if (button_press_count) { | ||
150 | del_timer (&button_timer); | ||
151 | } | ||
152 | button_press_count++; | 152 | button_press_count++; |
153 | init_timer (&button_timer); | 153 | mod_timer(&button_timer, jiffies + bdelay); |
154 | button_timer.function = button_sequence_finished; | ||
155 | button_timer.expires = (jiffies + bdelay); | ||
156 | add_timer (&button_timer); | ||
157 | 154 | ||
158 | return IRQ_HANDLED; | 155 | return IRQ_HANDLED; |
159 | } | 156 | } |
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 211c93fda6fc..e91b43a014b0 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c | |||
@@ -946,8 +946,7 @@ release_io: | |||
946 | 946 | ||
947 | return_with_timer: | 947 | return_with_timer: |
948 | DEBUGP(7, dev, "<- monitor_card (returns with timer)\n"); | 948 | DEBUGP(7, dev, "<- monitor_card (returns with timer)\n"); |
949 | dev->timer.expires = jiffies + dev->mdelay; | 949 | mod_timer(&dev->timer, jiffies + dev->mdelay); |
950 | add_timer(&dev->timer); | ||
951 | clear_bit(LOCK_MONITOR, &dev->flags); | 950 | clear_bit(LOCK_MONITOR, &dev->flags); |
952 | } | 951 | } |
953 | 952 | ||
@@ -1406,12 +1405,9 @@ static void start_monitor(struct cm4000_dev *dev) | |||
1406 | DEBUGP(3, dev, "-> start_monitor\n"); | 1405 | DEBUGP(3, dev, "-> start_monitor\n"); |
1407 | if (!dev->monitor_running) { | 1406 | if (!dev->monitor_running) { |
1408 | DEBUGP(5, dev, "create, init and add timer\n"); | 1407 | DEBUGP(5, dev, "create, init and add timer\n"); |
1409 | init_timer(&dev->timer); | 1408 | setup_timer(&dev->timer, monitor_card, (unsigned long)dev); |
1410 | dev->monitor_running = 1; | 1409 | dev->monitor_running = 1; |
1411 | dev->timer.expires = jiffies; | 1410 | mod_timer(&dev->timer, jiffies); |
1412 | dev->timer.data = (unsigned long) dev; | ||
1413 | dev->timer.function = monitor_card; | ||
1414 | add_timer(&dev->timer); | ||
1415 | } else | 1411 | } else |
1416 | DEBUGP(5, dev, "monitor already running\n"); | 1412 | DEBUGP(5, dev, "monitor already running\n"); |
1417 | DEBUGP(3, dev, "<- start_monitor\n"); | 1413 | DEBUGP(3, dev, "<- start_monitor\n"); |
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 9b1ff7e8f896..0e82968c2f38 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c | |||
@@ -632,8 +632,7 @@ static int reader_probe(struct pcmcia_device *link) | |||
632 | init_waitqueue_head(&dev->poll_wait); | 632 | init_waitqueue_head(&dev->poll_wait); |
633 | init_waitqueue_head(&dev->read_wait); | 633 | init_waitqueue_head(&dev->read_wait); |
634 | init_waitqueue_head(&dev->write_wait); | 634 | init_waitqueue_head(&dev->write_wait); |
635 | init_timer(&dev->poll_timer); | 635 | setup_timer(&dev->poll_timer, cm4040_do_poll, 0); |
636 | dev->poll_timer.function = &cm4040_do_poll; | ||
637 | 636 | ||
638 | ret = reader_config(link, i); | 637 | ret = reader_config(link, i); |
639 | if (ret) | 638 | if (ret) |
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index f108c136800a..8d025e9b5bce 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -887,10 +887,8 @@ static void bh_transmit(MGSLPC_INFO *info) | |||
887 | if (debug_level >= DEBUG_LEVEL_BH) | 887 | if (debug_level >= DEBUG_LEVEL_BH) |
888 | printk("bh_transmit() entry on %s\n", info->device_name); | 888 | printk("bh_transmit() entry on %s\n", info->device_name); |
889 | 889 | ||
890 | if (tty) { | 890 | if (tty) |
891 | tty_wakeup(tty); | 891 | tty_wakeup(tty); |
892 | wake_up_interruptible(&tty->write_wait); | ||
893 | } | ||
894 | } | 892 | } |
895 | 893 | ||
896 | static void bh_status(MGSLPC_INFO *info) | 894 | static void bh_status(MGSLPC_INFO *info) |
@@ -1363,9 +1361,7 @@ static int startup(MGSLPC_INFO * info) | |||
1363 | 1361 | ||
1364 | memset(&info->icount, 0, sizeof(info->icount)); | 1362 | memset(&info->icount, 0, sizeof(info->icount)); |
1365 | 1363 | ||
1366 | init_timer(&info->tx_timer); | 1364 | setup_timer(&info->tx_timer, tx_timeout, (unsigned long)info); |
1367 | info->tx_timer.data = (unsigned long)info; | ||
1368 | info->tx_timer.function = tx_timeout; | ||
1369 | 1365 | ||
1370 | /* Allocate and claim adapter resources */ | 1366 | /* Allocate and claim adapter resources */ |
1371 | retval = claim_resources(info); | 1367 | retval = claim_resources(info); |
@@ -1410,7 +1406,7 @@ static void shutdown(MGSLPC_INFO * info) | |||
1410 | wake_up_interruptible(&info->status_event_wait_q); | 1406 | wake_up_interruptible(&info->status_event_wait_q); |
1411 | wake_up_interruptible(&info->event_wait_q); | 1407 | wake_up_interruptible(&info->event_wait_q); |
1412 | 1408 | ||
1413 | del_timer(&info->tx_timer); | 1409 | del_timer_sync(&info->tx_timer); |
1414 | 1410 | ||
1415 | if (info->tx_buf) { | 1411 | if (info->tx_buf) { |
1416 | free_page((unsigned long) info->tx_buf); | 1412 | free_page((unsigned long) info->tx_buf); |
@@ -3551,8 +3547,8 @@ static void tx_start(MGSLPC_INFO *info) | |||
3551 | } else { | 3547 | } else { |
3552 | info->tx_active = 1; | 3548 | info->tx_active = 1; |
3553 | tx_ready(info); | 3549 | tx_ready(info); |
3554 | info->tx_timer.expires = jiffies + msecs_to_jiffies(5000); | 3550 | mod_timer(&info->tx_timer, jiffies + |
3555 | add_timer(&info->tx_timer); | 3551 | msecs_to_jiffies(5000)); |
3556 | } | 3552 | } |
3557 | } | 3553 | } |
3558 | 3554 | ||
diff --git a/drivers/char/random.c b/drivers/char/random.c index 13d0b1350a62..b9dc7aa1dfb3 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -1117,14 +1117,14 @@ random_ioctl(struct inode * inode, struct file * file, | |||
1117 | } | 1117 | } |
1118 | } | 1118 | } |
1119 | 1119 | ||
1120 | struct file_operations random_fops = { | 1120 | const struct file_operations random_fops = { |
1121 | .read = random_read, | 1121 | .read = random_read, |
1122 | .write = random_write, | 1122 | .write = random_write, |
1123 | .poll = random_poll, | 1123 | .poll = random_poll, |
1124 | .ioctl = random_ioctl, | 1124 | .ioctl = random_ioctl, |
1125 | }; | 1125 | }; |
1126 | 1126 | ||
1127 | struct file_operations urandom_fops = { | 1127 | const struct file_operations urandom_fops = { |
1128 | .read = urandom_read, | 1128 | .read = urandom_read, |
1129 | .write = random_write, | 1129 | .write = random_write, |
1130 | .ioctl = random_ioctl, | 1130 | .ioctl = random_ioctl, |
diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 645e20a06ece..1f0d7c60c944 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c | |||
@@ -154,7 +154,7 @@ static int raw_ctl_ioctl(struct inode *inode, struct file *filp, | |||
154 | goto out; | 154 | goto out; |
155 | } | 155 | } |
156 | 156 | ||
157 | if (rq.raw_minor < 0 || rq.raw_minor >= MAX_RAW_MINORS) { | 157 | if (rq.raw_minor <= 0 || rq.raw_minor >= MAX_RAW_MINORS) { |
158 | err = -EINVAL; | 158 | err = -EINVAL; |
159 | goto out; | 159 | goto out; |
160 | } | 160 | } |
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index e79b2ede8510..85c161845260 100644 --- a/drivers/char/rio/rio_linux.c +++ b/drivers/char/rio/rio_linux.c | |||
@@ -418,8 +418,7 @@ static void rio_pollfunc(unsigned long data) | |||
418 | func_enter(); | 418 | func_enter(); |
419 | 419 | ||
420 | rio_interrupt(0, &p->RIOHosts[data]); | 420 | rio_interrupt(0, &p->RIOHosts[data]); |
421 | p->RIOHosts[data].timer.expires = jiffies + rio_poll; | 421 | mod_timer(&p->RIOHosts[data].timer, jiffies + rio_poll); |
422 | add_timer(&p->RIOHosts[data].timer); | ||
423 | 422 | ||
424 | func_exit(); | 423 | func_exit(); |
425 | } | 424 | } |
@@ -1154,13 +1153,10 @@ static int __init rio_init(void) | |||
1154 | /* Init the timer "always" to make sure that it can safely be | 1153 | /* Init the timer "always" to make sure that it can safely be |
1155 | deleted when we unload... */ | 1154 | deleted when we unload... */ |
1156 | 1155 | ||
1157 | init_timer(&hp->timer); | 1156 | setup_timer(&hp->timer, rio_pollfunc, i); |
1158 | if (!hp->Ivec) { | 1157 | if (!hp->Ivec) { |
1159 | rio_dprintk(RIO_DEBUG_INIT, "Starting polling at %dj intervals.\n", rio_poll); | 1158 | rio_dprintk(RIO_DEBUG_INIT, "Starting polling at %dj intervals.\n", rio_poll); |
1160 | hp->timer.data = i; | 1159 | mod_timer(&hp->timer, jiffies + rio_poll); |
1161 | hp->timer.function = rio_pollfunc; | ||
1162 | hp->timer.expires = jiffies + rio_poll; | ||
1163 | add_timer(&hp->timer); | ||
1164 | } | 1160 | } |
1165 | } | 1161 | } |
1166 | 1162 | ||
@@ -1191,7 +1187,7 @@ static void __exit rio_exit(void) | |||
1191 | rio_dprintk(RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec); | 1187 | rio_dprintk(RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec); |
1192 | } | 1188 | } |
1193 | /* It is safe/allowed to del_timer a non-active timer */ | 1189 | /* It is safe/allowed to del_timer a non-active timer */ |
1194 | del_timer(&hp->timer); | 1190 | del_timer_sync(&hp->timer); |
1195 | if (hp->Caddr) | 1191 | if (hp->Caddr) |
1196 | iounmap(hp->Caddr); | 1192 | iounmap(hp->Caddr); |
1197 | if (hp->Type == RIO_PCI) | 1193 | if (hp->Type == RIO_PCI) |
diff --git a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c index eeda40c5e189..ebc76342712c 100644 --- a/drivers/char/rio/riointr.c +++ b/drivers/char/rio/riointr.c | |||
@@ -162,13 +162,8 @@ void RIOTxEnable(char *en) | |||
162 | 162 | ||
163 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | 163 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); |
164 | 164 | ||
165 | if (PortP->gs.xmit_cnt <= (PortP->gs.wakeup_chars + 2 * PKT_MAX_DATA_LEN)) { | 165 | if (PortP->gs.xmit_cnt <= (PortP->gs.wakeup_chars + 2 * PKT_MAX_DATA_LEN)) |
166 | rio_dprintk(RIO_DEBUG_INTR, "Waking up.... ldisc:%d (%d/%d)....", (int) (PortP->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)), PortP->gs.wakeup_chars, PortP->gs.xmit_cnt); | 166 | tty_wakeup(PortP->gs.tty); |
167 | if ((PortP->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && PortP->gs.tty->ldisc.write_wakeup) | ||
168 | (PortP->gs.tty->ldisc.write_wakeup) (PortP->gs.tty); | ||
169 | rio_dprintk(RIO_DEBUG_INTR, "(%d/%d)\n", PortP->gs.wakeup_chars, PortP->gs.xmit_cnt); | ||
170 | wake_up_interruptible(&PortP->gs.tty->write_wait); | ||
171 | } | ||
172 | 167 | ||
173 | } | 168 | } |
174 | 169 | ||
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index e2a94bfb2a43..70145254fb9d 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c | |||
@@ -1229,7 +1229,6 @@ static void rc_flush_buffer(struct tty_struct *tty) | |||
1229 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; | 1229 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; |
1230 | restore_flags(flags); | 1230 | restore_flags(flags); |
1231 | 1231 | ||
1232 | wake_up_interruptible(&tty->write_wait); | ||
1233 | tty_wakeup(tty); | 1232 | tty_wakeup(tty); |
1234 | } | 1233 | } |
1235 | 1234 | ||
@@ -1570,10 +1569,8 @@ static void do_softint(struct work_struct *ugly_api) | |||
1570 | if(!(tty = port->tty)) | 1569 | if(!(tty = port->tty)) |
1571 | return; | 1570 | return; |
1572 | 1571 | ||
1573 | if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) { | 1572 | if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) |
1574 | tty_wakeup(tty); | 1573 | tty_wakeup(tty); |
1575 | wake_up_interruptible(&tty->write_wait); | ||
1576 | } | ||
1577 | } | 1574 | } |
1578 | 1575 | ||
1579 | static const struct tty_operations riscom_ops = { | 1576 | static const struct tty_operations riscom_ops = { |
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index e94a62e30fc4..76357c855ce3 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c | |||
@@ -106,6 +106,8 @@ | |||
106 | 106 | ||
107 | /****** RocketPort Local Variables ******/ | 107 | /****** RocketPort Local Variables ******/ |
108 | 108 | ||
109 | static void rp_do_poll(unsigned long dummy); | ||
110 | |||
109 | static struct tty_driver *rocket_driver; | 111 | static struct tty_driver *rocket_driver; |
110 | 112 | ||
111 | static struct rocket_version driver_version = { | 113 | static struct rocket_version driver_version = { |
@@ -116,7 +118,7 @@ static struct r_port *rp_table[MAX_RP_PORTS]; /* The main repository of | |||
116 | static unsigned int xmit_flags[NUM_BOARDS]; /* Bit significant, indicates port had data to transmit. */ | 118 | static unsigned int xmit_flags[NUM_BOARDS]; /* Bit significant, indicates port had data to transmit. */ |
117 | /* eg. Bit 0 indicates port 0 has xmit data, ... */ | 119 | /* eg. Bit 0 indicates port 0 has xmit data, ... */ |
118 | static atomic_t rp_num_ports_open; /* Number of serial ports open */ | 120 | static atomic_t rp_num_ports_open; /* Number of serial ports open */ |
119 | static struct timer_list rocket_timer; | 121 | static DEFINE_TIMER(rocket_timer, rp_do_poll, 0, 0); |
120 | 122 | ||
121 | static unsigned long board1; /* ISA addresses, retrieved from rocketport.conf */ | 123 | static unsigned long board1; /* ISA addresses, retrieved from rocketport.conf */ |
122 | static unsigned long board2; | 124 | static unsigned long board2; |
@@ -474,7 +476,6 @@ static void rp_do_transmit(struct r_port *info) | |||
474 | 476 | ||
475 | if (info->xmit_cnt < WAKEUP_CHARS) { | 477 | if (info->xmit_cnt < WAKEUP_CHARS) { |
476 | tty_wakeup(tty); | 478 | tty_wakeup(tty); |
477 | wake_up_interruptible(&tty->write_wait); | ||
478 | #ifdef ROCKETPORT_HAVE_POLL_WAIT | 479 | #ifdef ROCKETPORT_HAVE_POLL_WAIT |
479 | wake_up_interruptible(&tty->poll_wait); | 480 | wake_up_interruptible(&tty->poll_wait); |
480 | #endif | 481 | #endif |
@@ -1772,7 +1773,6 @@ static int rp_write(struct tty_struct *tty, | |||
1772 | end: | 1773 | end: |
1773 | if (info->xmit_cnt < WAKEUP_CHARS) { | 1774 | if (info->xmit_cnt < WAKEUP_CHARS) { |
1774 | tty_wakeup(tty); | 1775 | tty_wakeup(tty); |
1775 | wake_up_interruptible(&tty->write_wait); | ||
1776 | #ifdef ROCKETPORT_HAVE_POLL_WAIT | 1776 | #ifdef ROCKETPORT_HAVE_POLL_WAIT |
1777 | wake_up_interruptible(&tty->poll_wait); | 1777 | wake_up_interruptible(&tty->poll_wait); |
1778 | #endif | 1778 | #endif |
@@ -1841,7 +1841,6 @@ static void rp_flush_buffer(struct tty_struct *tty) | |||
1841 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | 1841 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; |
1842 | spin_unlock_irqrestore(&info->slock, flags); | 1842 | spin_unlock_irqrestore(&info->slock, flags); |
1843 | 1843 | ||
1844 | wake_up_interruptible(&tty->write_wait); | ||
1845 | #ifdef ROCKETPORT_HAVE_POLL_WAIT | 1844 | #ifdef ROCKETPORT_HAVE_POLL_WAIT |
1846 | wake_up_interruptible(&tty->poll_wait); | 1845 | wake_up_interruptible(&tty->poll_wait); |
1847 | #endif | 1846 | #endif |
@@ -2371,12 +2370,6 @@ static int __init rp_init(void) | |||
2371 | return -ENOMEM; | 2370 | return -ENOMEM; |
2372 | 2371 | ||
2373 | /* | 2372 | /* |
2374 | * Set up the timer channel. | ||
2375 | */ | ||
2376 | init_timer(&rocket_timer); | ||
2377 | rocket_timer.function = rp_do_poll; | ||
2378 | |||
2379 | /* | ||
2380 | * Initialize the array of pointers to our own internal state | 2373 | * Initialize the array of pointers to our own internal state |
2381 | * structures. | 2374 | * structures. |
2382 | */ | 2375 | */ |
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 664f36c98e6a..b6d3072dce5a 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c | |||
@@ -135,7 +135,9 @@ static struct fasync_struct *rtc_async_queue; | |||
135 | static DECLARE_WAIT_QUEUE_HEAD(rtc_wait); | 135 | static DECLARE_WAIT_QUEUE_HEAD(rtc_wait); |
136 | 136 | ||
137 | #ifdef RTC_IRQ | 137 | #ifdef RTC_IRQ |
138 | static struct timer_list rtc_irq_timer; | 138 | static void rtc_dropped_irq(unsigned long data); |
139 | |||
140 | static DEFINE_TIMER(rtc_irq_timer, rtc_dropped_irq, 0, 0); | ||
139 | #endif | 141 | #endif |
140 | 142 | ||
141 | static ssize_t rtc_read(struct file *file, char __user *buf, | 143 | static ssize_t rtc_read(struct file *file, char __user *buf, |
@@ -150,8 +152,6 @@ static unsigned int rtc_poll(struct file *file, poll_table *wait); | |||
150 | 152 | ||
151 | static void get_rtc_alm_time (struct rtc_time *alm_tm); | 153 | static void get_rtc_alm_time (struct rtc_time *alm_tm); |
152 | #ifdef RTC_IRQ | 154 | #ifdef RTC_IRQ |
153 | static void rtc_dropped_irq(unsigned long data); | ||
154 | |||
155 | static void set_rtc_irq_bit_locked(unsigned char bit); | 155 | static void set_rtc_irq_bit_locked(unsigned char bit); |
156 | static void mask_rtc_irq_bit_locked(unsigned char bit); | 156 | static void mask_rtc_irq_bit_locked(unsigned char bit); |
157 | 157 | ||
@@ -454,8 +454,8 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) | |||
454 | 454 | ||
455 | spin_lock_irqsave (&rtc_lock, flags); | 455 | spin_lock_irqsave (&rtc_lock, flags); |
456 | if (!(rtc_status & RTC_TIMER_ON)) { | 456 | if (!(rtc_status & RTC_TIMER_ON)) { |
457 | rtc_irq_timer.expires = jiffies + HZ/rtc_freq + 2*HZ/100; | 457 | mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq + |
458 | add_timer(&rtc_irq_timer); | 458 | 2*HZ/100); |
459 | rtc_status |= RTC_TIMER_ON; | 459 | rtc_status |= RTC_TIMER_ON; |
460 | } | 460 | } |
461 | set_rtc_irq_bit_locked(RTC_PIE); | 461 | set_rtc_irq_bit_locked(RTC_PIE); |
@@ -1084,8 +1084,6 @@ no_irq: | |||
1084 | if (rtc_has_irq == 0) | 1084 | if (rtc_has_irq == 0) |
1085 | goto no_irq2; | 1085 | goto no_irq2; |
1086 | 1086 | ||
1087 | init_timer(&rtc_irq_timer); | ||
1088 | rtc_irq_timer.function = rtc_dropped_irq; | ||
1089 | spin_lock_irq(&rtc_lock); | 1087 | spin_lock_irq(&rtc_lock); |
1090 | rtc_freq = 1024; | 1088 | rtc_freq = 1024; |
1091 | if (!hpet_set_periodic_freq(rtc_freq)) { | 1089 | if (!hpet_set_periodic_freq(rtc_freq)) { |
diff --git a/drivers/char/scan_keyb.c b/drivers/char/scan_keyb.c deleted file mode 100644 index 2b5bb4f5754d..000000000000 --- a/drivers/char/scan_keyb.c +++ /dev/null | |||
@@ -1,149 +0,0 @@ | |||
1 | /* | ||
2 | * $Id: scan_keyb.c,v 1.2 2000/07/04 06:24:42 yaegashi Exp $ | ||
3 | * Copyright (C) 2000 YAEGASHI Takeshi | ||
4 | * Generic scan keyboard driver | ||
5 | */ | ||
6 | |||
7 | #include <linux/spinlock.h> | ||
8 | #include <linux/sched.h> | ||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/tty.h> | ||
11 | #include <linux/mm.h> | ||
12 | #include <linux/signal.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/kbd_ll.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/random.h> | ||
17 | #include <linux/poll.h> | ||
18 | #include <linux/miscdevice.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/kbd_kern.h> | ||
21 | #include <linux/timer.h> | ||
22 | |||
23 | #define SCANHZ (HZ/20) | ||
24 | |||
25 | struct scan_keyboard { | ||
26 | struct scan_keyboard *next; | ||
27 | int (*scan)(unsigned char *buffer); | ||
28 | const unsigned char *table; | ||
29 | unsigned char *s0, *s1; | ||
30 | int length; | ||
31 | }; | ||
32 | |||
33 | static int scan_jiffies=0; | ||
34 | static struct scan_keyboard *keyboards=NULL; | ||
35 | struct timer_list scan_timer; | ||
36 | |||
37 | static void check_kbd(const unsigned char *table, | ||
38 | unsigned char *new, unsigned char *old, int length) | ||
39 | { | ||
40 | int need_tasklet_schedule=0; | ||
41 | unsigned int xor, bit; | ||
42 | |||
43 | while(length-->0) { | ||
44 | if((xor=*new^*old)==0) { | ||
45 | table+=8; | ||
46 | } | ||
47 | else { | ||
48 | for(bit=0x01; bit<0x100; bit<<=1) { | ||
49 | if(xor&bit) { | ||
50 | handle_scancode(*table, !(*new&bit)); | ||
51 | need_tasklet_schedule=1; | ||
52 | #if 0 | ||
53 | printk("0x%x %s\n", *table, (*new&bit)?"released":"pressed"); | ||
54 | #endif | ||
55 | } | ||
56 | table++; | ||
57 | } | ||
58 | } | ||
59 | new++; old++; | ||
60 | } | ||
61 | |||
62 | if(need_tasklet_schedule) | ||
63 | tasklet_schedule(&keyboard_tasklet); | ||
64 | } | ||
65 | |||
66 | |||
67 | static void scan_kbd(unsigned long dummy) | ||
68 | { | ||
69 | struct scan_keyboard *kbd; | ||
70 | |||
71 | scan_jiffies++; | ||
72 | |||
73 | for(kbd=keyboards; kbd!=NULL; kbd=kbd->next) { | ||
74 | if(scan_jiffies&1) { | ||
75 | if(!kbd->scan(kbd->s0)) | ||
76 | check_kbd(kbd->table, | ||
77 | kbd->s0, kbd->s1, kbd->length); | ||
78 | else | ||
79 | memcpy(kbd->s0, kbd->s1, kbd->length); | ||
80 | } | ||
81 | else { | ||
82 | if(!kbd->scan(kbd->s1)) | ||
83 | check_kbd(kbd->table, | ||
84 | kbd->s1, kbd->s0, kbd->length); | ||
85 | else | ||
86 | memcpy(kbd->s1, kbd->s0, kbd->length); | ||
87 | } | ||
88 | |||
89 | } | ||
90 | |||
91 | init_timer(&scan_timer); | ||
92 | scan_timer.expires = jiffies + SCANHZ; | ||
93 | scan_timer.data = 0; | ||
94 | scan_timer.function = scan_kbd; | ||
95 | add_timer(&scan_timer); | ||
96 | } | ||
97 | |||
98 | |||
99 | int register_scan_keyboard(int (*scan)(unsigned char *buffer), | ||
100 | const unsigned char *table, | ||
101 | int length) | ||
102 | { | ||
103 | struct scan_keyboard *kbd; | ||
104 | |||
105 | kbd = kmalloc(sizeof(struct scan_keyboard), GFP_KERNEL); | ||
106 | if (kbd == NULL) | ||
107 | goto error_out; | ||
108 | |||
109 | kbd->scan=scan; | ||
110 | kbd->table=table; | ||
111 | kbd->length=length; | ||
112 | |||
113 | kbd->s0 = kmalloc(length, GFP_KERNEL); | ||
114 | if (kbd->s0 == NULL) | ||
115 | goto error_free_kbd; | ||
116 | |||
117 | kbd->s1 = kmalloc(length, GFP_KERNEL); | ||
118 | if (kbd->s1 == NULL) | ||
119 | goto error_free_s0; | ||
120 | |||
121 | memset(kbd->s0, -1, kbd->length); | ||
122 | memset(kbd->s1, -1, kbd->length); | ||
123 | |||
124 | kbd->next=keyboards; | ||
125 | keyboards=kbd; | ||
126 | |||
127 | return 0; | ||
128 | |||
129 | error_free_s0: | ||
130 | kfree(kbd->s0); | ||
131 | |||
132 | error_free_kbd: | ||
133 | kfree(kbd); | ||
134 | |||
135 | error_out: | ||
136 | return -ENOMEM; | ||
137 | } | ||
138 | |||
139 | |||
140 | void __init scan_kbd_init(void) | ||
141 | { | ||
142 | init_timer(&scan_timer); | ||
143 | scan_timer.expires = jiffies + SCANHZ; | ||
144 | scan_timer.data = 0; | ||
145 | scan_timer.function = scan_kbd; | ||
146 | add_timer(&scan_timer); | ||
147 | |||
148 | printk(KERN_INFO "Generic scan keyboard driver initialized\n"); | ||
149 | } | ||
diff --git a/drivers/char/scan_keyb.h b/drivers/char/scan_keyb.h deleted file mode 100644 index b4b611290a00..000000000000 --- a/drivers/char/scan_keyb.h +++ /dev/null | |||
@@ -1,15 +0,0 @@ | |||
1 | #ifndef __DRIVER_CHAR_SCAN_KEYB_H | ||
2 | #define __DRIVER_CHAR_SCAN_KEYB_H | ||
3 | /* | ||
4 | * $Id: scan_keyb.h,v 1.1 2000/06/10 21:45:30 yaegashi Exp $ | ||
5 | * Copyright (C) 2000 YAEGASHI Takeshi | ||
6 | * Generic scan keyboard driver | ||
7 | */ | ||
8 | |||
9 | int register_scan_keyboard(int (*scan)(unsigned char *buffer), | ||
10 | const unsigned char *table, | ||
11 | int length); | ||
12 | |||
13 | void __init scan_kbd_init(void); | ||
14 | |||
15 | #endif | ||
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index af50d32ae2c7..5fd314adc1f2 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c | |||
@@ -111,12 +111,13 @@ u_char initial_console_speed; | |||
111 | 111 | ||
112 | /* This is the per-port data structure */ | 112 | /* This is the per-port data structure */ |
113 | struct cyclades_port cy_port[] = { | 113 | struct cyclades_port cy_port[] = { |
114 | /* CARD# */ | 114 | /* CARD# */ |
115 | {-1 }, /* ttyS0 */ | 115 | {-1}, /* ttyS0 */ |
116 | {-1 }, /* ttyS1 */ | 116 | {-1}, /* ttyS1 */ |
117 | {-1 }, /* ttyS2 */ | 117 | {-1}, /* ttyS2 */ |
118 | {-1 }, /* ttyS3 */ | 118 | {-1}, /* ttyS3 */ |
119 | }; | 119 | }; |
120 | |||
120 | #define NR_PORTS ARRAY_SIZE(cy_port) | 121 | #define NR_PORTS ARRAY_SIZE(cy_port) |
121 | 122 | ||
122 | /* | 123 | /* |
@@ -128,42 +129,46 @@ struct cyclades_port cy_port[] = { | |||
128 | * HI VHI | 129 | * HI VHI |
129 | */ | 130 | */ |
130 | static int baud_table[] = { | 131 | static int baud_table[] = { |
131 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, | 132 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, |
132 | 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800,115200,150000, | 133 | 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000, |
133 | 0}; | 134 | 0 |
135 | }; | ||
134 | 136 | ||
135 | #if 0 | 137 | #if 0 |
136 | static char baud_co[] = { /* 25 MHz clock option table */ | 138 | static char baud_co[] = { /* 25 MHz clock option table */ |
137 | /* value => 00 01 02 03 04 */ | 139 | /* value => 00 01 02 03 04 */ |
138 | /* divide by 8 32 128 512 2048 */ | 140 | /* divide by 8 32 128 512 2048 */ |
139 | 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02, | 141 | 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02, |
140 | 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | 142 | 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
143 | }; | ||
141 | 144 | ||
142 | static char baud_bpr[] = { /* 25 MHz baud rate period table */ | 145 | static char baud_bpr[] = { /* 25 MHz baud rate period table */ |
143 | 0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3, | 146 | 0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3, |
144 | 0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15}; | 147 | 0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15 |
148 | }; | ||
145 | #endif | 149 | #endif |
146 | 150 | ||
147 | /* I think 166 brd clocks 2401 at 20MHz.... */ | 151 | /* I think 166 brd clocks 2401 at 20MHz.... */ |
148 | 152 | ||
149 | /* These values are written directly to tcor, and >> 5 for writing to rcor */ | 153 | /* These values are written directly to tcor, and >> 5 for writing to rcor */ |
150 | static u_char baud_co[] = { /* 20 MHz clock option table */ | 154 | static u_char baud_co[] = { /* 20 MHz clock option table */ |
151 | 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x60, 0x60, 0x40, | 155 | 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x60, 0x60, 0x40, |
152 | 0x40, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | 156 | 0x40, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
157 | }; | ||
153 | 158 | ||
154 | /* These values written directly to tbpr/rbpr */ | 159 | /* These values written directly to tbpr/rbpr */ |
155 | static u_char baud_bpr[] = { /* 20 MHz baud rate period table */ | 160 | static u_char baud_bpr[] = { /* 20 MHz baud rate period table */ |
156 | 0x00, 0xc0, 0x80, 0x58, 0x6c, 0x40, 0xc0, 0x81, 0x40, 0x81, | 161 | 0x00, 0xc0, 0x80, 0x58, 0x6c, 0x40, 0xc0, 0x81, 0x40, 0x81, |
157 | 0x57, 0x40, 0x81, 0x40, 0x81, 0x40, 0x2b, 0x20, 0x15, 0x10}; | 162 | 0x57, 0x40, 0x81, 0x40, 0x81, 0x40, 0x2b, 0x20, 0x15, 0x10 |
158 | 163 | }; | |
159 | static u_char baud_cor4[] = { /* receive threshold */ | ||
160 | 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, | ||
161 | 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07}; | ||
162 | |||
163 | 164 | ||
165 | static u_char baud_cor4[] = { /* receive threshold */ | ||
166 | 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, | ||
167 | 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07 | ||
168 | }; | ||
164 | 169 | ||
165 | static void shutdown(struct cyclades_port *); | 170 | static void shutdown(struct cyclades_port *); |
166 | static int startup (struct cyclades_port *); | 171 | static int startup(struct cyclades_port *); |
167 | static void cy_throttle(struct tty_struct *); | 172 | static void cy_throttle(struct tty_struct *); |
168 | static void cy_unthrottle(struct tty_struct *); | 173 | static void cy_unthrottle(struct tty_struct *); |
169 | static void config_setup(struct cyclades_port *); | 174 | static void config_setup(struct cyclades_port *); |
@@ -174,16 +179,16 @@ static void show_status(int); | |||
174 | 179 | ||
175 | #ifdef CONFIG_REMOTE_DEBUG | 180 | #ifdef CONFIG_REMOTE_DEBUG |
176 | static void debug_setup(void); | 181 | static void debug_setup(void); |
177 | void queueDebugChar (int c); | 182 | void queueDebugChar(int c); |
178 | int getDebugChar(void); | 183 | int getDebugChar(void); |
179 | 184 | ||
180 | #define DEBUG_PORT 1 | 185 | #define DEBUG_PORT 1 |
181 | #define DEBUG_LEN 256 | 186 | #define DEBUG_LEN 256 |
182 | 187 | ||
183 | typedef struct { | 188 | typedef struct { |
184 | int in; | 189 | int in; |
185 | int out; | 190 | int out; |
186 | unsigned char buf[DEBUG_LEN]; | 191 | unsigned char buf[DEBUG_LEN]; |
187 | } debugq; | 192 | } debugq; |
188 | 193 | ||
189 | debugq debugiq; | 194 | debugq debugiq; |
@@ -196,7 +201,7 @@ debugq debugiq; | |||
196 | * delay, but this wild guess will do for now. | 201 | * delay, but this wild guess will do for now. |
197 | */ | 202 | */ |
198 | 203 | ||
199 | void my_udelay (long us) | 204 | void my_udelay(long us) |
200 | { | 205 | { |
201 | u_char x; | 206 | u_char x; |
202 | volatile u_char *p = &x; | 207 | volatile u_char *p = &x; |
@@ -207,62 +212,73 @@ void my_udelay (long us) | |||
207 | x |= *p; | 212 | x |= *p; |
208 | } | 213 | } |
209 | 214 | ||
210 | static inline int | 215 | static inline int serial_paranoia_check(struct cyclades_port *info, char *name, |
211 | serial_paranoia_check(struct cyclades_port *info, char *name, | 216 | const char *routine) |
212 | const char *routine) | ||
213 | { | 217 | { |
214 | #ifdef SERIAL_PARANOIA_CHECK | 218 | #ifdef SERIAL_PARANOIA_CHECK |
215 | static const char *badmagic = | 219 | if (!info) { |
216 | "Warning: bad magic number for serial struct (%s) in %s\n"; | 220 | printk("Warning: null cyclades_port for (%s) in %s\n", name, |
217 | static const char *badinfo = | 221 | routine); |
218 | "Warning: null cyclades_port for (%s) in %s\n"; | 222 | return 1; |
219 | static const char *badrange = | 223 | } |
220 | "Warning: cyclades_port out of range for (%s) in %s\n"; | 224 | |
221 | 225 | if ((long)info < (long)(&cy_port[0]) | |
222 | if (!info) { | 226 | || (long)(&cy_port[NR_PORTS]) < (long)info) { |
223 | printk(badinfo, name, routine); | 227 | printk("Warning: cyclades_port out of range for (%s) in %s\n", |
224 | return 1; | 228 | name, routine); |
225 | } | 229 | return 1; |
226 | 230 | } | |
227 | if( (long)info < (long)(&cy_port[0]) | 231 | |
228 | || (long)(&cy_port[NR_PORTS]) < (long)info ){ | 232 | if (info->magic != CYCLADES_MAGIC) { |
229 | printk(badrange, name, routine); | 233 | printk("Warning: bad magic number for serial struct (%s) in " |
230 | return 1; | 234 | "%s\n", name, routine); |
231 | } | 235 | return 1; |
232 | 236 | } | |
233 | if (info->magic != CYCLADES_MAGIC) { | ||
234 | printk(badmagic, name, routine); | ||
235 | return 1; | ||
236 | } | ||
237 | #endif | 237 | #endif |
238 | return 0; | 238 | return 0; |
239 | } /* serial_paranoia_check */ | 239 | } /* serial_paranoia_check */ |
240 | 240 | ||
241 | #if 0 | 241 | #if 0 |
242 | /* The following diagnostic routines allow the driver to spew | 242 | /* The following diagnostic routines allow the driver to spew |
243 | information on the screen, even (especially!) during interrupts. | 243 | information on the screen, even (especially!) during interrupts. |
244 | */ | 244 | */ |
245 | void | 245 | void SP(char *data) |
246 | SP(char *data){ | 246 | { |
247 | unsigned long flags; | 247 | unsigned long flags; |
248 | local_irq_save(flags); | 248 | local_irq_save(flags); |
249 | console_print(data); | 249 | console_print(data); |
250 | local_irq_restore(flags); | 250 | local_irq_restore(flags); |
251 | } | 251 | } |
252 | |||
252 | char scrn[2]; | 253 | char scrn[2]; |
253 | void | 254 | void CP(char data) |
254 | CP(char data){ | 255 | { |
255 | unsigned long flags; | 256 | unsigned long flags; |
256 | local_irq_save(flags); | 257 | local_irq_save(flags); |
257 | scrn[0] = data; | 258 | scrn[0] = data; |
258 | console_print(scrn); | 259 | console_print(scrn); |
259 | local_irq_restore(flags); | 260 | local_irq_restore(flags); |
260 | }/* CP */ | 261 | } /* CP */ |
261 | 262 | ||
262 | void CP1(int data) { (data<10)? CP(data+'0'): CP(data+'A'-10); }/* CP1 */ | 263 | void CP1(int data) |
263 | void CP2(int data) { CP1((data>>4) & 0x0f); CP1( data & 0x0f); }/* CP2 */ | 264 | { |
264 | void CP4(int data) { CP2((data>>8) & 0xff); CP2(data & 0xff); }/* CP4 */ | 265 | (data < 10) ? CP(data + '0') : CP(data + 'A' - 10); |
265 | void CP8(long data) { CP4((data>>16) & 0xffff); CP4(data & 0xffff); }/* CP8 */ | 266 | } /* CP1 */ |
267 | void CP2(int data) | ||
268 | { | ||
269 | CP1((data >> 4) & 0x0f); | ||
270 | CP1(data & 0x0f); | ||
271 | } /* CP2 */ | ||
272 | void CP4(int data) | ||
273 | { | ||
274 | CP2((data >> 8) & 0xff); | ||
275 | CP2(data & 0xff); | ||
276 | } /* CP4 */ | ||
277 | void CP8(long data) | ||
278 | { | ||
279 | CP4((data >> 16) & 0xffff); | ||
280 | CP4(data & 0xffff); | ||
281 | } /* CP8 */ | ||
266 | #endif | 282 | #endif |
267 | 283 | ||
268 | /* This routine waits up to 1000 micro-seconds for the previous | 284 | /* This routine waits up to 1000 micro-seconds for the previous |
@@ -270,87 +286,78 @@ void CP8(long data) { CP4((data>>16) & 0xffff); CP4(data & 0xffff); }/* CP8 */ | |||
270 | new command. An error is returned if the previous command | 286 | new command. An error is returned if the previous command |
271 | didn't finish within the time limit. | 287 | didn't finish within the time limit. |
272 | */ | 288 | */ |
273 | u_short | 289 | u_short write_cy_cmd(volatile u_char * base_addr, u_char cmd) |
274 | write_cy_cmd(volatile u_char *base_addr, u_char cmd) | ||
275 | { | 290 | { |
276 | unsigned long flags; | 291 | unsigned long flags; |
277 | volatile int i; | 292 | volatile int i; |
278 | 293 | ||
279 | local_irq_save(flags); | 294 | local_irq_save(flags); |
280 | /* Check to see that the previous command has completed */ | 295 | /* Check to see that the previous command has completed */ |
281 | for(i = 0 ; i < 100 ; i++){ | 296 | for (i = 0; i < 100; i++) { |
282 | if (base_addr[CyCCR] == 0){ | 297 | if (base_addr[CyCCR] == 0) { |
283 | break; | 298 | break; |
284 | } | 299 | } |
285 | my_udelay(10L); | 300 | my_udelay(10L); |
286 | } | 301 | } |
287 | /* if the CCR never cleared, the previous command | 302 | /* if the CCR never cleared, the previous command |
288 | didn't finish within the "reasonable time" */ | 303 | didn't finish within the "reasonable time" */ |
289 | if ( i == 10 ) { | 304 | if (i == 10) { |
290 | local_irq_restore(flags); | 305 | local_irq_restore(flags); |
291 | return (-1); | 306 | return (-1); |
292 | } | 307 | } |
293 | 308 | ||
294 | /* Issue the new command */ | 309 | /* Issue the new command */ |
295 | base_addr[CyCCR] = cmd; | 310 | base_addr[CyCCR] = cmd; |
296 | local_irq_restore(flags); | 311 | local_irq_restore(flags); |
297 | return(0); | 312 | return (0); |
298 | } /* write_cy_cmd */ | 313 | } /* write_cy_cmd */ |
299 | |||
300 | 314 | ||
301 | /* cy_start and cy_stop provide software output flow control as a | 315 | /* cy_start and cy_stop provide software output flow control as a |
302 | function of XON/XOFF, software CTS, and other such stuff. */ | 316 | function of XON/XOFF, software CTS, and other such stuff. */ |
303 | 317 | ||
304 | static void | 318 | static void cy_stop(struct tty_struct *tty) |
305 | cy_stop(struct tty_struct *tty) | ||
306 | { | 319 | { |
307 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 320 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; |
308 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; | 321 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; |
309 | int channel; | 322 | int channel; |
310 | unsigned long flags; | 323 | unsigned long flags; |
311 | 324 | ||
312 | #ifdef SERIAL_DEBUG_OTHER | 325 | #ifdef SERIAL_DEBUG_OTHER |
313 | printk("cy_stop %s\n", tty->name); /* */ | 326 | printk("cy_stop %s\n", tty->name); /* */ |
314 | #endif | 327 | #endif |
315 | 328 | ||
316 | if (serial_paranoia_check(info, tty->name, "cy_stop")) | 329 | if (serial_paranoia_check(info, tty->name, "cy_stop")) |
317 | return; | 330 | return; |
318 | |||
319 | channel = info->line; | ||
320 | 331 | ||
321 | local_irq_save(flags); | 332 | channel = info->line; |
322 | base_addr[CyCAR] = (u_char)(channel); /* index channel */ | ||
323 | base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy); | ||
324 | local_irq_restore(flags); | ||
325 | 333 | ||
326 | return; | 334 | local_irq_save(flags); |
327 | } /* cy_stop */ | 335 | base_addr[CyCAR] = (u_char) (channel); /* index channel */ |
336 | base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); | ||
337 | local_irq_restore(flags); | ||
338 | } /* cy_stop */ | ||
328 | 339 | ||
329 | static void | 340 | static void cy_start(struct tty_struct *tty) |
330 | cy_start(struct tty_struct *tty) | ||
331 | { | 341 | { |
332 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 342 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; |
333 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; | 343 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; |
334 | int channel; | 344 | int channel; |
335 | unsigned long flags; | 345 | unsigned long flags; |
336 | 346 | ||
337 | #ifdef SERIAL_DEBUG_OTHER | 347 | #ifdef SERIAL_DEBUG_OTHER |
338 | printk("cy_start %s\n", tty->name); /* */ | 348 | printk("cy_start %s\n", tty->name); /* */ |
339 | #endif | 349 | #endif |
340 | 350 | ||
341 | if (serial_paranoia_check(info, tty->name, "cy_start")) | 351 | if (serial_paranoia_check(info, tty->name, "cy_start")) |
342 | return; | 352 | return; |
343 | |||
344 | channel = info->line; | ||
345 | 353 | ||
346 | local_irq_save(flags); | 354 | channel = info->line; |
347 | base_addr[CyCAR] = (u_char)(channel); | ||
348 | base_addr[CyIER] |= CyTxMpty; | ||
349 | local_irq_restore(flags); | ||
350 | |||
351 | return; | ||
352 | } /* cy_start */ | ||
353 | 355 | ||
356 | local_irq_save(flags); | ||
357 | base_addr[CyCAR] = (u_char) (channel); | ||
358 | base_addr[CyIER] |= CyTxMpty; | ||
359 | local_irq_restore(flags); | ||
360 | } /* cy_start */ | ||
354 | 361 | ||
355 | /* | 362 | /* |
356 | * This routine is used by the interrupt handler to schedule | 363 | * This routine is used by the interrupt handler to schedule |
@@ -358,332 +365,332 @@ cy_start(struct tty_struct *tty) | |||
358 | * (also known as the "bottom half"). This can be called any | 365 | * (also known as the "bottom half"). This can be called any |
359 | * number of times for any channel without harm. | 366 | * number of times for any channel without harm. |
360 | */ | 367 | */ |
361 | static inline void | 368 | static inline void cy_sched_event(struct cyclades_port *info, int event) |
362 | cy_sched_event(struct cyclades_port *info, int event) | ||
363 | { | 369 | { |
364 | info->event |= 1 << event; /* remember what kind of event and who */ | 370 | info->event |= 1 << event; /* remember what kind of event and who */ |
365 | schedule_work(&info->tqueue); | 371 | schedule_work(&info->tqueue); |
366 | } /* cy_sched_event */ | 372 | } /* cy_sched_event */ |
367 | |||
368 | 373 | ||
369 | /* The real interrupt service routines are called | 374 | /* The real interrupt service routines are called |
370 | whenever the card wants its hand held--chars | 375 | whenever the card wants its hand held--chars |
371 | received, out buffer empty, modem change, etc. | 376 | received, out buffer empty, modem change, etc. |
372 | */ | 377 | */ |
373 | static irqreturn_t | 378 | static irqreturn_t cd2401_rxerr_interrupt(int irq, void *dev_id) |
374 | cd2401_rxerr_interrupt(int irq, void *dev_id) | ||
375 | { | 379 | { |
376 | struct tty_struct *tty; | 380 | struct tty_struct *tty; |
377 | struct cyclades_port *info; | 381 | struct cyclades_port *info; |
378 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; | 382 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; |
379 | unsigned char err, rfoc; | 383 | unsigned char err, rfoc; |
380 | int channel; | 384 | int channel; |
381 | char data; | 385 | char data; |
382 | 386 | ||
383 | /* determine the channel and change to that context */ | 387 | /* determine the channel and change to that context */ |
384 | channel = (u_short ) (base_addr[CyLICR] >> 2); | 388 | channel = (u_short) (base_addr[CyLICR] >> 2); |
385 | info = &cy_port[channel]; | 389 | info = &cy_port[channel]; |
386 | info->last_active = jiffies; | 390 | info->last_active = jiffies; |
387 | 391 | ||
388 | if ((err = base_addr[CyRISR]) & CyTIMEOUT) { | 392 | if ((err = base_addr[CyRISR]) & CyTIMEOUT) { |
389 | /* This is a receive timeout interrupt, ignore it */ | 393 | /* This is a receive timeout interrupt, ignore it */ |
390 | base_addr[CyREOIR] = CyNOTRANS; | 394 | base_addr[CyREOIR] = CyNOTRANS; |
391 | return IRQ_HANDLED; | 395 | return IRQ_HANDLED; |
392 | } | 396 | } |
393 | |||
394 | /* Read a byte of data if there is any - assume the error | ||
395 | * is associated with this character */ | ||
396 | 397 | ||
397 | if ((rfoc = base_addr[CyRFOC]) != 0) | 398 | /* Read a byte of data if there is any - assume the error |
398 | data = base_addr[CyRDR]; | 399 | * is associated with this character */ |
399 | else | ||
400 | data = 0; | ||
401 | 400 | ||
402 | /* if there is nowhere to put the data, discard it */ | 401 | if ((rfoc = base_addr[CyRFOC]) != 0) |
403 | if(info->tty == 0) { | 402 | data = base_addr[CyRDR]; |
403 | else | ||
404 | data = 0; | ||
405 | |||
406 | /* if there is nowhere to put the data, discard it */ | ||
407 | if (info->tty == 0) { | ||
408 | base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS; | ||
409 | return IRQ_HANDLED; | ||
410 | } else { /* there is an open port for this data */ | ||
411 | tty = info->tty; | ||
412 | if (err & info->ignore_status_mask) { | ||
413 | base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS; | ||
414 | return IRQ_HANDLED; | ||
415 | } | ||
416 | if (tty_buffer_request_room(tty, 1) != 0) { | ||
417 | if (err & info->read_status_mask) { | ||
418 | if (err & CyBREAK) { | ||
419 | tty_insert_flip_char(tty, data, | ||
420 | TTY_BREAK); | ||
421 | if (info->flags & ASYNC_SAK) { | ||
422 | do_SAK(tty); | ||
423 | } | ||
424 | } else if (err & CyFRAME) { | ||
425 | tty_insert_flip_char(tty, data, | ||
426 | TTY_FRAME); | ||
427 | } else if (err & CyPARITY) { | ||
428 | tty_insert_flip_char(tty, data, | ||
429 | TTY_PARITY); | ||
430 | } else if (err & CyOVERRUN) { | ||
431 | tty_insert_flip_char(tty, 0, | ||
432 | TTY_OVERRUN); | ||
433 | /* | ||
434 | If the flip buffer itself is | ||
435 | overflowing, we still loose | ||
436 | the next incoming character. | ||
437 | */ | ||
438 | if (tty_buffer_request_room(tty, 1) != | ||
439 | 0) { | ||
440 | tty_insert_flip_char(tty, data, | ||
441 | TTY_FRAME); | ||
442 | } | ||
443 | /* These two conditions may imply */ | ||
444 | /* a normal read should be done. */ | ||
445 | /* else if(data & CyTIMEOUT) */ | ||
446 | /* else if(data & CySPECHAR) */ | ||
447 | } else { | ||
448 | tty_insert_flip_char(tty, 0, | ||
449 | TTY_NORMAL); | ||
450 | } | ||
451 | } else { | ||
452 | tty_insert_flip_char(tty, data, TTY_NORMAL); | ||
453 | } | ||
454 | } else { | ||
455 | /* there was a software buffer overrun | ||
456 | and nothing could be done about it!!! */ | ||
457 | } | ||
458 | } | ||
459 | tty_schedule_flip(tty); | ||
460 | /* end of service */ | ||
404 | base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS; | 461 | base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS; |
405 | return IRQ_HANDLED; | 462 | return IRQ_HANDLED; |
406 | } | 463 | } /* cy_rxerr_interrupt */ |
407 | else { /* there is an open port for this data */ | 464 | |
408 | tty = info->tty; | 465 | static irqreturn_t cd2401_modem_interrupt(int irq, void *dev_id) |
409 | if(err & info->ignore_status_mask){ | ||
410 | base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS; | ||
411 | return IRQ_HANDLED; | ||
412 | } | ||
413 | if (tty_buffer_request_room(tty, 1) != 0){ | ||
414 | if (err & info->read_status_mask){ | ||
415 | if(err & CyBREAK){ | ||
416 | tty_insert_flip_char(tty, data, TTY_BREAK); | ||
417 | if (info->flags & ASYNC_SAK){ | ||
418 | do_SAK(tty); | ||
419 | } | ||
420 | }else if(err & CyFRAME){ | ||
421 | tty_insert_flip_char(tty, data, TTY_FRAME); | ||
422 | }else if(err & CyPARITY){ | ||
423 | tty_insert_flip_char(tty, data, TTY_PARITY); | ||
424 | }else if(err & CyOVERRUN){ | ||
425 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | ||
426 | /* | ||
427 | If the flip buffer itself is | ||
428 | overflowing, we still loose | ||
429 | the next incoming character. | ||
430 | */ | ||
431 | if (tty_buffer_request_room(tty, 1) != 0){ | ||
432 | tty_insert_flip_char(tty, data, TTY_FRAME); | ||
433 | } | ||
434 | /* These two conditions may imply */ | ||
435 | /* a normal read should be done. */ | ||
436 | /* else if(data & CyTIMEOUT) */ | ||
437 | /* else if(data & CySPECHAR) */ | ||
438 | }else{ | ||
439 | tty_insert_flip_char(tty, 0, TTY_NORMAL); | ||
440 | } | ||
441 | }else{ | ||
442 | tty_insert_flip_char(tty, data, TTY_NORMAL); | ||
443 | } | ||
444 | }else{ | ||
445 | /* there was a software buffer overrun | ||
446 | and nothing could be done about it!!! */ | ||
447 | } | ||
448 | } | ||
449 | tty_schedule_flip(tty); | ||
450 | /* end of service */ | ||
451 | base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS; | ||
452 | return IRQ_HANDLED; | ||
453 | } /* cy_rxerr_interrupt */ | ||
454 | |||
455 | static irqreturn_t | ||
456 | cd2401_modem_interrupt(int irq, void *dev_id) | ||
457 | { | 466 | { |
458 | struct cyclades_port *info; | 467 | struct cyclades_port *info; |
459 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; | 468 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; |
460 | int channel; | 469 | int channel; |
461 | int mdm_change; | 470 | int mdm_change; |
462 | int mdm_status; | 471 | int mdm_status; |
463 | 472 | ||
464 | 473 | /* determine the channel and change to that context */ | |
465 | /* determine the channel and change to that context */ | 474 | channel = (u_short) (base_addr[CyLICR] >> 2); |
466 | channel = (u_short ) (base_addr[CyLICR] >> 2); | 475 | info = &cy_port[channel]; |
467 | info = &cy_port[channel]; | 476 | info->last_active = jiffies; |
468 | info->last_active = jiffies; | 477 | |
469 | 478 | mdm_change = base_addr[CyMISR]; | |
470 | mdm_change = base_addr[CyMISR]; | 479 | mdm_status = base_addr[CyMSVR1]; |
471 | mdm_status = base_addr[CyMSVR1]; | 480 | |
472 | 481 | if (info->tty == 0) { /* nowhere to put the data, ignore it */ | |
473 | if(info->tty == 0){ /* nowhere to put the data, ignore it */ | 482 | ; |
474 | ; | 483 | } else { |
475 | }else{ | 484 | if ((mdm_change & CyDCD) |
476 | if((mdm_change & CyDCD) | 485 | && (info->flags & ASYNC_CHECK_CD)) { |
477 | && (info->flags & ASYNC_CHECK_CD)){ | 486 | if (mdm_status & CyDCD) { |
478 | if(mdm_status & CyDCD){ | ||
479 | /* CP('!'); */ | 487 | /* CP('!'); */ |
480 | cy_sched_event(info, Cy_EVENT_OPEN_WAKEUP); | 488 | cy_sched_event(info, Cy_EVENT_OPEN_WAKEUP); |
481 | } else { | 489 | } else { |
482 | /* CP('@'); */ | 490 | /* CP('@'); */ |
483 | cy_sched_event(info, Cy_EVENT_HANGUP); | 491 | cy_sched_event(info, Cy_EVENT_HANGUP); |
484 | } | 492 | } |
485 | } | ||
486 | if((mdm_change & CyCTS) | ||
487 | && (info->flags & ASYNC_CTS_FLOW)){ | ||
488 | if(info->tty->stopped){ | ||
489 | if(mdm_status & CyCTS){ | ||
490 | /* !!! cy_start isn't used because... */ | ||
491 | info->tty->stopped = 0; | ||
492 | base_addr[CyIER] |= CyTxMpty; | ||
493 | cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); | ||
494 | } | 493 | } |
495 | }else{ | 494 | if ((mdm_change & CyCTS) |
496 | if(!(mdm_status & CyCTS)){ | 495 | && (info->flags & ASYNC_CTS_FLOW)) { |
497 | /* !!! cy_stop isn't used because... */ | 496 | if (info->tty->stopped) { |
498 | info->tty->stopped = 1; | 497 | if (mdm_status & CyCTS) { |
499 | base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy); | 498 | /* !!! cy_start isn't used because... */ |
499 | info->tty->stopped = 0; | ||
500 | base_addr[CyIER] |= CyTxMpty; | ||
501 | cy_sched_event(info, | ||
502 | Cy_EVENT_WRITE_WAKEUP); | ||
503 | } | ||
504 | } else { | ||
505 | if (!(mdm_status & CyCTS)) { | ||
506 | /* !!! cy_stop isn't used because... */ | ||
507 | info->tty->stopped = 1; | ||
508 | base_addr[CyIER] &= | ||
509 | ~(CyTxMpty | CyTxRdy); | ||
510 | } | ||
511 | } | ||
512 | } | ||
513 | if (mdm_status & CyDSR) { | ||
500 | } | 514 | } |
501 | } | ||
502 | } | ||
503 | if(mdm_status & CyDSR){ | ||
504 | } | 515 | } |
505 | } | 516 | base_addr[CyMEOIR] = 0; |
506 | base_addr[CyMEOIR] = 0; | 517 | return IRQ_HANDLED; |
507 | return IRQ_HANDLED; | 518 | } /* cy_modem_interrupt */ |
508 | } /* cy_modem_interrupt */ | ||
509 | 519 | ||
510 | static irqreturn_t | 520 | static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id) |
511 | cd2401_tx_interrupt(int irq, void *dev_id) | ||
512 | { | 521 | { |
513 | struct cyclades_port *info; | 522 | struct cyclades_port *info; |
514 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; | 523 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; |
515 | int channel; | 524 | int channel; |
516 | int char_count, saved_cnt; | 525 | int char_count, saved_cnt; |
517 | int outch; | 526 | int outch; |
518 | 527 | ||
519 | /* determine the channel and change to that context */ | 528 | /* determine the channel and change to that context */ |
520 | channel = (u_short ) (base_addr[CyLICR] >> 2); | 529 | channel = (u_short) (base_addr[CyLICR] >> 2); |
521 | 530 | ||
522 | #ifdef CONFIG_REMOTE_DEBUG | 531 | #ifdef CONFIG_REMOTE_DEBUG |
523 | if (channel == DEBUG_PORT) { | 532 | if (channel == DEBUG_PORT) { |
524 | panic ("TxInt on debug port!!!"); | 533 | panic("TxInt on debug port!!!"); |
525 | } | 534 | } |
526 | #endif | 535 | #endif |
527 | 536 | ||
528 | info = &cy_port[channel]; | 537 | info = &cy_port[channel]; |
529 | 538 | ||
530 | /* validate the port number (as configured and open) */ | 539 | /* validate the port number (as configured and open) */ |
531 | if( (channel < 0) || (NR_PORTS <= channel) ){ | 540 | if ((channel < 0) || (NR_PORTS <= channel)) { |
532 | base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy); | 541 | base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); |
533 | base_addr[CyTEOIR] = CyNOTRANS; | 542 | base_addr[CyTEOIR] = CyNOTRANS; |
534 | return IRQ_HANDLED; | 543 | return IRQ_HANDLED; |
535 | } | 544 | } |
536 | info->last_active = jiffies; | 545 | info->last_active = jiffies; |
537 | if(info->tty == 0){ | 546 | if (info->tty == 0) { |
538 | base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy); | 547 | base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); |
539 | if (info->xmit_cnt < WAKEUP_CHARS) { | 548 | if (info->xmit_cnt < WAKEUP_CHARS) { |
540 | cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); | 549 | cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); |
541 | } | 550 | } |
542 | base_addr[CyTEOIR] = CyNOTRANS; | 551 | base_addr[CyTEOIR] = CyNOTRANS; |
543 | return IRQ_HANDLED; | 552 | return IRQ_HANDLED; |
544 | } | 553 | } |
545 | 554 | ||
546 | /* load the on-chip space available for outbound data */ | 555 | /* load the on-chip space available for outbound data */ |
547 | saved_cnt = char_count = base_addr[CyTFTC]; | 556 | saved_cnt = char_count = base_addr[CyTFTC]; |
548 | 557 | ||
549 | if(info->x_char) { /* send special char */ | 558 | if (info->x_char) { /* send special char */ |
550 | outch = info->x_char; | 559 | outch = info->x_char; |
551 | base_addr[CyTDR] = outch; | ||
552 | char_count--; | ||
553 | info->x_char = 0; | ||
554 | } | ||
555 | |||
556 | if (info->x_break){ | ||
557 | /* The Cirrus chip requires the "Embedded Transmit | ||
558 | Commands" of start break, delay, and end break | ||
559 | sequences to be sent. The duration of the | ||
560 | break is given in TICs, which runs at HZ | ||
561 | (typically 100) and the PPR runs at 200 Hz, | ||
562 | so the delay is duration * 200/HZ, and thus a | ||
563 | break can run from 1/100 sec to about 5/4 sec. | ||
564 | Need to check these values - RGH 141095. | ||
565 | */ | ||
566 | base_addr[CyTDR] = 0; /* start break */ | ||
567 | base_addr[CyTDR] = 0x81; | ||
568 | base_addr[CyTDR] = 0; /* delay a bit */ | ||
569 | base_addr[CyTDR] = 0x82; | ||
570 | base_addr[CyTDR] = info->x_break*200/HZ; | ||
571 | base_addr[CyTDR] = 0; /* terminate break */ | ||
572 | base_addr[CyTDR] = 0x83; | ||
573 | char_count -= 7; | ||
574 | info->x_break = 0; | ||
575 | } | ||
576 | |||
577 | while (char_count > 0){ | ||
578 | if (!info->xmit_cnt){ | ||
579 | base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy); | ||
580 | break; | ||
581 | } | ||
582 | if (info->xmit_buf == 0){ | ||
583 | base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy); | ||
584 | break; | ||
585 | } | ||
586 | if (info->tty->stopped || info->tty->hw_stopped){ | ||
587 | base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy); | ||
588 | break; | ||
589 | } | ||
590 | /* Because the Embedded Transmit Commands have been | ||
591 | enabled, we must check to see if the escape | ||
592 | character, NULL, is being sent. If it is, we | ||
593 | must ensure that there is room for it to be | ||
594 | doubled in the output stream. Therefore we | ||
595 | no longer advance the pointer when the character | ||
596 | is fetched, but rather wait until after the check | ||
597 | for a NULL output character. (This is necessary | ||
598 | because there may not be room for the two chars | ||
599 | needed to send a NULL. | ||
600 | */ | ||
601 | outch = info->xmit_buf[info->xmit_tail]; | ||
602 | if( outch ){ | ||
603 | info->xmit_cnt--; | ||
604 | info->xmit_tail = (info->xmit_tail + 1) | ||
605 | & (PAGE_SIZE - 1); | ||
606 | base_addr[CyTDR] = outch; | ||
607 | char_count--; | ||
608 | }else{ | ||
609 | if(char_count > 1){ | ||
610 | info->xmit_cnt--; | ||
611 | info->xmit_tail = (info->xmit_tail + 1) | ||
612 | & (PAGE_SIZE - 1); | ||
613 | base_addr[CyTDR] = outch; | 560 | base_addr[CyTDR] = outch; |
614 | base_addr[CyTDR] = 0; | ||
615 | char_count--; | 561 | char_count--; |
616 | char_count--; | 562 | info->x_char = 0; |
617 | }else{ | ||
618 | break; | ||
619 | } | ||
620 | } | 563 | } |
621 | } | ||
622 | 564 | ||
623 | if (info->xmit_cnt < WAKEUP_CHARS) { | 565 | if (info->x_break) { |
624 | cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); | 566 | /* The Cirrus chip requires the "Embedded Transmit |
625 | } | 567 | Commands" of start break, delay, and end break |
626 | base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS; | 568 | sequences to be sent. The duration of the |
627 | return IRQ_HANDLED; | 569 | break is given in TICs, which runs at HZ |
628 | } /* cy_tx_interrupt */ | 570 | (typically 100) and the PPR runs at 200 Hz, |
571 | so the delay is duration * 200/HZ, and thus a | ||
572 | break can run from 1/100 sec to about 5/4 sec. | ||
573 | Need to check these values - RGH 141095. | ||
574 | */ | ||
575 | base_addr[CyTDR] = 0; /* start break */ | ||
576 | base_addr[CyTDR] = 0x81; | ||
577 | base_addr[CyTDR] = 0; /* delay a bit */ | ||
578 | base_addr[CyTDR] = 0x82; | ||
579 | base_addr[CyTDR] = info->x_break * 200 / HZ; | ||
580 | base_addr[CyTDR] = 0; /* terminate break */ | ||
581 | base_addr[CyTDR] = 0x83; | ||
582 | char_count -= 7; | ||
583 | info->x_break = 0; | ||
584 | } | ||
585 | |||
586 | while (char_count > 0) { | ||
587 | if (!info->xmit_cnt) { | ||
588 | base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); | ||
589 | break; | ||
590 | } | ||
591 | if (info->xmit_buf == 0) { | ||
592 | base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); | ||
593 | break; | ||
594 | } | ||
595 | if (info->tty->stopped || info->tty->hw_stopped) { | ||
596 | base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); | ||
597 | break; | ||
598 | } | ||
599 | /* Because the Embedded Transmit Commands have been | ||
600 | enabled, we must check to see if the escape | ||
601 | character, NULL, is being sent. If it is, we | ||
602 | must ensure that there is room for it to be | ||
603 | doubled in the output stream. Therefore we | ||
604 | no longer advance the pointer when the character | ||
605 | is fetched, but rather wait until after the check | ||
606 | for a NULL output character. (This is necessary | ||
607 | because there may not be room for the two chars | ||
608 | needed to send a NULL. | ||
609 | */ | ||
610 | outch = info->xmit_buf[info->xmit_tail]; | ||
611 | if (outch) { | ||
612 | info->xmit_cnt--; | ||
613 | info->xmit_tail = (info->xmit_tail + 1) | ||
614 | & (PAGE_SIZE - 1); | ||
615 | base_addr[CyTDR] = outch; | ||
616 | char_count--; | ||
617 | } else { | ||
618 | if (char_count > 1) { | ||
619 | info->xmit_cnt--; | ||
620 | info->xmit_tail = (info->xmit_tail + 1) | ||
621 | & (PAGE_SIZE - 1); | ||
622 | base_addr[CyTDR] = outch; | ||
623 | base_addr[CyTDR] = 0; | ||
624 | char_count--; | ||
625 | char_count--; | ||
626 | } else { | ||
627 | break; | ||
628 | } | ||
629 | } | ||
630 | } | ||
631 | |||
632 | if (info->xmit_cnt < WAKEUP_CHARS) { | ||
633 | cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); | ||
634 | } | ||
635 | base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS; | ||
636 | return IRQ_HANDLED; | ||
637 | } /* cy_tx_interrupt */ | ||
629 | 638 | ||
630 | static irqreturn_t | 639 | static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id) |
631 | cd2401_rx_interrupt(int irq, void *dev_id) | ||
632 | { | 640 | { |
633 | struct tty_struct *tty; | 641 | struct tty_struct *tty; |
634 | struct cyclades_port *info; | 642 | struct cyclades_port *info; |
635 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; | 643 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; |
636 | int channel; | 644 | int channel; |
637 | char data; | 645 | char data; |
638 | int char_count; | 646 | int char_count; |
639 | int save_cnt; | 647 | int save_cnt; |
640 | int len; | 648 | int len; |
641 | 649 | ||
642 | /* determine the channel and change to that context */ | 650 | /* determine the channel and change to that context */ |
643 | channel = (u_short ) (base_addr[CyLICR] >> 2); | 651 | channel = (u_short) (base_addr[CyLICR] >> 2); |
644 | info = &cy_port[channel]; | 652 | info = &cy_port[channel]; |
645 | info->last_active = jiffies; | 653 | info->last_active = jiffies; |
646 | save_cnt = char_count = base_addr[CyRFOC]; | 654 | save_cnt = char_count = base_addr[CyRFOC]; |
647 | 655 | ||
648 | #ifdef CONFIG_REMOTE_DEBUG | 656 | #ifdef CONFIG_REMOTE_DEBUG |
649 | if (channel == DEBUG_PORT) { | 657 | if (channel == DEBUG_PORT) { |
650 | while (char_count--) { | 658 | while (char_count--) { |
651 | data = base_addr[CyRDR]; | 659 | data = base_addr[CyRDR]; |
652 | queueDebugChar(data); | 660 | queueDebugChar(data); |
653 | } | 661 | } |
654 | } | 662 | } else |
655 | else | ||
656 | #endif | 663 | #endif |
657 | /* if there is nowhere to put the data, discard it */ | 664 | /* if there is nowhere to put the data, discard it */ |
658 | if(info->tty == 0){ | 665 | if (info->tty == 0) { |
659 | while(char_count--){ | 666 | while (char_count--) { |
660 | data = base_addr[CyRDR]; | 667 | data = base_addr[CyRDR]; |
661 | } | 668 | } |
662 | }else{ /* there is an open port for this data */ | 669 | } else { /* there is an open port for this data */ |
663 | tty = info->tty; | 670 | tty = info->tty; |
664 | /* load # characters available from the chip */ | 671 | /* load # characters available from the chip */ |
665 | 672 | ||
666 | #ifdef CYCLOM_ENABLE_MONITORING | 673 | #ifdef CYCLOM_ENABLE_MONITORING |
667 | ++info->mon.int_count; | 674 | ++info->mon.int_count; |
668 | info->mon.char_count += char_count; | 675 | info->mon.char_count += char_count; |
669 | if (char_count > info->mon.char_max) | 676 | if (char_count > info->mon.char_max) |
670 | info->mon.char_max = char_count; | 677 | info->mon.char_max = char_count; |
671 | info->mon.char_last = char_count; | 678 | info->mon.char_last = char_count; |
672 | #endif | 679 | #endif |
673 | len = tty_buffer_request_room(tty, char_count); | 680 | len = tty_buffer_request_room(tty, char_count); |
674 | while(len--){ | 681 | while (len--) { |
675 | data = base_addr[CyRDR]; | 682 | data = base_addr[CyRDR]; |
676 | tty_insert_flip_char(tty, data, TTY_NORMAL); | 683 | tty_insert_flip_char(tty, data, TTY_NORMAL); |
677 | #ifdef CYCLOM_16Y_HACK | 684 | #ifdef CYCLOM_16Y_HACK |
678 | udelay(10L); | 685 | udelay(10L); |
679 | #endif | 686 | #endif |
680 | } | 687 | } |
681 | tty_schedule_flip(tty); | 688 | tty_schedule_flip(tty); |
682 | } | 689 | } |
683 | /* end of service */ | 690 | /* end of service */ |
684 | base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS; | 691 | base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS; |
685 | return IRQ_HANDLED; | 692 | return IRQ_HANDLED; |
686 | } /* cy_rx_interrupt */ | 693 | } /* cy_rx_interrupt */ |
687 | 694 | ||
688 | /* | 695 | /* |
689 | * This routine is used to handle the "bottom half" processing for the | 696 | * This routine is used to handle the "bottom half" processing for the |
@@ -705,192 +712,188 @@ cd2401_rx_interrupt(int irq, void *dev_id) | |||
705 | * structure) to the bottom half of the driver. Previous kernels | 712 | * structure) to the bottom half of the driver. Previous kernels |
706 | * had to poll every port to see if that port needed servicing. | 713 | * had to poll every port to see if that port needed servicing. |
707 | */ | 714 | */ |
708 | static void | 715 | static void do_softint(struct work_struct *ugly_api) |
709 | do_softint(struct work_struct *ugly_api) | ||
710 | { | 716 | { |
711 | struct cyclades_port *info = container_of(ugly_api, struct cyclades_port, tqueue); | 717 | struct cyclades_port *info = |
712 | struct tty_struct *tty; | 718 | container_of(ugly_api, struct cyclades_port, tqueue); |
713 | 719 | struct tty_struct *tty; | |
714 | tty = info->tty; | ||
715 | if (!tty) | ||
716 | return; | ||
717 | 720 | ||
718 | if (test_and_clear_bit(Cy_EVENT_HANGUP, &info->event)) { | 721 | tty = info->tty; |
719 | tty_hangup(info->tty); | 722 | if (!tty) |
720 | wake_up_interruptible(&info->open_wait); | 723 | return; |
721 | info->flags &= ~ASYNC_NORMAL_ACTIVE; | ||
722 | } | ||
723 | if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) { | ||
724 | wake_up_interruptible(&info->open_wait); | ||
725 | } | ||
726 | if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) { | ||
727 | tty_wakeup(tty); | ||
728 | } | ||
729 | } /* do_softint */ | ||
730 | 724 | ||
725 | if (test_and_clear_bit(Cy_EVENT_HANGUP, &info->event)) { | ||
726 | tty_hangup(info->tty); | ||
727 | wake_up_interruptible(&info->open_wait); | ||
728 | info->flags &= ~ASYNC_NORMAL_ACTIVE; | ||
729 | } | ||
730 | if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) { | ||
731 | wake_up_interruptible(&info->open_wait); | ||
732 | } | ||
733 | if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) { | ||
734 | tty_wakeup(tty); | ||
735 | } | ||
736 | } /* do_softint */ | ||
731 | 737 | ||
732 | /* This is called whenever a port becomes active; | 738 | /* This is called whenever a port becomes active; |
733 | interrupts are enabled and DTR & RTS are turned on. | 739 | interrupts are enabled and DTR & RTS are turned on. |
734 | */ | 740 | */ |
735 | static int | 741 | static int startup(struct cyclades_port *info) |
736 | startup(struct cyclades_port * info) | ||
737 | { | 742 | { |
738 | unsigned long flags; | 743 | unsigned long flags; |
739 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; | 744 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; |
740 | int channel; | 745 | int channel; |
741 | 746 | ||
742 | if (info->flags & ASYNC_INITIALIZED){ | 747 | if (info->flags & ASYNC_INITIALIZED) { |
743 | return 0; | 748 | return 0; |
744 | } | 749 | } |
745 | 750 | ||
746 | if (!info->type){ | 751 | if (!info->type) { |
747 | if (info->tty){ | 752 | if (info->tty) { |
748 | set_bit(TTY_IO_ERROR, &info->tty->flags); | 753 | set_bit(TTY_IO_ERROR, &info->tty->flags); |
754 | } | ||
755 | return 0; | ||
749 | } | 756 | } |
750 | return 0; | 757 | if (!info->xmit_buf) { |
751 | } | 758 | info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL); |
752 | if (!info->xmit_buf){ | 759 | if (!info->xmit_buf) { |
753 | info->xmit_buf = (unsigned char *) get_zeroed_page (GFP_KERNEL); | 760 | return -ENOMEM; |
754 | if (!info->xmit_buf){ | 761 | } |
755 | return -ENOMEM; | ||
756 | } | 762 | } |
757 | } | ||
758 | 763 | ||
759 | config_setup(info); | 764 | config_setup(info); |
760 | 765 | ||
761 | channel = info->line; | 766 | channel = info->line; |
762 | 767 | ||
763 | #ifdef SERIAL_DEBUG_OPEN | 768 | #ifdef SERIAL_DEBUG_OPEN |
764 | printk("startup channel %d\n", channel); | 769 | printk("startup channel %d\n", channel); |
765 | #endif | 770 | #endif |
766 | 771 | ||
767 | local_irq_save(flags); | 772 | local_irq_save(flags); |
768 | base_addr[CyCAR] = (u_char)channel; | 773 | base_addr[CyCAR] = (u_char) channel; |
769 | write_cy_cmd(base_addr,CyENB_RCVR|CyENB_XMTR); | 774 | write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR); |
770 | 775 | ||
771 | base_addr[CyCAR] = (u_char)channel; /* !!! Is this needed? */ | 776 | base_addr[CyCAR] = (u_char) channel; /* !!! Is this needed? */ |
772 | base_addr[CyMSVR1] = CyRTS; | 777 | base_addr[CyMSVR1] = CyRTS; |
773 | /* CP('S');CP('1'); */ | 778 | /* CP('S');CP('1'); */ |
774 | base_addr[CyMSVR2] = CyDTR; | 779 | base_addr[CyMSVR2] = CyDTR; |
775 | 780 | ||
776 | #ifdef SERIAL_DEBUG_DTR | 781 | #ifdef SERIAL_DEBUG_DTR |
777 | printk("cyc: %d: raising DTR\n", __LINE__); | 782 | printk("cyc: %d: raising DTR\n", __LINE__); |
778 | printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]); | 783 | printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], |
784 | base_addr[CyMSVR2]); | ||
779 | #endif | 785 | #endif |
780 | 786 | ||
781 | base_addr[CyIER] |= CyRxData; | 787 | base_addr[CyIER] |= CyRxData; |
782 | info->flags |= ASYNC_INITIALIZED; | 788 | info->flags |= ASYNC_INITIALIZED; |
783 | 789 | ||
784 | if (info->tty){ | 790 | if (info->tty) { |
785 | clear_bit(TTY_IO_ERROR, &info->tty->flags); | 791 | clear_bit(TTY_IO_ERROR, &info->tty->flags); |
786 | } | 792 | } |
787 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | 793 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; |
788 | 794 | ||
789 | local_irq_restore(flags); | 795 | local_irq_restore(flags); |
790 | 796 | ||
791 | #ifdef SERIAL_DEBUG_OPEN | 797 | #ifdef SERIAL_DEBUG_OPEN |
792 | printk(" done\n"); | 798 | printk(" done\n"); |
793 | #endif | 799 | #endif |
794 | return 0; | 800 | return 0; |
795 | } /* startup */ | 801 | } /* startup */ |
796 | 802 | ||
797 | void | 803 | void start_xmit(struct cyclades_port *info) |
798 | start_xmit( struct cyclades_port *info ) | ||
799 | { | 804 | { |
800 | unsigned long flags; | 805 | unsigned long flags; |
801 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; | 806 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; |
802 | int channel; | 807 | int channel; |
803 | 808 | ||
804 | channel = info->line; | 809 | channel = info->line; |
805 | local_irq_save(flags); | 810 | local_irq_save(flags); |
806 | base_addr[CyCAR] = channel; | 811 | base_addr[CyCAR] = channel; |
807 | base_addr[CyIER] |= CyTxMpty; | 812 | base_addr[CyIER] |= CyTxMpty; |
808 | local_irq_restore(flags); | 813 | local_irq_restore(flags); |
809 | } /* start_xmit */ | 814 | } /* start_xmit */ |
810 | 815 | ||
811 | /* | 816 | /* |
812 | * This routine shuts down a serial port; interrupts are disabled, | 817 | * This routine shuts down a serial port; interrupts are disabled, |
813 | * and DTR is dropped if the hangup on close termio flag is on. | 818 | * and DTR is dropped if the hangup on close termio flag is on. |
814 | */ | 819 | */ |
815 | static void | 820 | static void shutdown(struct cyclades_port *info) |
816 | shutdown(struct cyclades_port * info) | ||
817 | { | 821 | { |
818 | unsigned long flags; | 822 | unsigned long flags; |
819 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; | 823 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; |
820 | int channel; | 824 | int channel; |
821 | 825 | ||
822 | if (!(info->flags & ASYNC_INITIALIZED)){ | 826 | if (!(info->flags & ASYNC_INITIALIZED)) { |
823 | /* CP('$'); */ | 827 | /* CP('$'); */ |
824 | return; | 828 | return; |
825 | } | 829 | } |
826 | 830 | ||
827 | channel = info->line; | 831 | channel = info->line; |
828 | 832 | ||
829 | #ifdef SERIAL_DEBUG_OPEN | 833 | #ifdef SERIAL_DEBUG_OPEN |
830 | printk("shutdown channel %d\n", channel); | 834 | printk("shutdown channel %d\n", channel); |
831 | #endif | 835 | #endif |
832 | 836 | ||
833 | /* !!! REALLY MUST WAIT FOR LAST CHARACTER TO BE | 837 | /* !!! REALLY MUST WAIT FOR LAST CHARACTER TO BE |
834 | SENT BEFORE DROPPING THE LINE !!! (Perhaps | 838 | SENT BEFORE DROPPING THE LINE !!! (Perhaps |
835 | set some flag that is read when XMTY happens.) | 839 | set some flag that is read when XMTY happens.) |
836 | Other choices are to delay some fixed interval | 840 | Other choices are to delay some fixed interval |
837 | or schedule some later processing. | 841 | or schedule some later processing. |
838 | */ | 842 | */ |
839 | local_irq_save(flags); | 843 | local_irq_save(flags); |
840 | if (info->xmit_buf){ | 844 | if (info->xmit_buf) { |
841 | free_page((unsigned long) info->xmit_buf); | 845 | free_page((unsigned long)info->xmit_buf); |
842 | info->xmit_buf = NULL; | 846 | info->xmit_buf = NULL; |
843 | } | 847 | } |
844 | 848 | ||
845 | base_addr[CyCAR] = (u_char)channel; | 849 | base_addr[CyCAR] = (u_char) channel; |
846 | if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { | 850 | if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { |
847 | base_addr[CyMSVR1] = 0; | 851 | base_addr[CyMSVR1] = 0; |
848 | /* CP('C');CP('1'); */ | 852 | /* CP('C');CP('1'); */ |
849 | base_addr[CyMSVR2] = 0; | 853 | base_addr[CyMSVR2] = 0; |
850 | #ifdef SERIAL_DEBUG_DTR | 854 | #ifdef SERIAL_DEBUG_DTR |
851 | printk("cyc: %d: dropping DTR\n", __LINE__); | 855 | printk("cyc: %d: dropping DTR\n", __LINE__); |
852 | printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]); | 856 | printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], |
857 | base_addr[CyMSVR2]); | ||
853 | #endif | 858 | #endif |
854 | } | 859 | } |
855 | write_cy_cmd(base_addr,CyDIS_RCVR); | 860 | write_cy_cmd(base_addr, CyDIS_RCVR); |
856 | /* it may be appropriate to clear _XMIT at | 861 | /* it may be appropriate to clear _XMIT at |
857 | some later date (after testing)!!! */ | 862 | some later date (after testing)!!! */ |
858 | 863 | ||
859 | if (info->tty){ | 864 | if (info->tty) { |
860 | set_bit(TTY_IO_ERROR, &info->tty->flags); | 865 | set_bit(TTY_IO_ERROR, &info->tty->flags); |
861 | } | 866 | } |
862 | info->flags &= ~ASYNC_INITIALIZED; | 867 | info->flags &= ~ASYNC_INITIALIZED; |
863 | local_irq_restore(flags); | 868 | local_irq_restore(flags); |
864 | 869 | ||
865 | #ifdef SERIAL_DEBUG_OPEN | 870 | #ifdef SERIAL_DEBUG_OPEN |
866 | printk(" done\n"); | 871 | printk(" done\n"); |
867 | #endif | 872 | #endif |
868 | return; | 873 | } /* shutdown */ |
869 | } /* shutdown */ | ||
870 | 874 | ||
871 | /* | 875 | /* |
872 | * This routine finds or computes the various line characteristics. | 876 | * This routine finds or computes the various line characteristics. |
873 | */ | 877 | */ |
874 | static void | 878 | static void config_setup(struct cyclades_port *info) |
875 | config_setup(struct cyclades_port * info) | ||
876 | { | 879 | { |
877 | unsigned long flags; | 880 | unsigned long flags; |
878 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; | 881 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; |
879 | int channel; | 882 | int channel; |
880 | unsigned cflag; | 883 | unsigned cflag; |
881 | int i; | 884 | int i; |
882 | unsigned char ti, need_init_chan = 0; | 885 | unsigned char ti, need_init_chan = 0; |
883 | 886 | ||
884 | if (!info->tty || !info->tty->termios){ | 887 | if (!info->tty || !info->tty->termios) { |
885 | return; | 888 | return; |
886 | } | 889 | } |
887 | if (info->line == -1){ | 890 | if (info->line == -1) { |
888 | return; | 891 | return; |
889 | } | 892 | } |
890 | cflag = info->tty->termios->c_cflag; | 893 | cflag = info->tty->termios->c_cflag; |
891 | 894 | ||
892 | /* baud rate */ | 895 | /* baud rate */ |
893 | i = cflag & CBAUD; | 896 | i = cflag & CBAUD; |
894 | #ifdef CBAUDEX | 897 | #ifdef CBAUDEX |
895 | /* Starting with kernel 1.1.65, there is direct support for | 898 | /* Starting with kernel 1.1.65, there is direct support for |
896 | higher baud rates. The following code supports those | 899 | higher baud rates. The following code supports those |
@@ -900,120 +903,123 @@ config_setup(struct cyclades_port * info) | |||
900 | is still the possibility of supporting 75 kbit/sec with | 903 | is still the possibility of supporting 75 kbit/sec with |
901 | the Cyclades board.) | 904 | the Cyclades board.) |
902 | */ | 905 | */ |
903 | if (i & CBAUDEX) { | 906 | if (i & CBAUDEX) { |
904 | if (i == B57600) | 907 | if (i == B57600) |
905 | i = 16; | 908 | i = 16; |
906 | else if(i == B115200) | 909 | else if (i == B115200) |
907 | i = 18; | 910 | i = 18; |
908 | #ifdef B78600 | 911 | #ifdef B78600 |
909 | else if(i == B78600) | 912 | else if (i == B78600) |
910 | i = 17; | 913 | i = 17; |
911 | #endif | 914 | #endif |
912 | else | 915 | else |
913 | info->tty->termios->c_cflag &= ~CBAUDEX; | 916 | info->tty->termios->c_cflag &= ~CBAUDEX; |
914 | } | 917 | } |
915 | #endif | 918 | #endif |
916 | if (i == 15) { | 919 | if (i == 15) { |
917 | if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) | 920 | if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) |
918 | i += 1; | 921 | i += 1; |
919 | if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) | 922 | if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) |
920 | i += 3; | 923 | i += 3; |
921 | } | 924 | } |
922 | /* Don't ever change the speed of the console port. It will | 925 | /* Don't ever change the speed of the console port. It will |
923 | * run at the speed specified in bootinfo, or at 19.2K */ | 926 | * run at the speed specified in bootinfo, or at 19.2K */ |
924 | /* Actually, it should run at whatever speed 166Bug was using */ | 927 | /* Actually, it should run at whatever speed 166Bug was using */ |
925 | /* Note info->timeout isn't used at present */ | 928 | /* Note info->timeout isn't used at present */ |
926 | if (info != serial_console_info) { | 929 | if (info != serial_console_info) { |
927 | info->tbpr = baud_bpr[i]; /* Tx BPR */ | 930 | info->tbpr = baud_bpr[i]; /* Tx BPR */ |
928 | info->tco = baud_co[i]; /* Tx CO */ | 931 | info->tco = baud_co[i]; /* Tx CO */ |
929 | info->rbpr = baud_bpr[i]; /* Rx BPR */ | 932 | info->rbpr = baud_bpr[i]; /* Rx BPR */ |
930 | info->rco = baud_co[i] >> 5; /* Rx CO */ | 933 | info->rco = baud_co[i] >> 5; /* Rx CO */ |
931 | if (baud_table[i] == 134) { | 934 | if (baud_table[i] == 134) { |
932 | info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2; | 935 | info->timeout = |
933 | /* get it right for 134.5 baud */ | 936 | (info->xmit_fifo_size * HZ * 30 / 269) + 2; |
934 | } else if (baud_table[i]) { | 937 | /* get it right for 134.5 baud */ |
935 | info->timeout = (info->xmit_fifo_size*HZ*15/baud_table[i]) + 2; | 938 | } else if (baud_table[i]) { |
936 | /* this needs to be propagated into the card info */ | 939 | info->timeout = |
940 | (info->xmit_fifo_size * HZ * 15 / baud_table[i]) + | ||
941 | 2; | ||
942 | /* this needs to be propagated into the card info */ | ||
943 | } else { | ||
944 | info->timeout = 0; | ||
945 | } | ||
946 | } | ||
947 | /* By tradition (is it a standard?) a baud rate of zero | ||
948 | implies the line should be/has been closed. A bit | ||
949 | later in this routine such a test is performed. */ | ||
950 | |||
951 | /* byte size and parity */ | ||
952 | info->cor7 = 0; | ||
953 | info->cor6 = 0; | ||
954 | info->cor5 = 0; | ||
955 | info->cor4 = (info->default_threshold ? info->default_threshold : baud_cor4[i]); /* receive threshold */ | ||
956 | /* Following two lines added 101295, RGH. */ | ||
957 | /* It is obviously wrong to access CyCORx, and not info->corx here, | ||
958 | * try and remember to fix it later! */ | ||
959 | channel = info->line; | ||
960 | base_addr[CyCAR] = (u_char) channel; | ||
961 | if (C_CLOCAL(info->tty)) { | ||
962 | if (base_addr[CyIER] & CyMdmCh) | ||
963 | base_addr[CyIER] &= ~CyMdmCh; /* without modem intr */ | ||
964 | /* ignore 1->0 modem transitions */ | ||
965 | if (base_addr[CyCOR4] & (CyDSR | CyCTS | CyDCD)) | ||
966 | base_addr[CyCOR4] &= ~(CyDSR | CyCTS | CyDCD); | ||
967 | /* ignore 0->1 modem transitions */ | ||
968 | if (base_addr[CyCOR5] & (CyDSR | CyCTS | CyDCD)) | ||
969 | base_addr[CyCOR5] &= ~(CyDSR | CyCTS | CyDCD); | ||
937 | } else { | 970 | } else { |
938 | info->timeout = 0; | 971 | if ((base_addr[CyIER] & CyMdmCh) != CyMdmCh) |
939 | } | 972 | base_addr[CyIER] |= CyMdmCh; /* with modem intr */ |
940 | } | 973 | /* act on 1->0 modem transitions */ |
941 | /* By tradition (is it a standard?) a baud rate of zero | 974 | if ((base_addr[CyCOR4] & (CyDSR | CyCTS | CyDCD)) != |
942 | implies the line should be/has been closed. A bit | 975 | (CyDSR | CyCTS | CyDCD)) |
943 | later in this routine such a test is performed. */ | 976 | base_addr[CyCOR4] |= CyDSR | CyCTS | CyDCD; |
944 | 977 | /* act on 0->1 modem transitions */ | |
945 | /* byte size and parity */ | 978 | if ((base_addr[CyCOR5] & (CyDSR | CyCTS | CyDCD)) != |
946 | info->cor7 = 0; | 979 | (CyDSR | CyCTS | CyDCD)) |
947 | info->cor6 = 0; | 980 | base_addr[CyCOR5] |= CyDSR | CyCTS | CyDCD; |
948 | info->cor5 = 0; | 981 | } |
949 | info->cor4 = (info->default_threshold | 982 | info->cor3 = (cflag & CSTOPB) ? Cy_2_STOP : Cy_1_STOP; |
950 | ? info->default_threshold | 983 | info->cor2 = CyETC; |
951 | : baud_cor4[i]); /* receive threshold */ | 984 | switch (cflag & CSIZE) { |
952 | /* Following two lines added 101295, RGH. */ | 985 | case CS5: |
953 | /* It is obviously wrong to access CyCORx, and not info->corx here, | 986 | info->cor1 = Cy_5_BITS; |
954 | * try and remember to fix it later! */ | 987 | break; |
955 | channel = info->line; | 988 | case CS6: |
956 | base_addr[CyCAR] = (u_char)channel; | 989 | info->cor1 = Cy_6_BITS; |
957 | if (C_CLOCAL(info->tty)) { | 990 | break; |
958 | if (base_addr[CyIER] & CyMdmCh) | 991 | case CS7: |
959 | base_addr[CyIER] &= ~CyMdmCh; /* without modem intr */ | 992 | info->cor1 = Cy_7_BITS; |
960 | /* ignore 1->0 modem transitions */ | 993 | break; |
961 | if (base_addr[CyCOR4] & (CyDSR|CyCTS|CyDCD)) | 994 | case CS8: |
962 | base_addr[CyCOR4] &= ~(CyDSR|CyCTS|CyDCD); | 995 | info->cor1 = Cy_8_BITS; |
963 | /* ignore 0->1 modem transitions */ | 996 | break; |
964 | if (base_addr[CyCOR5] & (CyDSR|CyCTS|CyDCD)) | 997 | } |
965 | base_addr[CyCOR5] &= ~(CyDSR|CyCTS|CyDCD); | 998 | if (cflag & PARENB) { |
966 | } else { | 999 | if (cflag & PARODD) { |
967 | if ((base_addr[CyIER] & CyMdmCh) != CyMdmCh) | 1000 | info->cor1 |= CyPARITY_O; |
968 | base_addr[CyIER] |= CyMdmCh; /* with modem intr */ | 1001 | } else { |
969 | /* act on 1->0 modem transitions */ | 1002 | info->cor1 |= CyPARITY_E; |
970 | if ((base_addr[CyCOR4] & (CyDSR|CyCTS|CyDCD)) != (CyDSR|CyCTS|CyDCD)) | 1003 | } |
971 | base_addr[CyCOR4] |= CyDSR|CyCTS|CyDCD; | 1004 | } else { |
972 | /* act on 0->1 modem transitions */ | 1005 | info->cor1 |= CyPARITY_NONE; |
973 | if ((base_addr[CyCOR5] & (CyDSR|CyCTS|CyDCD)) != (CyDSR|CyCTS|CyDCD)) | 1006 | } |
974 | base_addr[CyCOR5] |= CyDSR|CyCTS|CyDCD; | 1007 | |
975 | } | 1008 | /* CTS flow control flag */ |
976 | info->cor3 = (cflag & CSTOPB) ? Cy_2_STOP : Cy_1_STOP; | ||
977 | info->cor2 = CyETC; | ||
978 | switch(cflag & CSIZE){ | ||
979 | case CS5: | ||
980 | info->cor1 = Cy_5_BITS; | ||
981 | break; | ||
982 | case CS6: | ||
983 | info->cor1 = Cy_6_BITS; | ||
984 | break; | ||
985 | case CS7: | ||
986 | info->cor1 = Cy_7_BITS; | ||
987 | break; | ||
988 | case CS8: | ||
989 | info->cor1 = Cy_8_BITS; | ||
990 | break; | ||
991 | } | ||
992 | if (cflag & PARENB){ | ||
993 | if (cflag & PARODD){ | ||
994 | info->cor1 |= CyPARITY_O; | ||
995 | }else{ | ||
996 | info->cor1 |= CyPARITY_E; | ||
997 | } | ||
998 | }else{ | ||
999 | info->cor1 |= CyPARITY_NONE; | ||
1000 | } | ||
1001 | |||
1002 | /* CTS flow control flag */ | ||
1003 | #if 0 | 1009 | #if 0 |
1004 | /* Don't complcate matters for now! RGH 141095 */ | 1010 | /* Don't complcate matters for now! RGH 141095 */ |
1005 | if (cflag & CRTSCTS){ | 1011 | if (cflag & CRTSCTS) { |
1006 | info->flags |= ASYNC_CTS_FLOW; | 1012 | info->flags |= ASYNC_CTS_FLOW; |
1007 | info->cor2 |= CyCtsAE; | 1013 | info->cor2 |= CyCtsAE; |
1008 | }else{ | 1014 | } else { |
1009 | info->flags &= ~ASYNC_CTS_FLOW; | 1015 | info->flags &= ~ASYNC_CTS_FLOW; |
1010 | info->cor2 &= ~CyCtsAE; | 1016 | info->cor2 &= ~CyCtsAE; |
1011 | } | 1017 | } |
1012 | #endif | 1018 | #endif |
1013 | if (cflag & CLOCAL) | 1019 | if (cflag & CLOCAL) |
1014 | info->flags &= ~ASYNC_CHECK_CD; | 1020 | info->flags &= ~ASYNC_CHECK_CD; |
1015 | else | 1021 | else |
1016 | info->flags |= ASYNC_CHECK_CD; | 1022 | info->flags |= ASYNC_CHECK_CD; |
1017 | 1023 | ||
1018 | /*********************************************** | 1024 | /*********************************************** |
1019 | The hardware option, CyRtsAO, presents RTS when | 1025 | The hardware option, CyRtsAO, presents RTS when |
@@ -1025,149 +1031,146 @@ config_setup(struct cyclades_port * info) | |||
1025 | cable. Contact Marcio Saito for details. | 1031 | cable. Contact Marcio Saito for details. |
1026 | ***********************************************/ | 1032 | ***********************************************/ |
1027 | 1033 | ||
1028 | channel = info->line; | 1034 | channel = info->line; |
1029 | 1035 | ||
1030 | local_irq_save(flags); | 1036 | local_irq_save(flags); |
1031 | base_addr[CyCAR] = (u_char)channel; | 1037 | base_addr[CyCAR] = (u_char) channel; |
1032 | 1038 | ||
1033 | /* CyCMR set once only in mvme167_init_serial() */ | 1039 | /* CyCMR set once only in mvme167_init_serial() */ |
1034 | if (base_addr[CyLICR] != channel << 2) | 1040 | if (base_addr[CyLICR] != channel << 2) |
1035 | base_addr[CyLICR] = channel << 2; | 1041 | base_addr[CyLICR] = channel << 2; |
1036 | if (base_addr[CyLIVR] != 0x5c) | 1042 | if (base_addr[CyLIVR] != 0x5c) |
1037 | base_addr[CyLIVR] = 0x5c; | 1043 | base_addr[CyLIVR] = 0x5c; |
1038 | 1044 | ||
1039 | /* tx and rx baud rate */ | 1045 | /* tx and rx baud rate */ |
1040 | 1046 | ||
1041 | if (base_addr[CyCOR1] != info->cor1) | 1047 | if (base_addr[CyCOR1] != info->cor1) |
1042 | need_init_chan = 1; | 1048 | need_init_chan = 1; |
1043 | if (base_addr[CyTCOR] != info->tco) | 1049 | if (base_addr[CyTCOR] != info->tco) |
1044 | base_addr[CyTCOR] = info->tco; | 1050 | base_addr[CyTCOR] = info->tco; |
1045 | if (base_addr[CyTBPR] != info->tbpr) | 1051 | if (base_addr[CyTBPR] != info->tbpr) |
1046 | base_addr[CyTBPR] = info->tbpr; | 1052 | base_addr[CyTBPR] = info->tbpr; |
1047 | if (base_addr[CyRCOR] != info->rco) | 1053 | if (base_addr[CyRCOR] != info->rco) |
1048 | base_addr[CyRCOR] = info->rco; | 1054 | base_addr[CyRCOR] = info->rco; |
1049 | if (base_addr[CyRBPR] != info->rbpr) | 1055 | if (base_addr[CyRBPR] != info->rbpr) |
1050 | base_addr[CyRBPR] = info->rbpr; | 1056 | base_addr[CyRBPR] = info->rbpr; |
1051 | 1057 | ||
1052 | /* set line characteristics according configuration */ | 1058 | /* set line characteristics according configuration */ |
1053 | 1059 | ||
1054 | if (base_addr[CySCHR1] != START_CHAR(info->tty)) | 1060 | if (base_addr[CySCHR1] != START_CHAR(info->tty)) |
1055 | base_addr[CySCHR1] = START_CHAR(info->tty); | 1061 | base_addr[CySCHR1] = START_CHAR(info->tty); |
1056 | if (base_addr[CySCHR2] != STOP_CHAR(info->tty)) | 1062 | if (base_addr[CySCHR2] != STOP_CHAR(info->tty)) |
1057 | base_addr[CySCHR2] = STOP_CHAR(info->tty); | 1063 | base_addr[CySCHR2] = STOP_CHAR(info->tty); |
1058 | if (base_addr[CySCRL] != START_CHAR(info->tty)) | 1064 | if (base_addr[CySCRL] != START_CHAR(info->tty)) |
1059 | base_addr[CySCRL] = START_CHAR(info->tty); | 1065 | base_addr[CySCRL] = START_CHAR(info->tty); |
1060 | if (base_addr[CySCRH] != START_CHAR(info->tty)) | 1066 | if (base_addr[CySCRH] != START_CHAR(info->tty)) |
1061 | base_addr[CySCRH] = START_CHAR(info->tty); | 1067 | base_addr[CySCRH] = START_CHAR(info->tty); |
1062 | if (base_addr[CyCOR1] != info->cor1) | 1068 | if (base_addr[CyCOR1] != info->cor1) |
1063 | base_addr[CyCOR1] = info->cor1; | 1069 | base_addr[CyCOR1] = info->cor1; |
1064 | if (base_addr[CyCOR2] != info->cor2) | 1070 | if (base_addr[CyCOR2] != info->cor2) |
1065 | base_addr[CyCOR2] = info->cor2; | 1071 | base_addr[CyCOR2] = info->cor2; |
1066 | if (base_addr[CyCOR3] != info->cor3) | 1072 | if (base_addr[CyCOR3] != info->cor3) |
1067 | base_addr[CyCOR3] = info->cor3; | 1073 | base_addr[CyCOR3] = info->cor3; |
1068 | if (base_addr[CyCOR4] != info->cor4) | 1074 | if (base_addr[CyCOR4] != info->cor4) |
1069 | base_addr[CyCOR4] = info->cor4; | 1075 | base_addr[CyCOR4] = info->cor4; |
1070 | if (base_addr[CyCOR5] != info->cor5) | 1076 | if (base_addr[CyCOR5] != info->cor5) |
1071 | base_addr[CyCOR5] = info->cor5; | 1077 | base_addr[CyCOR5] = info->cor5; |
1072 | if (base_addr[CyCOR6] != info->cor6) | 1078 | if (base_addr[CyCOR6] != info->cor6) |
1073 | base_addr[CyCOR6] = info->cor6; | 1079 | base_addr[CyCOR6] = info->cor6; |
1074 | if (base_addr[CyCOR7] != info->cor7) | 1080 | if (base_addr[CyCOR7] != info->cor7) |
1075 | base_addr[CyCOR7] = info->cor7; | 1081 | base_addr[CyCOR7] = info->cor7; |
1076 | 1082 | ||
1077 | if (need_init_chan) | 1083 | if (need_init_chan) |
1078 | write_cy_cmd(base_addr,CyINIT_CHAN); | 1084 | write_cy_cmd(base_addr, CyINIT_CHAN); |
1079 | 1085 | ||
1080 | base_addr[CyCAR] = (u_char)channel; /* !!! Is this needed? */ | 1086 | base_addr[CyCAR] = (u_char) channel; /* !!! Is this needed? */ |
1081 | 1087 | ||
1082 | /* 2ms default rx timeout */ | 1088 | /* 2ms default rx timeout */ |
1083 | ti = info->default_timeout ? info->default_timeout : 0x02; | 1089 | ti = info->default_timeout ? info->default_timeout : 0x02; |
1084 | if (base_addr[CyRTPRL] != ti) | 1090 | if (base_addr[CyRTPRL] != ti) |
1085 | base_addr[CyRTPRL] = ti; | 1091 | base_addr[CyRTPRL] = ti; |
1086 | if (base_addr[CyRTPRH] != 0) | 1092 | if (base_addr[CyRTPRH] != 0) |
1087 | base_addr[CyRTPRH] = 0; | 1093 | base_addr[CyRTPRH] = 0; |
1088 | 1094 | ||
1089 | /* Set up RTS here also ????? RGH 141095 */ | 1095 | /* Set up RTS here also ????? RGH 141095 */ |
1090 | if(i == 0){ /* baud rate is zero, turn off line */ | 1096 | if (i == 0) { /* baud rate is zero, turn off line */ |
1091 | if ((base_addr[CyMSVR2] & CyDTR) == CyDTR) | 1097 | if ((base_addr[CyMSVR2] & CyDTR) == CyDTR) |
1092 | base_addr[CyMSVR2] = 0; | 1098 | base_addr[CyMSVR2] = 0; |
1093 | #ifdef SERIAL_DEBUG_DTR | 1099 | #ifdef SERIAL_DEBUG_DTR |
1094 | printk("cyc: %d: dropping DTR\n", __LINE__); | 1100 | printk("cyc: %d: dropping DTR\n", __LINE__); |
1095 | printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]); | 1101 | printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], |
1102 | base_addr[CyMSVR2]); | ||
1096 | #endif | 1103 | #endif |
1097 | }else{ | 1104 | } else { |
1098 | if ((base_addr[CyMSVR2] & CyDTR) != CyDTR) | 1105 | if ((base_addr[CyMSVR2] & CyDTR) != CyDTR) |
1099 | base_addr[CyMSVR2] = CyDTR; | 1106 | base_addr[CyMSVR2] = CyDTR; |
1100 | #ifdef SERIAL_DEBUG_DTR | 1107 | #ifdef SERIAL_DEBUG_DTR |
1101 | printk("cyc: %d: raising DTR\n", __LINE__); | 1108 | printk("cyc: %d: raising DTR\n", __LINE__); |
1102 | printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]); | 1109 | printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], |
1110 | base_addr[CyMSVR2]); | ||
1103 | #endif | 1111 | #endif |
1104 | } | 1112 | } |
1105 | 1113 | ||
1106 | if (info->tty){ | 1114 | if (info->tty) { |
1107 | clear_bit(TTY_IO_ERROR, &info->tty->flags); | 1115 | clear_bit(TTY_IO_ERROR, &info->tty->flags); |
1108 | } | 1116 | } |
1109 | 1117 | ||
1110 | local_irq_restore(flags); | 1118 | local_irq_restore(flags); |
1111 | |||
1112 | } /* config_setup */ | ||
1113 | 1119 | ||
1120 | } /* config_setup */ | ||
1114 | 1121 | ||
1115 | static void | 1122 | static void cy_put_char(struct tty_struct *tty, unsigned char ch) |
1116 | cy_put_char(struct tty_struct *tty, unsigned char ch) | ||
1117 | { | 1123 | { |
1118 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1124 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; |
1119 | unsigned long flags; | 1125 | unsigned long flags; |
1120 | 1126 | ||
1121 | #ifdef SERIAL_DEBUG_IO | 1127 | #ifdef SERIAL_DEBUG_IO |
1122 | printk("cy_put_char %s(0x%02x)\n", tty->name, ch); | 1128 | printk("cy_put_char %s(0x%02x)\n", tty->name, ch); |
1123 | #endif | 1129 | #endif |
1124 | 1130 | ||
1125 | if (serial_paranoia_check(info, tty->name, "cy_put_char")) | 1131 | if (serial_paranoia_check(info, tty->name, "cy_put_char")) |
1126 | return; | 1132 | return; |
1127 | 1133 | ||
1128 | if (!info->xmit_buf) | 1134 | if (!info->xmit_buf) |
1129 | return; | 1135 | return; |
1130 | 1136 | ||
1131 | local_irq_save(flags); | 1137 | local_irq_save(flags); |
1132 | if (info->xmit_cnt >= PAGE_SIZE - 1) { | 1138 | if (info->xmit_cnt >= PAGE_SIZE - 1) { |
1133 | local_irq_restore(flags); | 1139 | local_irq_restore(flags); |
1134 | return; | 1140 | return; |
1135 | } | 1141 | } |
1136 | 1142 | ||
1137 | info->xmit_buf[info->xmit_head++] = ch; | 1143 | info->xmit_buf[info->xmit_head++] = ch; |
1138 | info->xmit_head &= PAGE_SIZE - 1; | 1144 | info->xmit_head &= PAGE_SIZE - 1; |
1139 | info->xmit_cnt++; | 1145 | info->xmit_cnt++; |
1140 | local_irq_restore(flags); | 1146 | local_irq_restore(flags); |
1141 | } /* cy_put_char */ | 1147 | } /* cy_put_char */ |
1142 | |||
1143 | 1148 | ||
1144 | static void | 1149 | static void cy_flush_chars(struct tty_struct *tty) |
1145 | cy_flush_chars(struct tty_struct *tty) | ||
1146 | { | 1150 | { |
1147 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1151 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; |
1148 | unsigned long flags; | 1152 | unsigned long flags; |
1149 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; | 1153 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; |
1150 | int channel; | 1154 | int channel; |
1151 | 1155 | ||
1152 | #ifdef SERIAL_DEBUG_IO | 1156 | #ifdef SERIAL_DEBUG_IO |
1153 | printk("cy_flush_chars %s\n", tty->name); /* */ | 1157 | printk("cy_flush_chars %s\n", tty->name); /* */ |
1154 | #endif | 1158 | #endif |
1155 | 1159 | ||
1156 | if (serial_paranoia_check(info, tty->name, "cy_flush_chars")) | 1160 | if (serial_paranoia_check(info, tty->name, "cy_flush_chars")) |
1157 | return; | 1161 | return; |
1158 | 1162 | ||
1159 | if (info->xmit_cnt <= 0 || tty->stopped | 1163 | if (info->xmit_cnt <= 0 || tty->stopped |
1160 | || tty->hw_stopped || !info->xmit_buf) | 1164 | || tty->hw_stopped || !info->xmit_buf) |
1161 | return; | 1165 | return; |
1162 | 1166 | ||
1163 | channel = info->line; | 1167 | channel = info->line; |
1164 | 1168 | ||
1165 | local_irq_save(flags); | 1169 | local_irq_save(flags); |
1166 | base_addr[CyCAR] = channel; | 1170 | base_addr[CyCAR] = channel; |
1167 | base_addr[CyIER] |= CyTxMpty; | 1171 | base_addr[CyIER] |= CyTxMpty; |
1168 | local_irq_restore(flags); | 1172 | local_irq_restore(flags); |
1169 | } /* cy_flush_chars */ | 1173 | } /* cy_flush_chars */ |
1170 | |||
1171 | 1174 | ||
1172 | /* This routine gets called when tty_write has put something into | 1175 | /* This routine gets called when tty_write has put something into |
1173 | the write_queue. If the port is not already transmitting stuff, | 1176 | the write_queue. If the port is not already transmitting stuff, |
@@ -1175,650 +1178,616 @@ cy_flush_chars(struct tty_struct *tty) | |||
1175 | routine will then ensure that the characters are sent. If the | 1178 | routine will then ensure that the characters are sent. If the |
1176 | port is already active, there is no need to kick it. | 1179 | port is already active, there is no need to kick it. |
1177 | */ | 1180 | */ |
1178 | static int | 1181 | static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count) |
1179 | cy_write(struct tty_struct * tty, | ||
1180 | const unsigned char *buf, int count) | ||
1181 | { | 1182 | { |
1182 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1183 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; |
1183 | unsigned long flags; | 1184 | unsigned long flags; |
1184 | int c, total = 0; | 1185 | int c, total = 0; |
1185 | 1186 | ||
1186 | #ifdef SERIAL_DEBUG_IO | 1187 | #ifdef SERIAL_DEBUG_IO |
1187 | printk("cy_write %s\n", tty->name); /* */ | 1188 | printk("cy_write %s\n", tty->name); /* */ |
1188 | #endif | 1189 | #endif |
1189 | 1190 | ||
1190 | if (serial_paranoia_check(info, tty->name, "cy_write")){ | 1191 | if (serial_paranoia_check(info, tty->name, "cy_write")) { |
1191 | return 0; | 1192 | return 0; |
1192 | } | 1193 | } |
1193 | |||
1194 | if (!info->xmit_buf){ | ||
1195 | return 0; | ||
1196 | } | ||
1197 | |||
1198 | while (1) { | ||
1199 | local_irq_save(flags); | ||
1200 | c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, | ||
1201 | SERIAL_XMIT_SIZE - info->xmit_head)); | ||
1202 | if (c <= 0) { | ||
1203 | local_irq_restore(flags); | ||
1204 | break; | ||
1205 | } | ||
1206 | |||
1207 | memcpy(info->xmit_buf + info->xmit_head, buf, c); | ||
1208 | info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); | ||
1209 | info->xmit_cnt += c; | ||
1210 | local_irq_restore(flags); | ||
1211 | |||
1212 | buf += c; | ||
1213 | count -= c; | ||
1214 | total += c; | ||
1215 | } | ||
1216 | |||
1217 | if (info->xmit_cnt | ||
1218 | && !tty->stopped | ||
1219 | && !tty->hw_stopped ) { | ||
1220 | start_xmit(info); | ||
1221 | } | ||
1222 | return total; | ||
1223 | } /* cy_write */ | ||
1224 | 1194 | ||
1195 | if (!info->xmit_buf) { | ||
1196 | return 0; | ||
1197 | } | ||
1225 | 1198 | ||
1226 | static int | 1199 | while (1) { |
1227 | cy_write_room(struct tty_struct *tty) | 1200 | local_irq_save(flags); |
1201 | c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, | ||
1202 | SERIAL_XMIT_SIZE - info->xmit_head)); | ||
1203 | if (c <= 0) { | ||
1204 | local_irq_restore(flags); | ||
1205 | break; | ||
1206 | } | ||
1207 | |||
1208 | memcpy(info->xmit_buf + info->xmit_head, buf, c); | ||
1209 | info->xmit_head = | ||
1210 | (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1); | ||
1211 | info->xmit_cnt += c; | ||
1212 | local_irq_restore(flags); | ||
1213 | |||
1214 | buf += c; | ||
1215 | count -= c; | ||
1216 | total += c; | ||
1217 | } | ||
1218 | |||
1219 | if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) { | ||
1220 | start_xmit(info); | ||
1221 | } | ||
1222 | return total; | ||
1223 | } /* cy_write */ | ||
1224 | |||
1225 | static int cy_write_room(struct tty_struct *tty) | ||
1228 | { | 1226 | { |
1229 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1227 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; |
1230 | int ret; | 1228 | int ret; |
1231 | 1229 | ||
1232 | #ifdef SERIAL_DEBUG_IO | 1230 | #ifdef SERIAL_DEBUG_IO |
1233 | printk("cy_write_room %s\n", tty->name); /* */ | 1231 | printk("cy_write_room %s\n", tty->name); /* */ |
1234 | #endif | 1232 | #endif |
1235 | 1233 | ||
1236 | if (serial_paranoia_check(info, tty->name, "cy_write_room")) | 1234 | if (serial_paranoia_check(info, tty->name, "cy_write_room")) |
1237 | return 0; | 1235 | return 0; |
1238 | ret = PAGE_SIZE - info->xmit_cnt - 1; | 1236 | ret = PAGE_SIZE - info->xmit_cnt - 1; |
1239 | if (ret < 0) | 1237 | if (ret < 0) |
1240 | ret = 0; | 1238 | ret = 0; |
1241 | return ret; | 1239 | return ret; |
1242 | } /* cy_write_room */ | 1240 | } /* cy_write_room */ |
1243 | |||
1244 | 1241 | ||
1245 | static int | 1242 | static int cy_chars_in_buffer(struct tty_struct *tty) |
1246 | cy_chars_in_buffer(struct tty_struct *tty) | ||
1247 | { | 1243 | { |
1248 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1244 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; |
1249 | 1245 | ||
1250 | #ifdef SERIAL_DEBUG_IO | 1246 | #ifdef SERIAL_DEBUG_IO |
1251 | printk("cy_chars_in_buffer %s %d\n", tty->name, info->xmit_cnt); /* */ | 1247 | printk("cy_chars_in_buffer %s %d\n", tty->name, info->xmit_cnt); /* */ |
1252 | #endif | 1248 | #endif |
1253 | 1249 | ||
1254 | if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer")) | 1250 | if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer")) |
1255 | return 0; | 1251 | return 0; |
1256 | |||
1257 | return info->xmit_cnt; | ||
1258 | } /* cy_chars_in_buffer */ | ||
1259 | 1252 | ||
1253 | return info->xmit_cnt; | ||
1254 | } /* cy_chars_in_buffer */ | ||
1260 | 1255 | ||
1261 | static void | 1256 | static void cy_flush_buffer(struct tty_struct *tty) |
1262 | cy_flush_buffer(struct tty_struct *tty) | ||
1263 | { | 1257 | { |
1264 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1258 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; |
1265 | unsigned long flags; | 1259 | unsigned long flags; |
1266 | 1260 | ||
1267 | #ifdef SERIAL_DEBUG_IO | 1261 | #ifdef SERIAL_DEBUG_IO |
1268 | printk("cy_flush_buffer %s\n", tty->name); /* */ | 1262 | printk("cy_flush_buffer %s\n", tty->name); /* */ |
1269 | #endif | 1263 | #endif |
1270 | 1264 | ||
1271 | if (serial_paranoia_check(info, tty->name, "cy_flush_buffer")) | 1265 | if (serial_paranoia_check(info, tty->name, "cy_flush_buffer")) |
1272 | return; | 1266 | return; |
1273 | local_irq_save(flags); | 1267 | local_irq_save(flags); |
1274 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | 1268 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; |
1275 | local_irq_restore(flags); | 1269 | local_irq_restore(flags); |
1276 | tty_wakeup(tty); | 1270 | tty_wakeup(tty); |
1277 | } /* cy_flush_buffer */ | 1271 | } /* cy_flush_buffer */ |
1278 | |||
1279 | 1272 | ||
1280 | /* This routine is called by the upper-layer tty layer to signal | 1273 | /* This routine is called by the upper-layer tty layer to signal |
1281 | that incoming characters should be throttled or that the | 1274 | that incoming characters should be throttled or that the |
1282 | throttle should be released. | 1275 | throttle should be released. |
1283 | */ | 1276 | */ |
1284 | static void | 1277 | static void cy_throttle(struct tty_struct *tty) |
1285 | cy_throttle(struct tty_struct * tty) | ||
1286 | { | 1278 | { |
1287 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1279 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; |
1288 | unsigned long flags; | 1280 | unsigned long flags; |
1289 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; | 1281 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; |
1290 | int channel; | 1282 | int channel; |
1291 | 1283 | ||
1292 | #ifdef SERIAL_DEBUG_THROTTLE | 1284 | #ifdef SERIAL_DEBUG_THROTTLE |
1293 | char buf[64]; | 1285 | char buf[64]; |
1294 | 1286 | ||
1295 | printk("throttle %s: %d....\n", tty_name(tty, buf), | 1287 | printk("throttle %s: %d....\n", tty_name(tty, buf), |
1296 | tty->ldisc.chars_in_buffer(tty)); | 1288 | tty->ldisc.chars_in_buffer(tty)); |
1297 | printk("cy_throttle %s\n", tty->name); | 1289 | printk("cy_throttle %s\n", tty->name); |
1298 | #endif | 1290 | #endif |
1299 | 1291 | ||
1300 | if (serial_paranoia_check(info, tty->name, "cy_nthrottle")){ | 1292 | if (serial_paranoia_check(info, tty->name, "cy_nthrottle")) { |
1301 | return; | 1293 | return; |
1302 | } | 1294 | } |
1303 | 1295 | ||
1304 | if (I_IXOFF(tty)) { | 1296 | if (I_IXOFF(tty)) { |
1305 | info->x_char = STOP_CHAR(tty); | 1297 | info->x_char = STOP_CHAR(tty); |
1306 | /* Should use the "Send Special Character" feature!!! */ | 1298 | /* Should use the "Send Special Character" feature!!! */ |
1307 | } | 1299 | } |
1308 | 1300 | ||
1309 | channel = info->line; | 1301 | channel = info->line; |
1310 | 1302 | ||
1311 | local_irq_save(flags); | 1303 | local_irq_save(flags); |
1312 | base_addr[CyCAR] = (u_char)channel; | 1304 | base_addr[CyCAR] = (u_char) channel; |
1313 | base_addr[CyMSVR1] = 0; | 1305 | base_addr[CyMSVR1] = 0; |
1314 | local_irq_restore(flags); | 1306 | local_irq_restore(flags); |
1315 | 1307 | } /* cy_throttle */ | |
1316 | return; | ||
1317 | } /* cy_throttle */ | ||
1318 | |||
1319 | 1308 | ||
1320 | static void | 1309 | static void cy_unthrottle(struct tty_struct *tty) |
1321 | cy_unthrottle(struct tty_struct * tty) | ||
1322 | { | 1310 | { |
1323 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1311 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; |
1324 | unsigned long flags; | 1312 | unsigned long flags; |
1325 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; | 1313 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; |
1326 | int channel; | 1314 | int channel; |
1327 | 1315 | ||
1328 | #ifdef SERIAL_DEBUG_THROTTLE | 1316 | #ifdef SERIAL_DEBUG_THROTTLE |
1329 | char buf[64]; | 1317 | char buf[64]; |
1330 | 1318 | ||
1331 | printk("throttle %s: %d....\n", tty_name(tty, buf), | 1319 | printk("throttle %s: %d....\n", tty_name(tty, buf), |
1332 | tty->ldisc.chars_in_buffer(tty)); | 1320 | tty->ldisc.chars_in_buffer(tty)); |
1333 | printk("cy_unthrottle %s\n", tty->name); | 1321 | printk("cy_unthrottle %s\n", tty->name); |
1334 | #endif | 1322 | #endif |
1335 | 1323 | ||
1336 | if (serial_paranoia_check(info, tty->name, "cy_nthrottle")){ | 1324 | if (serial_paranoia_check(info, tty->name, "cy_nthrottle")) { |
1337 | return; | 1325 | return; |
1338 | } | 1326 | } |
1339 | 1327 | ||
1340 | if (I_IXOFF(tty)) { | 1328 | if (I_IXOFF(tty)) { |
1341 | info->x_char = START_CHAR(tty); | 1329 | info->x_char = START_CHAR(tty); |
1342 | /* Should use the "Send Special Character" feature!!! */ | 1330 | /* Should use the "Send Special Character" feature!!! */ |
1343 | } | 1331 | } |
1344 | 1332 | ||
1345 | channel = info->line; | 1333 | channel = info->line; |
1346 | 1334 | ||
1347 | local_irq_save(flags); | 1335 | local_irq_save(flags); |
1348 | base_addr[CyCAR] = (u_char)channel; | 1336 | base_addr[CyCAR] = (u_char) channel; |
1349 | base_addr[CyMSVR1] = CyRTS; | 1337 | base_addr[CyMSVR1] = CyRTS; |
1350 | local_irq_restore(flags); | 1338 | local_irq_restore(flags); |
1351 | 1339 | } /* cy_unthrottle */ | |
1352 | return; | ||
1353 | } /* cy_unthrottle */ | ||
1354 | 1340 | ||
1355 | static int | 1341 | static int |
1356 | get_serial_info(struct cyclades_port * info, | 1342 | get_serial_info(struct cyclades_port *info, |
1357 | struct serial_struct __user * retinfo) | 1343 | struct serial_struct __user * retinfo) |
1358 | { | 1344 | { |
1359 | struct serial_struct tmp; | 1345 | struct serial_struct tmp; |
1360 | 1346 | ||
1361 | /* CP('g'); */ | 1347 | /* CP('g'); */ |
1362 | if (!retinfo) | 1348 | if (!retinfo) |
1363 | return -EFAULT; | 1349 | return -EFAULT; |
1364 | memset(&tmp, 0, sizeof(tmp)); | 1350 | memset(&tmp, 0, sizeof(tmp)); |
1365 | tmp.type = info->type; | 1351 | tmp.type = info->type; |
1366 | tmp.line = info->line; | 1352 | tmp.line = info->line; |
1367 | tmp.port = info->line; | 1353 | tmp.port = info->line; |
1368 | tmp.irq = 0; | 1354 | tmp.irq = 0; |
1369 | tmp.flags = info->flags; | 1355 | tmp.flags = info->flags; |
1370 | tmp.baud_base = 0; /*!!!*/ | 1356 | tmp.baud_base = 0; /*!!! */ |
1371 | tmp.close_delay = info->close_delay; | 1357 | tmp.close_delay = info->close_delay; |
1372 | tmp.custom_divisor = 0; /*!!!*/ | 1358 | tmp.custom_divisor = 0; /*!!! */ |
1373 | tmp.hub6 = 0; /*!!!*/ | 1359 | tmp.hub6 = 0; /*!!! */ |
1374 | return copy_to_user(retinfo,&tmp,sizeof(*retinfo)) ? -EFAULT : 0; | 1360 | return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0; |
1375 | } /* get_serial_info */ | 1361 | } /* get_serial_info */ |
1376 | 1362 | ||
1377 | static int | 1363 | static int |
1378 | set_serial_info(struct cyclades_port * info, | 1364 | set_serial_info(struct cyclades_port *info, |
1379 | struct serial_struct __user * new_info) | 1365 | struct serial_struct __user * new_info) |
1380 | { | 1366 | { |
1381 | struct serial_struct new_serial; | 1367 | struct serial_struct new_serial; |
1382 | struct cyclades_port old_info; | 1368 | struct cyclades_port old_info; |
1383 | 1369 | ||
1384 | /* CP('s'); */ | 1370 | /* CP('s'); */ |
1385 | if (!new_info) | 1371 | if (!new_info) |
1386 | return -EFAULT; | 1372 | return -EFAULT; |
1387 | if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) | 1373 | if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) |
1388 | return -EFAULT; | 1374 | return -EFAULT; |
1389 | old_info = *info; | 1375 | old_info = *info; |
1376 | |||
1377 | if (!capable(CAP_SYS_ADMIN)) { | ||
1378 | if ((new_serial.close_delay != info->close_delay) || | ||
1379 | ((new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) != | ||
1380 | (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))) | ||
1381 | return -EPERM; | ||
1382 | info->flags = ((info->flags & ~ASYNC_USR_MASK) | | ||
1383 | (new_serial.flags & ASYNC_USR_MASK)); | ||
1384 | goto check_and_exit; | ||
1385 | } | ||
1390 | 1386 | ||
1391 | if (!capable(CAP_SYS_ADMIN)) { | 1387 | /* |
1392 | if ((new_serial.close_delay != info->close_delay) || | 1388 | * OK, past this point, all the error checking has been done. |
1393 | ((new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) != | 1389 | * At this point, we start making changes..... |
1394 | (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))) | 1390 | */ |
1395 | return -EPERM; | ||
1396 | info->flags = ((info->flags & ~ASYNC_USR_MASK) | | ||
1397 | (new_serial.flags & ASYNC_USR_MASK)); | ||
1398 | goto check_and_exit; | ||
1399 | } | ||
1400 | 1391 | ||
1392 | info->flags = ((info->flags & ~ASYNC_FLAGS) | | ||
1393 | (new_serial.flags & ASYNC_FLAGS)); | ||
1394 | info->close_delay = new_serial.close_delay; | ||
1401 | 1395 | ||
1402 | /* | 1396 | check_and_exit: |
1403 | * OK, past this point, all the error checking has been done. | 1397 | if (info->flags & ASYNC_INITIALIZED) { |
1404 | * At this point, we start making changes..... | 1398 | config_setup(info); |
1405 | */ | 1399 | return 0; |
1400 | } | ||
1401 | return startup(info); | ||
1402 | } /* set_serial_info */ | ||
1406 | 1403 | ||
1407 | info->flags = ((info->flags & ~ASYNC_FLAGS) | | 1404 | static int cy_tiocmget(struct tty_struct *tty, struct file *file) |
1408 | (new_serial.flags & ASYNC_FLAGS)); | 1405 | { |
1409 | info->close_delay = new_serial.close_delay; | 1406 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; |
1407 | int channel; | ||
1408 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | ||
1409 | unsigned long flags; | ||
1410 | unsigned char status; | ||
1410 | 1411 | ||
1412 | channel = info->line; | ||
1411 | 1413 | ||
1412 | check_and_exit: | 1414 | local_irq_save(flags); |
1413 | if (info->flags & ASYNC_INITIALIZED){ | 1415 | base_addr[CyCAR] = (u_char) channel; |
1414 | config_setup(info); | 1416 | status = base_addr[CyMSVR1] | base_addr[CyMSVR2]; |
1415 | return 0; | 1417 | local_irq_restore(flags); |
1416 | }else{ | ||
1417 | return startup(info); | ||
1418 | } | ||
1419 | } /* set_serial_info */ | ||
1420 | 1418 | ||
1421 | static int | 1419 | return ((status & CyRTS) ? TIOCM_RTS : 0) |
1422 | cy_tiocmget(struct tty_struct *tty, struct file *file) | 1420 | | ((status & CyDTR) ? TIOCM_DTR : 0) |
1423 | { | 1421 | | ((status & CyDCD) ? TIOCM_CAR : 0) |
1424 | struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; | 1422 | | ((status & CyDSR) ? TIOCM_DSR : 0) |
1425 | int channel; | 1423 | | ((status & CyCTS) ? TIOCM_CTS : 0); |
1426 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; | 1424 | } /* cy_tiocmget */ |
1427 | unsigned long flags; | ||
1428 | unsigned char status; | ||
1429 | |||
1430 | channel = info->line; | ||
1431 | |||
1432 | local_irq_save(flags); | ||
1433 | base_addr[CyCAR] = (u_char)channel; | ||
1434 | status = base_addr[CyMSVR1] | base_addr[CyMSVR2]; | ||
1435 | local_irq_restore(flags); | ||
1436 | |||
1437 | return ((status & CyRTS) ? TIOCM_RTS : 0) | ||
1438 | | ((status & CyDTR) ? TIOCM_DTR : 0) | ||
1439 | | ((status & CyDCD) ? TIOCM_CAR : 0) | ||
1440 | | ((status & CyDSR) ? TIOCM_DSR : 0) | ||
1441 | | ((status & CyCTS) ? TIOCM_CTS : 0); | ||
1442 | } /* cy_tiocmget */ | ||
1443 | 1425 | ||
1444 | static int | 1426 | static int |
1445 | cy_tiocmset(struct tty_struct *tty, struct file *file, | 1427 | cy_tiocmset(struct tty_struct *tty, struct file *file, |
1446 | unsigned int set, unsigned int clear) | 1428 | unsigned int set, unsigned int clear) |
1447 | { | 1429 | { |
1448 | struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; | 1430 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; |
1449 | int channel; | 1431 | int channel; |
1450 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; | 1432 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; |
1451 | unsigned long flags; | 1433 | unsigned long flags; |
1452 | 1434 | ||
1453 | channel = info->line; | 1435 | channel = info->line; |
1454 | 1436 | ||
1455 | if (set & TIOCM_RTS){ | 1437 | if (set & TIOCM_RTS) { |
1456 | local_irq_save(flags); | 1438 | local_irq_save(flags); |
1457 | base_addr[CyCAR] = (u_char)channel; | 1439 | base_addr[CyCAR] = (u_char) channel; |
1458 | base_addr[CyMSVR1] = CyRTS; | 1440 | base_addr[CyMSVR1] = CyRTS; |
1459 | local_irq_restore(flags); | 1441 | local_irq_restore(flags); |
1460 | } | 1442 | } |
1461 | if (set & TIOCM_DTR){ | 1443 | if (set & TIOCM_DTR) { |
1462 | local_irq_save(flags); | 1444 | local_irq_save(flags); |
1463 | base_addr[CyCAR] = (u_char)channel; | 1445 | base_addr[CyCAR] = (u_char) channel; |
1464 | /* CP('S');CP('2'); */ | 1446 | /* CP('S');CP('2'); */ |
1465 | base_addr[CyMSVR2] = CyDTR; | 1447 | base_addr[CyMSVR2] = CyDTR; |
1466 | #ifdef SERIAL_DEBUG_DTR | 1448 | #ifdef SERIAL_DEBUG_DTR |
1467 | printk("cyc: %d: raising DTR\n", __LINE__); | 1449 | printk("cyc: %d: raising DTR\n", __LINE__); |
1468 | printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]); | 1450 | printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], |
1451 | base_addr[CyMSVR2]); | ||
1469 | #endif | 1452 | #endif |
1470 | local_irq_restore(flags); | 1453 | local_irq_restore(flags); |
1471 | } | 1454 | } |
1472 | 1455 | ||
1473 | if (clear & TIOCM_RTS){ | 1456 | if (clear & TIOCM_RTS) { |
1474 | local_irq_save(flags); | 1457 | local_irq_save(flags); |
1475 | base_addr[CyCAR] = (u_char)channel; | 1458 | base_addr[CyCAR] = (u_char) channel; |
1476 | base_addr[CyMSVR1] = 0; | 1459 | base_addr[CyMSVR1] = 0; |
1477 | local_irq_restore(flags); | 1460 | local_irq_restore(flags); |
1478 | } | 1461 | } |
1479 | if (clear & TIOCM_DTR){ | 1462 | if (clear & TIOCM_DTR) { |
1480 | local_irq_save(flags); | 1463 | local_irq_save(flags); |
1481 | base_addr[CyCAR] = (u_char)channel; | 1464 | base_addr[CyCAR] = (u_char) channel; |
1482 | /* CP('C');CP('2'); */ | 1465 | /* CP('C');CP('2'); */ |
1483 | base_addr[CyMSVR2] = 0; | 1466 | base_addr[CyMSVR2] = 0; |
1484 | #ifdef SERIAL_DEBUG_DTR | 1467 | #ifdef SERIAL_DEBUG_DTR |
1485 | printk("cyc: %d: dropping DTR\n", __LINE__); | 1468 | printk("cyc: %d: dropping DTR\n", __LINE__); |
1486 | printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]); | 1469 | printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], |
1470 | base_addr[CyMSVR2]); | ||
1487 | #endif | 1471 | #endif |
1488 | local_irq_restore(flags); | 1472 | local_irq_restore(flags); |
1489 | } | 1473 | } |
1490 | 1474 | ||
1491 | return 0; | 1475 | return 0; |
1492 | } /* set_modem_info */ | 1476 | } /* set_modem_info */ |
1493 | 1477 | ||
1494 | static void | 1478 | static void send_break(struct cyclades_port *info, int duration) |
1495 | send_break( struct cyclades_port * info, int duration) | 1479 | { /* Let the transmit ISR take care of this (since it |
1496 | { /* Let the transmit ISR take care of this (since it | 1480 | requires stuffing characters into the output stream). |
1497 | requires stuffing characters into the output stream). | 1481 | */ |
1498 | */ | 1482 | info->x_break = duration; |
1499 | info->x_break = duration; | 1483 | if (!info->xmit_cnt) { |
1500 | if (!info->xmit_cnt ) { | 1484 | start_xmit(info); |
1501 | start_xmit(info); | 1485 | } |
1502 | } | 1486 | } /* send_break */ |
1503 | } /* send_break */ | ||
1504 | 1487 | ||
1505 | static int | 1488 | static int |
1506 | get_mon_info(struct cyclades_port * info, struct cyclades_monitor __user * mon) | 1489 | get_mon_info(struct cyclades_port *info, struct cyclades_monitor __user * mon) |
1507 | { | 1490 | { |
1508 | 1491 | ||
1509 | if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor))) | 1492 | if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor))) |
1510 | return -EFAULT; | 1493 | return -EFAULT; |
1511 | info->mon.int_count = 0; | 1494 | info->mon.int_count = 0; |
1512 | info->mon.char_count = 0; | 1495 | info->mon.char_count = 0; |
1513 | info->mon.char_max = 0; | 1496 | info->mon.char_max = 0; |
1514 | info->mon.char_last = 0; | 1497 | info->mon.char_last = 0; |
1515 | return 0; | 1498 | return 0; |
1516 | } | 1499 | } |
1517 | 1500 | ||
1518 | static int | 1501 | static int set_threshold(struct cyclades_port *info, unsigned long __user * arg) |
1519 | set_threshold(struct cyclades_port * info, unsigned long __user *arg) | ||
1520 | { | 1502 | { |
1521 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; | 1503 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; |
1522 | unsigned long value; | 1504 | unsigned long value; |
1523 | int channel; | 1505 | int channel; |
1524 | 1506 | ||
1525 | if (get_user(value, arg)) | 1507 | if (get_user(value, arg)) |
1526 | return -EFAULT; | 1508 | return -EFAULT; |
1527 | 1509 | ||
1528 | channel = info->line; | 1510 | channel = info->line; |
1529 | info->cor4 &= ~CyREC_FIFO; | 1511 | info->cor4 &= ~CyREC_FIFO; |
1530 | info->cor4 |= value & CyREC_FIFO; | 1512 | info->cor4 |= value & CyREC_FIFO; |
1531 | base_addr[CyCOR4] = info->cor4; | 1513 | base_addr[CyCOR4] = info->cor4; |
1532 | return 0; | 1514 | return 0; |
1533 | } | 1515 | } |
1534 | 1516 | ||
1535 | static int | 1517 | static int |
1536 | get_threshold(struct cyclades_port * info, unsigned long __user *value) | 1518 | get_threshold(struct cyclades_port *info, unsigned long __user * value) |
1537 | { | 1519 | { |
1538 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; | 1520 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; |
1539 | int channel; | 1521 | int channel; |
1540 | unsigned long tmp; | 1522 | unsigned long tmp; |
1541 | 1523 | ||
1542 | channel = info->line; | 1524 | channel = info->line; |
1543 | 1525 | ||
1544 | tmp = base_addr[CyCOR4] & CyREC_FIFO; | 1526 | tmp = base_addr[CyCOR4] & CyREC_FIFO; |
1545 | return put_user(tmp,value); | 1527 | return put_user(tmp, value); |
1546 | } | 1528 | } |
1547 | 1529 | ||
1548 | static int | 1530 | static int |
1549 | set_default_threshold(struct cyclades_port * info, unsigned long __user *arg) | 1531 | set_default_threshold(struct cyclades_port *info, unsigned long __user * arg) |
1550 | { | 1532 | { |
1551 | unsigned long value; | 1533 | unsigned long value; |
1552 | 1534 | ||
1553 | if (get_user(value, arg)) | 1535 | if (get_user(value, arg)) |
1554 | return -EFAULT; | 1536 | return -EFAULT; |
1555 | 1537 | ||
1556 | info->default_threshold = value & 0x0f; | 1538 | info->default_threshold = value & 0x0f; |
1557 | return 0; | 1539 | return 0; |
1558 | } | 1540 | } |
1559 | 1541 | ||
1560 | static int | 1542 | static int |
1561 | get_default_threshold(struct cyclades_port * info, unsigned long __user *value) | 1543 | get_default_threshold(struct cyclades_port *info, unsigned long __user * value) |
1562 | { | 1544 | { |
1563 | return put_user(info->default_threshold,value); | 1545 | return put_user(info->default_threshold, value); |
1564 | } | 1546 | } |
1565 | 1547 | ||
1566 | static int | 1548 | static int set_timeout(struct cyclades_port *info, unsigned long __user * arg) |
1567 | set_timeout(struct cyclades_port * info, unsigned long __user *arg) | ||
1568 | { | 1549 | { |
1569 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; | 1550 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; |
1570 | int channel; | 1551 | int channel; |
1571 | unsigned long value; | 1552 | unsigned long value; |
1572 | 1553 | ||
1573 | if (get_user(value, arg)) | 1554 | if (get_user(value, arg)) |
1574 | return -EFAULT; | 1555 | return -EFAULT; |
1575 | 1556 | ||
1576 | channel = info->line; | 1557 | channel = info->line; |
1577 | 1558 | ||
1578 | base_addr[CyRTPRL] = value & 0xff; | 1559 | base_addr[CyRTPRL] = value & 0xff; |
1579 | base_addr[CyRTPRH] = (value >> 8) & 0xff; | 1560 | base_addr[CyRTPRH] = (value >> 8) & 0xff; |
1580 | return 0; | 1561 | return 0; |
1581 | } | 1562 | } |
1582 | 1563 | ||
1583 | static int | 1564 | static int get_timeout(struct cyclades_port *info, unsigned long __user * value) |
1584 | get_timeout(struct cyclades_port * info, unsigned long __user *value) | ||
1585 | { | 1565 | { |
1586 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; | 1566 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; |
1587 | int channel; | 1567 | int channel; |
1588 | unsigned long tmp; | 1568 | unsigned long tmp; |
1589 | 1569 | ||
1590 | channel = info->line; | 1570 | channel = info->line; |
1591 | 1571 | ||
1592 | tmp = base_addr[CyRTPRL]; | 1572 | tmp = base_addr[CyRTPRL]; |
1593 | return put_user(tmp,value); | 1573 | return put_user(tmp, value); |
1594 | } | 1574 | } |
1595 | 1575 | ||
1596 | static int | 1576 | static int set_default_timeout(struct cyclades_port *info, unsigned long value) |
1597 | set_default_timeout(struct cyclades_port * info, unsigned long value) | ||
1598 | { | 1577 | { |
1599 | info->default_timeout = value & 0xff; | 1578 | info->default_timeout = value & 0xff; |
1600 | return 0; | 1579 | return 0; |
1601 | } | 1580 | } |
1602 | 1581 | ||
1603 | static int | 1582 | static int |
1604 | get_default_timeout(struct cyclades_port * info, unsigned long __user *value) | 1583 | get_default_timeout(struct cyclades_port *info, unsigned long __user * value) |
1605 | { | 1584 | { |
1606 | return put_user(info->default_timeout,value); | 1585 | return put_user(info->default_timeout, value); |
1607 | } | 1586 | } |
1608 | 1587 | ||
1609 | static int | 1588 | static int |
1610 | cy_ioctl(struct tty_struct *tty, struct file * file, | 1589 | cy_ioctl(struct tty_struct *tty, struct file *file, |
1611 | unsigned int cmd, unsigned long arg) | 1590 | unsigned int cmd, unsigned long arg) |
1612 | { | 1591 | { |
1613 | unsigned long val; | 1592 | unsigned long val; |
1614 | struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; | 1593 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; |
1615 | int ret_val = 0; | 1594 | int ret_val = 0; |
1616 | void __user *argp = (void __user *)arg; | 1595 | void __user *argp = (void __user *)arg; |
1617 | 1596 | ||
1618 | #ifdef SERIAL_DEBUG_OTHER | 1597 | #ifdef SERIAL_DEBUG_OTHER |
1619 | printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */ | 1598 | printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */ |
1620 | #endif | 1599 | #endif |
1621 | 1600 | ||
1622 | switch (cmd) { | 1601 | switch (cmd) { |
1623 | case CYGETMON: | 1602 | case CYGETMON: |
1624 | ret_val = get_mon_info(info, argp); | 1603 | ret_val = get_mon_info(info, argp); |
1625 | break; | 1604 | break; |
1626 | case CYGETTHRESH: | 1605 | case CYGETTHRESH: |
1627 | ret_val = get_threshold(info, argp); | 1606 | ret_val = get_threshold(info, argp); |
1628 | break; | 1607 | break; |
1629 | case CYSETTHRESH: | 1608 | case CYSETTHRESH: |
1630 | ret_val = set_threshold(info, argp); | 1609 | ret_val = set_threshold(info, argp); |
1631 | break; | 1610 | break; |
1632 | case CYGETDEFTHRESH: | 1611 | case CYGETDEFTHRESH: |
1633 | ret_val = get_default_threshold(info, argp); | 1612 | ret_val = get_default_threshold(info, argp); |
1634 | break; | 1613 | break; |
1635 | case CYSETDEFTHRESH: | 1614 | case CYSETDEFTHRESH: |
1636 | ret_val = set_default_threshold(info, argp); | 1615 | ret_val = set_default_threshold(info, argp); |
1637 | break; | 1616 | break; |
1638 | case CYGETTIMEOUT: | 1617 | case CYGETTIMEOUT: |
1639 | ret_val = get_timeout(info, argp); | 1618 | ret_val = get_timeout(info, argp); |
1640 | break; | 1619 | break; |
1641 | case CYSETTIMEOUT: | 1620 | case CYSETTIMEOUT: |
1642 | ret_val = set_timeout(info, argp); | 1621 | ret_val = set_timeout(info, argp); |
1643 | break; | 1622 | break; |
1644 | case CYGETDEFTIMEOUT: | 1623 | case CYGETDEFTIMEOUT: |
1645 | ret_val = get_default_timeout(info, argp); | 1624 | ret_val = get_default_timeout(info, argp); |
1646 | break; | 1625 | break; |
1647 | case CYSETDEFTIMEOUT: | 1626 | case CYSETDEFTIMEOUT: |
1648 | ret_val = set_default_timeout(info, (unsigned long)arg); | 1627 | ret_val = set_default_timeout(info, (unsigned long)arg); |
1649 | break; | 1628 | break; |
1650 | case TCSBRK: /* SVID version: non-zero arg --> no break */ | 1629 | case TCSBRK: /* SVID version: non-zero arg --> no break */ |
1651 | ret_val = tty_check_change(tty); | 1630 | ret_val = tty_check_change(tty); |
1652 | if (ret_val) | 1631 | if (ret_val) |
1653 | break; | 1632 | break; |
1654 | tty_wait_until_sent(tty,0); | 1633 | tty_wait_until_sent(tty, 0); |
1655 | if (!arg) | 1634 | if (!arg) |
1656 | send_break(info, HZ/4); /* 1/4 second */ | 1635 | send_break(info, HZ / 4); /* 1/4 second */ |
1657 | break; | 1636 | break; |
1658 | case TCSBRKP: /* support for POSIX tcsendbreak() */ | 1637 | case TCSBRKP: /* support for POSIX tcsendbreak() */ |
1659 | ret_val = tty_check_change(tty); | 1638 | ret_val = tty_check_change(tty); |
1660 | if (ret_val) | 1639 | if (ret_val) |
1640 | break; | ||
1641 | tty_wait_until_sent(tty, 0); | ||
1642 | send_break(info, arg ? arg * (HZ / 10) : HZ / 4); | ||
1661 | break; | 1643 | break; |
1662 | tty_wait_until_sent(tty,0); | ||
1663 | send_break(info, arg ? arg*(HZ/10) : HZ/4); | ||
1664 | break; | ||
1665 | 1644 | ||
1666 | /* The following commands are incompletely implemented!!! */ | 1645 | /* The following commands are incompletely implemented!!! */ |
1667 | case TIOCGSOFTCAR: | 1646 | case TIOCGSOFTCAR: |
1668 | ret_val = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) argp); | 1647 | ret_val = |
1669 | break; | 1648 | put_user(C_CLOCAL(tty) ? 1 : 0, |
1670 | case TIOCSSOFTCAR: | 1649 | (unsigned long __user *)argp); |
1671 | ret_val = get_user(val, (unsigned long __user *) argp); | 1650 | break; |
1672 | if (ret_val) | 1651 | case TIOCSSOFTCAR: |
1673 | break; | 1652 | ret_val = get_user(val, (unsigned long __user *)argp); |
1674 | tty->termios->c_cflag = | 1653 | if (ret_val) |
1675 | ((tty->termios->c_cflag & ~CLOCAL) | (val ? CLOCAL : 0)); | 1654 | break; |
1676 | break; | 1655 | tty->termios->c_cflag = |
1677 | case TIOCGSERIAL: | 1656 | ((tty->termios->c_cflag & ~CLOCAL) | (val ? CLOCAL : 0)); |
1678 | ret_val = get_serial_info(info, argp); | 1657 | break; |
1679 | break; | 1658 | case TIOCGSERIAL: |
1680 | case TIOCSSERIAL: | 1659 | ret_val = get_serial_info(info, argp); |
1681 | ret_val = set_serial_info(info, argp); | 1660 | break; |
1682 | break; | 1661 | case TIOCSSERIAL: |
1683 | default: | 1662 | ret_val = set_serial_info(info, argp); |
1684 | ret_val = -ENOIOCTLCMD; | 1663 | break; |
1685 | } | 1664 | default: |
1665 | ret_val = -ENOIOCTLCMD; | ||
1666 | } | ||
1686 | 1667 | ||
1687 | #ifdef SERIAL_DEBUG_OTHER | 1668 | #ifdef SERIAL_DEBUG_OTHER |
1688 | printk("cy_ioctl done\n"); | 1669 | printk("cy_ioctl done\n"); |
1689 | #endif | 1670 | #endif |
1690 | 1671 | ||
1691 | return ret_val; | 1672 | return ret_val; |
1692 | } /* cy_ioctl */ | 1673 | } /* cy_ioctl */ |
1693 | |||
1694 | 1674 | ||
1695 | 1675 | static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | |
1696 | |||
1697 | static void | ||
1698 | cy_set_termios(struct tty_struct *tty, struct ktermios * old_termios) | ||
1699 | { | 1676 | { |
1700 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1677 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; |
1701 | 1678 | ||
1702 | #ifdef SERIAL_DEBUG_OTHER | 1679 | #ifdef SERIAL_DEBUG_OTHER |
1703 | printk("cy_set_termios %s\n", tty->name); | 1680 | printk("cy_set_termios %s\n", tty->name); |
1704 | #endif | 1681 | #endif |
1705 | 1682 | ||
1706 | if (tty->termios->c_cflag == old_termios->c_cflag) | 1683 | if (tty->termios->c_cflag == old_termios->c_cflag) |
1707 | return; | 1684 | return; |
1708 | config_setup(info); | 1685 | config_setup(info); |
1709 | 1686 | ||
1710 | if ((old_termios->c_cflag & CRTSCTS) && | 1687 | if ((old_termios->c_cflag & CRTSCTS) && |
1711 | !(tty->termios->c_cflag & CRTSCTS)) { | 1688 | !(tty->termios->c_cflag & CRTSCTS)) { |
1712 | tty->stopped = 0; | 1689 | tty->stopped = 0; |
1713 | cy_start(tty); | 1690 | cy_start(tty); |
1714 | } | 1691 | } |
1715 | #ifdef tytso_patch_94Nov25_1726 | 1692 | #ifdef tytso_patch_94Nov25_1726 |
1716 | if (!(old_termios->c_cflag & CLOCAL) && | 1693 | if (!(old_termios->c_cflag & CLOCAL) && |
1717 | (tty->termios->c_cflag & CLOCAL)) | 1694 | (tty->termios->c_cflag & CLOCAL)) |
1718 | wake_up_interruptible(&info->open_wait); | 1695 | wake_up_interruptible(&info->open_wait); |
1719 | #endif | 1696 | #endif |
1697 | } /* cy_set_termios */ | ||
1720 | 1698 | ||
1721 | return; | 1699 | static void cy_close(struct tty_struct *tty, struct file *filp) |
1722 | } /* cy_set_termios */ | ||
1723 | |||
1724 | |||
1725 | static void | ||
1726 | cy_close(struct tty_struct * tty, struct file * filp) | ||
1727 | { | 1700 | { |
1728 | struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; | 1701 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; |
1729 | 1702 | ||
1730 | /* CP('C'); */ | 1703 | /* CP('C'); */ |
1731 | #ifdef SERIAL_DEBUG_OTHER | 1704 | #ifdef SERIAL_DEBUG_OTHER |
1732 | printk("cy_close %s\n", tty->name); | 1705 | printk("cy_close %s\n", tty->name); |
1733 | #endif | 1706 | #endif |
1734 | 1707 | ||
1735 | if (!info | 1708 | if (!info || serial_paranoia_check(info, tty->name, "cy_close")) { |
1736 | || serial_paranoia_check(info, tty->name, "cy_close")){ | 1709 | return; |
1737 | return; | 1710 | } |
1738 | } | ||
1739 | #ifdef SERIAL_DEBUG_OPEN | 1711 | #ifdef SERIAL_DEBUG_OPEN |
1740 | printk("cy_close %s, count = %d\n", tty->name, info->count); | 1712 | printk("cy_close %s, count = %d\n", tty->name, info->count); |
1741 | #endif | 1713 | #endif |
1742 | 1714 | ||
1743 | if ((tty->count == 1) && (info->count != 1)) { | 1715 | if ((tty->count == 1) && (info->count != 1)) { |
1744 | /* | 1716 | /* |
1745 | * Uh, oh. tty->count is 1, which means that the tty | 1717 | * Uh, oh. tty->count is 1, which means that the tty |
1746 | * structure will be freed. Info->count should always | 1718 | * structure will be freed. Info->count should always |
1747 | * be one in these conditions. If it's greater than | 1719 | * be one in these conditions. If it's greater than |
1748 | * one, we've got real problems, since it means the | 1720 | * one, we've got real problems, since it means the |
1749 | * serial port won't be shutdown. | 1721 | * serial port won't be shutdown. |
1750 | */ | 1722 | */ |
1751 | printk("cy_close: bad serial port count; tty->count is 1, " | 1723 | printk("cy_close: bad serial port count; tty->count is 1, " |
1752 | "info->count is %d\n", info->count); | 1724 | "info->count is %d\n", info->count); |
1753 | info->count = 1; | 1725 | info->count = 1; |
1754 | } | 1726 | } |
1755 | #ifdef SERIAL_DEBUG_COUNT | 1727 | #ifdef SERIAL_DEBUG_COUNT |
1756 | printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count - 1); | 1728 | printk("cyc: %d: decrementing count to %d\n", __LINE__, |
1729 | info->count - 1); | ||
1757 | #endif | 1730 | #endif |
1758 | if (--info->count < 0) { | 1731 | if (--info->count < 0) { |
1759 | printk("cy_close: bad serial port count for ttys%d: %d\n", | 1732 | printk("cy_close: bad serial port count for ttys%d: %d\n", |
1760 | info->line, info->count); | 1733 | info->line, info->count); |
1761 | #ifdef SERIAL_DEBUG_COUNT | 1734 | #ifdef SERIAL_DEBUG_COUNT |
1762 | printk("cyc: %d: setting count to 0\n", __LINE__); | 1735 | printk("cyc: %d: setting count to 0\n", __LINE__); |
1763 | #endif | 1736 | #endif |
1764 | info->count = 0; | 1737 | info->count = 0; |
1765 | } | ||
1766 | if (info->count) | ||
1767 | return; | ||
1768 | info->flags |= ASYNC_CLOSING; | ||
1769 | if (info->flags & ASYNC_INITIALIZED) | ||
1770 | tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */ | ||
1771 | shutdown(info); | ||
1772 | if (tty->driver->flush_buffer) | ||
1773 | tty->driver->flush_buffer(tty); | ||
1774 | tty_ldisc_flush(tty); | ||
1775 | info->event = 0; | ||
1776 | info->tty = NULL; | ||
1777 | if (info->blocked_open) { | ||
1778 | if (info->close_delay) { | ||
1779 | msleep_interruptible(jiffies_to_msecs(info->close_delay)); | ||
1780 | } | 1738 | } |
1781 | wake_up_interruptible(&info->open_wait); | 1739 | if (info->count) |
1782 | } | 1740 | return; |
1783 | info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | 1741 | info->flags |= ASYNC_CLOSING; |
1784 | wake_up_interruptible(&info->close_wait); | 1742 | if (info->flags & ASYNC_INITIALIZED) |
1743 | tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */ | ||
1744 | shutdown(info); | ||
1745 | if (tty->driver->flush_buffer) | ||
1746 | tty->driver->flush_buffer(tty); | ||
1747 | tty_ldisc_flush(tty); | ||
1748 | info->event = 0; | ||
1749 | info->tty = NULL; | ||
1750 | if (info->blocked_open) { | ||
1751 | if (info->close_delay) { | ||
1752 | msleep_interruptible(jiffies_to_msecs | ||
1753 | (info->close_delay)); | ||
1754 | } | ||
1755 | wake_up_interruptible(&info->open_wait); | ||
1756 | } | ||
1757 | info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); | ||
1758 | wake_up_interruptible(&info->close_wait); | ||
1785 | 1759 | ||
1786 | #ifdef SERIAL_DEBUG_OTHER | 1760 | #ifdef SERIAL_DEBUG_OTHER |
1787 | printk("cy_close done\n"); | 1761 | printk("cy_close done\n"); |
1788 | #endif | 1762 | #endif |
1789 | 1763 | } /* cy_close */ | |
1790 | return; | ||
1791 | } /* cy_close */ | ||
1792 | 1764 | ||
1793 | /* | 1765 | /* |
1794 | * cy_hangup() --- called by tty_hangup() when a hangup is signaled. | 1766 | * cy_hangup() --- called by tty_hangup() when a hangup is signaled. |
1795 | */ | 1767 | */ |
1796 | void | 1768 | void cy_hangup(struct tty_struct *tty) |
1797 | cy_hangup(struct tty_struct *tty) | ||
1798 | { | 1769 | { |
1799 | struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; | 1770 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; |
1800 | 1771 | ||
1801 | #ifdef SERIAL_DEBUG_OTHER | 1772 | #ifdef SERIAL_DEBUG_OTHER |
1802 | printk("cy_hangup %s\n", tty->name); /* */ | 1773 | printk("cy_hangup %s\n", tty->name); /* */ |
1803 | #endif | 1774 | #endif |
1804 | 1775 | ||
1805 | if (serial_paranoia_check(info, tty->name, "cy_hangup")) | 1776 | if (serial_paranoia_check(info, tty->name, "cy_hangup")) |
1806 | return; | 1777 | return; |
1807 | 1778 | ||
1808 | shutdown(info); | 1779 | shutdown(info); |
1809 | #if 0 | 1780 | #if 0 |
1810 | info->event = 0; | 1781 | info->event = 0; |
1811 | info->count = 0; | 1782 | info->count = 0; |
1812 | #ifdef SERIAL_DEBUG_COUNT | 1783 | #ifdef SERIAL_DEBUG_COUNT |
1813 | printk("cyc: %d: setting count to 0\n", __LINE__); | 1784 | printk("cyc: %d: setting count to 0\n", __LINE__); |
1814 | #endif | 1785 | #endif |
1815 | info->tty = 0; | 1786 | info->tty = 0; |
1816 | #endif | 1787 | #endif |
1817 | info->flags &= ~ASYNC_NORMAL_ACTIVE; | 1788 | info->flags &= ~ASYNC_NORMAL_ACTIVE; |
1818 | wake_up_interruptible(&info->open_wait); | 1789 | wake_up_interruptible(&info->open_wait); |
1819 | } /* cy_hangup */ | 1790 | } /* cy_hangup */ |
1820 | |||
1821 | |||
1822 | 1791 | ||
1823 | /* | 1792 | /* |
1824 | * ------------------------------------------------------------ | 1793 | * ------------------------------------------------------------ |
@@ -1827,177 +1796,180 @@ cy_hangup(struct tty_struct *tty) | |||
1827 | */ | 1796 | */ |
1828 | 1797 | ||
1829 | static int | 1798 | static int |
1830 | block_til_ready(struct tty_struct *tty, struct file * filp, | 1799 | block_til_ready(struct tty_struct *tty, struct file *filp, |
1831 | struct cyclades_port *info) | 1800 | struct cyclades_port *info) |
1832 | { | 1801 | { |
1833 | DECLARE_WAITQUEUE(wait, current); | 1802 | DECLARE_WAITQUEUE(wait, current); |
1834 | unsigned long flags; | 1803 | unsigned long flags; |
1835 | int channel; | 1804 | int channel; |
1836 | int retval; | 1805 | int retval; |
1837 | volatile u_char *base_addr = (u_char *)BASE_ADDR; | 1806 | volatile u_char *base_addr = (u_char *) BASE_ADDR; |
1838 | 1807 | ||
1839 | /* | 1808 | /* |
1840 | * If the device is in the middle of being closed, then block | 1809 | * If the device is in the middle of being closed, then block |
1841 | * until it's done, and then try again. | 1810 | * until it's done, and then try again. |
1842 | */ | 1811 | */ |
1843 | if (info->flags & ASYNC_CLOSING) { | 1812 | if (info->flags & ASYNC_CLOSING) { |
1844 | interruptible_sleep_on(&info->close_wait); | 1813 | interruptible_sleep_on(&info->close_wait); |
1845 | if (info->flags & ASYNC_HUP_NOTIFY){ | 1814 | if (info->flags & ASYNC_HUP_NOTIFY) { |
1846 | return -EAGAIN; | 1815 | return -EAGAIN; |
1847 | }else{ | 1816 | } else { |
1848 | return -ERESTARTSYS; | 1817 | return -ERESTARTSYS; |
1849 | } | 1818 | } |
1850 | } | 1819 | } |
1851 | 1820 | ||
1852 | /* | 1821 | /* |
1853 | * If non-blocking mode is set, then make the check up front | 1822 | * If non-blocking mode is set, then make the check up front |
1854 | * and then exit. | 1823 | * and then exit. |
1855 | */ | 1824 | */ |
1856 | if (filp->f_flags & O_NONBLOCK) { | 1825 | if (filp->f_flags & O_NONBLOCK) { |
1857 | info->flags |= ASYNC_NORMAL_ACTIVE; | 1826 | info->flags |= ASYNC_NORMAL_ACTIVE; |
1858 | return 0; | 1827 | return 0; |
1859 | } | 1828 | } |
1860 | 1829 | ||
1861 | /* | 1830 | /* |
1862 | * Block waiting for the carrier detect and the line to become | 1831 | * Block waiting for the carrier detect and the line to become |
1863 | * free (i.e., not in use by the callout). While we are in | 1832 | * free (i.e., not in use by the callout). While we are in |
1864 | * this loop, info->count is dropped by one, so that | 1833 | * this loop, info->count is dropped by one, so that |
1865 | * cy_close() knows when to free things. We restore it upon | 1834 | * cy_close() knows when to free things. We restore it upon |
1866 | * exit, either normal or abnormal. | 1835 | * exit, either normal or abnormal. |
1867 | */ | 1836 | */ |
1868 | retval = 0; | 1837 | retval = 0; |
1869 | add_wait_queue(&info->open_wait, &wait); | 1838 | add_wait_queue(&info->open_wait, &wait); |
1870 | #ifdef SERIAL_DEBUG_OPEN | 1839 | #ifdef SERIAL_DEBUG_OPEN |
1871 | printk("block_til_ready before block: %s, count = %d\n", | 1840 | printk("block_til_ready before block: %s, count = %d\n", |
1872 | tty->name, info->count);/**/ | 1841 | tty->name, info->count); |
1842 | /**/ | ||
1873 | #endif | 1843 | #endif |
1874 | info->count--; | 1844 | info->count--; |
1875 | #ifdef SERIAL_DEBUG_COUNT | 1845 | #ifdef SERIAL_DEBUG_COUNT |
1876 | printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count); | 1846 | printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count); |
1877 | #endif | 1847 | #endif |
1878 | info->blocked_open++; | 1848 | info->blocked_open++; |
1879 | 1849 | ||
1880 | channel = info->line; | 1850 | channel = info->line; |
1881 | 1851 | ||
1882 | while (1) { | 1852 | while (1) { |
1883 | local_irq_save(flags); | 1853 | local_irq_save(flags); |
1884 | base_addr[CyCAR] = (u_char)channel; | 1854 | base_addr[CyCAR] = (u_char) channel; |
1885 | base_addr[CyMSVR1] = CyRTS; | 1855 | base_addr[CyMSVR1] = CyRTS; |
1886 | /* CP('S');CP('4'); */ | 1856 | /* CP('S');CP('4'); */ |
1887 | base_addr[CyMSVR2] = CyDTR; | 1857 | base_addr[CyMSVR2] = CyDTR; |
1888 | #ifdef SERIAL_DEBUG_DTR | 1858 | #ifdef SERIAL_DEBUG_DTR |
1889 | printk("cyc: %d: raising DTR\n", __LINE__); | 1859 | printk("cyc: %d: raising DTR\n", __LINE__); |
1890 | printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]); | 1860 | printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], |
1891 | #endif | 1861 | base_addr[CyMSVR2]); |
1892 | local_irq_restore(flags); | 1862 | #endif |
1893 | set_current_state(TASK_INTERRUPTIBLE); | 1863 | local_irq_restore(flags); |
1894 | if (tty_hung_up_p(filp) | 1864 | set_current_state(TASK_INTERRUPTIBLE); |
1895 | || !(info->flags & ASYNC_INITIALIZED) ){ | 1865 | if (tty_hung_up_p(filp) |
1896 | if (info->flags & ASYNC_HUP_NOTIFY) { | 1866 | || !(info->flags & ASYNC_INITIALIZED)) { |
1897 | retval = -EAGAIN; | 1867 | if (info->flags & ASYNC_HUP_NOTIFY) { |
1898 | }else{ | 1868 | retval = -EAGAIN; |
1899 | retval = -ERESTARTSYS; | 1869 | } else { |
1900 | } | 1870 | retval = -ERESTARTSYS; |
1901 | break; | 1871 | } |
1902 | } | 1872 | break; |
1903 | local_irq_save(flags); | 1873 | } |
1904 | base_addr[CyCAR] = (u_char)channel; | 1874 | local_irq_save(flags); |
1875 | base_addr[CyCAR] = (u_char) channel; | ||
1905 | /* CP('L');CP1(1 && C_CLOCAL(tty)); CP1(1 && (base_addr[CyMSVR1] & CyDCD) ); */ | 1876 | /* CP('L');CP1(1 && C_CLOCAL(tty)); CP1(1 && (base_addr[CyMSVR1] & CyDCD) ); */ |
1906 | if (!(info->flags & ASYNC_CLOSING) | 1877 | if (!(info->flags & ASYNC_CLOSING) |
1907 | && (C_CLOCAL(tty) | 1878 | && (C_CLOCAL(tty) |
1908 | || (base_addr[CyMSVR1] & CyDCD))) { | 1879 | || (base_addr[CyMSVR1] & CyDCD))) { |
1909 | local_irq_restore(flags); | 1880 | local_irq_restore(flags); |
1910 | break; | 1881 | break; |
1911 | } | 1882 | } |
1912 | local_irq_restore(flags); | 1883 | local_irq_restore(flags); |
1913 | if (signal_pending(current)) { | 1884 | if (signal_pending(current)) { |
1914 | retval = -ERESTARTSYS; | 1885 | retval = -ERESTARTSYS; |
1915 | break; | 1886 | break; |
1916 | } | 1887 | } |
1917 | #ifdef SERIAL_DEBUG_OPEN | 1888 | #ifdef SERIAL_DEBUG_OPEN |
1918 | printk("block_til_ready blocking: %s, count = %d\n", | 1889 | printk("block_til_ready blocking: %s, count = %d\n", |
1919 | tty->name, info->count);/**/ | 1890 | tty->name, info->count); |
1920 | #endif | 1891 | /**/ |
1921 | schedule(); | 1892 | #endif |
1922 | } | 1893 | schedule(); |
1923 | current->state = TASK_RUNNING; | 1894 | } |
1924 | remove_wait_queue(&info->open_wait, &wait); | 1895 | current->state = TASK_RUNNING; |
1925 | if (!tty_hung_up_p(filp)){ | 1896 | remove_wait_queue(&info->open_wait, &wait); |
1926 | info->count++; | 1897 | if (!tty_hung_up_p(filp)) { |
1898 | info->count++; | ||
1927 | #ifdef SERIAL_DEBUG_COUNT | 1899 | #ifdef SERIAL_DEBUG_COUNT |
1928 | printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count); | 1900 | printk("cyc: %d: incrementing count to %d\n", __LINE__, |
1901 | info->count); | ||
1929 | #endif | 1902 | #endif |
1930 | } | 1903 | } |
1931 | info->blocked_open--; | 1904 | info->blocked_open--; |
1932 | #ifdef SERIAL_DEBUG_OPEN | 1905 | #ifdef SERIAL_DEBUG_OPEN |
1933 | printk("block_til_ready after blocking: %s, count = %d\n", | 1906 | printk("block_til_ready after blocking: %s, count = %d\n", |
1934 | tty->name, info->count);/**/ | 1907 | tty->name, info->count); |
1908 | /**/ | ||
1935 | #endif | 1909 | #endif |
1936 | if (retval) | 1910 | if (retval) |
1937 | return retval; | 1911 | return retval; |
1938 | info->flags |= ASYNC_NORMAL_ACTIVE; | 1912 | info->flags |= ASYNC_NORMAL_ACTIVE; |
1939 | return 0; | 1913 | return 0; |
1940 | } /* block_til_ready */ | 1914 | } /* block_til_ready */ |
1941 | 1915 | ||
1942 | /* | 1916 | /* |
1943 | * This routine is called whenever a serial port is opened. It | 1917 | * This routine is called whenever a serial port is opened. It |
1944 | * performs the serial-specific initialization for the tty structure. | 1918 | * performs the serial-specific initialization for the tty structure. |
1945 | */ | 1919 | */ |
1946 | int | 1920 | int cy_open(struct tty_struct *tty, struct file *filp) |
1947 | cy_open(struct tty_struct *tty, struct file * filp) | ||
1948 | { | 1921 | { |
1949 | struct cyclades_port *info; | 1922 | struct cyclades_port *info; |
1950 | int retval, line; | 1923 | int retval, line; |
1951 | 1924 | ||
1952 | /* CP('O'); */ | 1925 | /* CP('O'); */ |
1953 | line = tty->index; | 1926 | line = tty->index; |
1954 | if ((line < 0) || (NR_PORTS <= line)){ | 1927 | if ((line < 0) || (NR_PORTS <= line)) { |
1955 | return -ENODEV; | 1928 | return -ENODEV; |
1956 | } | 1929 | } |
1957 | info = &cy_port[line]; | 1930 | info = &cy_port[line]; |
1958 | if (info->line < 0){ | 1931 | if (info->line < 0) { |
1959 | return -ENODEV; | 1932 | return -ENODEV; |
1960 | } | 1933 | } |
1961 | #ifdef SERIAL_DEBUG_OTHER | 1934 | #ifdef SERIAL_DEBUG_OTHER |
1962 | printk("cy_open %s\n", tty->name); /* */ | 1935 | printk("cy_open %s\n", tty->name); /* */ |
1963 | #endif | 1936 | #endif |
1964 | if (serial_paranoia_check(info, tty->name, "cy_open")){ | 1937 | if (serial_paranoia_check(info, tty->name, "cy_open")) { |
1965 | return -ENODEV; | 1938 | return -ENODEV; |
1966 | } | 1939 | } |
1967 | #ifdef SERIAL_DEBUG_OPEN | 1940 | #ifdef SERIAL_DEBUG_OPEN |
1968 | printk("cy_open %s, count = %d\n", tty->name, info->count);/**/ | 1941 | printk("cy_open %s, count = %d\n", tty->name, info->count); |
1942 | /**/ | ||
1969 | #endif | 1943 | #endif |
1970 | info->count++; | 1944 | info->count++; |
1971 | #ifdef SERIAL_DEBUG_COUNT | 1945 | #ifdef SERIAL_DEBUG_COUNT |
1972 | printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count); | 1946 | printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count); |
1973 | #endif | 1947 | #endif |
1974 | tty->driver_data = info; | 1948 | tty->driver_data = info; |
1975 | info->tty = tty; | 1949 | info->tty = tty; |
1976 | 1950 | ||
1977 | /* | 1951 | /* |
1978 | * Start up serial port | 1952 | * Start up serial port |
1979 | */ | 1953 | */ |
1980 | retval = startup(info); | 1954 | retval = startup(info); |
1981 | if (retval){ | 1955 | if (retval) { |
1982 | return retval; | 1956 | return retval; |
1983 | } | 1957 | } |
1984 | 1958 | ||
1985 | retval = block_til_ready(tty, filp, info); | 1959 | retval = block_til_ready(tty, filp, info); |
1986 | if (retval) { | 1960 | if (retval) { |
1987 | #ifdef SERIAL_DEBUG_OPEN | 1961 | #ifdef SERIAL_DEBUG_OPEN |
1988 | printk("cy_open returning after block_til_ready with %d\n", | 1962 | printk("cy_open returning after block_til_ready with %d\n", |
1989 | retval); | 1963 | retval); |
1990 | #endif | 1964 | #endif |
1991 | return retval; | 1965 | return retval; |
1992 | } | 1966 | } |
1993 | |||
1994 | #ifdef SERIAL_DEBUG_OPEN | 1967 | #ifdef SERIAL_DEBUG_OPEN |
1995 | printk("cy_open done\n");/**/ | 1968 | printk("cy_open done\n"); |
1969 | /**/ | ||
1996 | #endif | 1970 | #endif |
1997 | return 0; | 1971 | return 0; |
1998 | } /* cy_open */ | 1972 | } /* cy_open */ |
1999 | |||
2000 | |||
2001 | 1973 | ||
2002 | /* | 1974 | /* |
2003 | * --------------------------------------------------------------------- | 1975 | * --------------------------------------------------------------------- |
@@ -2012,11 +1984,10 @@ cy_open(struct tty_struct *tty, struct file * filp) | |||
2012 | * number, and identifies which options were configured into this | 1984 | * number, and identifies which options were configured into this |
2013 | * driver. | 1985 | * driver. |
2014 | */ | 1986 | */ |
2015 | static void | 1987 | static void show_version(void) |
2016 | show_version(void) | ||
2017 | { | 1988 | { |
2018 | printk("MVME166/167 cd2401 driver\n"); | 1989 | printk("MVME166/167 cd2401 driver\n"); |
2019 | } /* show_version */ | 1990 | } /* show_version */ |
2020 | 1991 | ||
2021 | /* initialize chips on card -- return number of valid | 1992 | /* initialize chips on card -- return number of valid |
2022 | chips (which is number of ports/4) */ | 1993 | chips (which is number of ports/4) */ |
@@ -2030,10 +2001,9 @@ show_version(void) | |||
2030 | * ... I wonder what I should do if this fails ... | 2001 | * ... I wonder what I should do if this fails ... |
2031 | */ | 2002 | */ |
2032 | 2003 | ||
2033 | void | 2004 | void mvme167_serial_console_setup(int cflag) |
2034 | mvme167_serial_console_setup(int cflag) | ||
2035 | { | 2005 | { |
2036 | volatile unsigned char* base_addr = (u_char *)BASE_ADDR; | 2006 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; |
2037 | int ch; | 2007 | int ch; |
2038 | u_char spd; | 2008 | u_char spd; |
2039 | u_char rcor, rbpr, badspeed = 0; | 2009 | u_char rcor, rbpr, badspeed = 0; |
@@ -2062,21 +2032,21 @@ mvme167_serial_console_setup(int cflag) | |||
2062 | 2032 | ||
2063 | /* OK, we have chosen a speed, now reset and reinitialise */ | 2033 | /* OK, we have chosen a speed, now reset and reinitialise */ |
2064 | 2034 | ||
2065 | my_udelay(20000L); /* Allow time for any active o/p to complete */ | 2035 | my_udelay(20000L); /* Allow time for any active o/p to complete */ |
2066 | if(base_addr[CyCCR] != 0x00){ | 2036 | if (base_addr[CyCCR] != 0x00) { |
2067 | local_irq_restore(flags); | 2037 | local_irq_restore(flags); |
2068 | /* printk(" chip is never idle (CCR != 0)\n"); */ | 2038 | /* printk(" chip is never idle (CCR != 0)\n"); */ |
2069 | return; | 2039 | return; |
2070 | } | 2040 | } |
2071 | 2041 | ||
2072 | base_addr[CyCCR] = CyCHIP_RESET; /* Reset the chip */ | 2042 | base_addr[CyCCR] = CyCHIP_RESET; /* Reset the chip */ |
2073 | my_udelay(1000L); | 2043 | my_udelay(1000L); |
2074 | 2044 | ||
2075 | if(base_addr[CyGFRCR] == 0x00){ | 2045 | if (base_addr[CyGFRCR] == 0x00) { |
2076 | local_irq_restore(flags); | 2046 | local_irq_restore(flags); |
2077 | /* printk(" chip is not responding (GFRCR stayed 0)\n"); */ | 2047 | /* printk(" chip is not responding (GFRCR stayed 0)\n"); */ |
2078 | return; | 2048 | return; |
2079 | } | 2049 | } |
2080 | 2050 | ||
2081 | /* | 2051 | /* |
2082 | * System clock is 20Mhz, divided by 2048, so divide by 10 for a 1.0ms | 2052 | * System clock is 20Mhz, divided by 2048, so divide by 10 for a 1.0ms |
@@ -2085,9 +2055,9 @@ mvme167_serial_console_setup(int cflag) | |||
2085 | 2055 | ||
2086 | base_addr[CyTPR] = 10; | 2056 | base_addr[CyTPR] = 10; |
2087 | 2057 | ||
2088 | base_addr[CyPILR1] = 0x01; /* Interrupt level for modem change */ | 2058 | base_addr[CyPILR1] = 0x01; /* Interrupt level for modem change */ |
2089 | base_addr[CyPILR2] = 0x02; /* Interrupt level for tx ints */ | 2059 | base_addr[CyPILR2] = 0x02; /* Interrupt level for tx ints */ |
2090 | base_addr[CyPILR3] = 0x03; /* Interrupt level for rx ints */ | 2060 | base_addr[CyPILR3] = 0x03; /* Interrupt level for rx ints */ |
2091 | 2061 | ||
2092 | /* | 2062 | /* |
2093 | * Attempt to set up all channels to something reasonable, and | 2063 | * Attempt to set up all channels to something reasonable, and |
@@ -2095,11 +2065,11 @@ mvme167_serial_console_setup(int cflag) | |||
2095 | * the ammount of fiddling we have to do in normal running. | 2065 | * the ammount of fiddling we have to do in normal running. |
2096 | */ | 2066 | */ |
2097 | 2067 | ||
2098 | for (ch = 3; ch >= 0 ; ch--) { | 2068 | for (ch = 3; ch >= 0; ch--) { |
2099 | base_addr[CyCAR] = (u_char)ch; | 2069 | base_addr[CyCAR] = (u_char) ch; |
2100 | base_addr[CyIER] = 0; | 2070 | base_addr[CyIER] = 0; |
2101 | base_addr[CyCMR] = CyASYNC; | 2071 | base_addr[CyCMR] = CyASYNC; |
2102 | base_addr[CyLICR] = (u_char)ch << 2; | 2072 | base_addr[CyLICR] = (u_char) ch << 2; |
2103 | base_addr[CyLIVR] = 0x5c; | 2073 | base_addr[CyLIVR] = 0x5c; |
2104 | base_addr[CyTCOR] = baud_co[spd]; | 2074 | base_addr[CyTCOR] = baud_co[spd]; |
2105 | base_addr[CyTBPR] = baud_bpr[spd]; | 2075 | base_addr[CyTBPR] = baud_bpr[spd]; |
@@ -2118,29 +2088,30 @@ mvme167_serial_console_setup(int cflag) | |||
2118 | base_addr[CyCOR7] = 0; | 2088 | base_addr[CyCOR7] = 0; |
2119 | base_addr[CyRTPRL] = 2; | 2089 | base_addr[CyRTPRL] = 2; |
2120 | base_addr[CyRTPRH] = 0; | 2090 | base_addr[CyRTPRH] = 0; |
2121 | base_addr[CyMSVR1] = 0; | 2091 | base_addr[CyMSVR1] = 0; |
2122 | base_addr[CyMSVR2] = 0; | 2092 | base_addr[CyMSVR2] = 0; |
2123 | write_cy_cmd(base_addr,CyINIT_CHAN|CyDIS_RCVR|CyDIS_XMTR); | 2093 | write_cy_cmd(base_addr, CyINIT_CHAN | CyDIS_RCVR | CyDIS_XMTR); |
2124 | } | 2094 | } |
2125 | 2095 | ||
2126 | /* | 2096 | /* |
2127 | * Now do specials for channel zero.... | 2097 | * Now do specials for channel zero.... |
2128 | */ | 2098 | */ |
2129 | 2099 | ||
2130 | base_addr[CyMSVR1] = CyRTS; | 2100 | base_addr[CyMSVR1] = CyRTS; |
2131 | base_addr[CyMSVR2] = CyDTR; | 2101 | base_addr[CyMSVR2] = CyDTR; |
2132 | base_addr[CyIER] = CyRxData; | 2102 | base_addr[CyIER] = CyRxData; |
2133 | write_cy_cmd(base_addr,CyENB_RCVR|CyENB_XMTR); | 2103 | write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR); |
2134 | 2104 | ||
2135 | local_irq_restore(flags); | 2105 | local_irq_restore(flags); |
2136 | 2106 | ||
2137 | my_udelay(20000L); /* Let it all settle down */ | 2107 | my_udelay(20000L); /* Let it all settle down */ |
2138 | 2108 | ||
2139 | printk("CD2401 initialised, chip is rev 0x%02x\n", base_addr[CyGFRCR]); | 2109 | printk("CD2401 initialised, chip is rev 0x%02x\n", base_addr[CyGFRCR]); |
2140 | if (badspeed) | 2110 | if (badspeed) |
2141 | printk(" WARNING: Failed to identify line speed, rcor=%02x,rbpr=%02x\n", | 2111 | printk |
2142 | rcor >> 5, rbpr); | 2112 | (" WARNING: Failed to identify line speed, rcor=%02x,rbpr=%02x\n", |
2143 | } /* serial_console_init */ | 2113 | rcor >> 5, rbpr); |
2114 | } /* serial_console_init */ | ||
2144 | 2115 | ||
2145 | static const struct tty_operations cy_ops = { | 2116 | static const struct tty_operations cy_ops = { |
2146 | .open = cy_open, | 2117 | .open = cy_open, |
@@ -2161,6 +2132,7 @@ static const struct tty_operations cy_ops = { | |||
2161 | .tiocmget = cy_tiocmget, | 2132 | .tiocmget = cy_tiocmget, |
2162 | .tiocmset = cy_tiocmset, | 2133 | .tiocmset = cy_tiocmset, |
2163 | }; | 2134 | }; |
2135 | |||
2164 | /* The serial driver boot-time initialization code! | 2136 | /* The serial driver boot-time initialization code! |
2165 | Hardware I/O ports are mapped to character special devices on a | 2137 | Hardware I/O ports are mapped to character special devices on a |
2166 | first found, first allocated manner. That is, this code searches | 2138 | first found, first allocated manner. That is, this code searches |
@@ -2177,214 +2149,214 @@ static const struct tty_operations cy_ops = { | |||
2177 | If there are more cards with more ports than have been statically | 2149 | If there are more cards with more ports than have been statically |
2178 | allocated above, a warning is printed and the extra ports are ignored. | 2150 | allocated above, a warning is printed and the extra ports are ignored. |
2179 | */ | 2151 | */ |
2180 | static int __init | 2152 | static int __init serial167_init(void) |
2181 | serial167_init(void) | ||
2182 | { | 2153 | { |
2183 | struct cyclades_port *info; | 2154 | struct cyclades_port *info; |
2184 | int ret = 0; | 2155 | int ret = 0; |
2185 | int good_ports = 0; | 2156 | int good_ports = 0; |
2186 | int port_num = 0; | 2157 | int port_num = 0; |
2187 | int index; | 2158 | int index; |
2188 | int DefSpeed; | 2159 | int DefSpeed; |
2189 | #ifdef notyet | 2160 | #ifdef notyet |
2190 | struct sigaction sa; | 2161 | struct sigaction sa; |
2191 | #endif | 2162 | #endif |
2192 | 2163 | ||
2193 | if (!(mvme16x_config &MVME16x_CONFIG_GOT_CD2401)) | 2164 | if (!(mvme16x_config & MVME16x_CONFIG_GOT_CD2401)) |
2194 | return 0; | 2165 | return 0; |
2195 | 2166 | ||
2196 | cy_serial_driver = alloc_tty_driver(NR_PORTS); | 2167 | cy_serial_driver = alloc_tty_driver(NR_PORTS); |
2197 | if (!cy_serial_driver) | 2168 | if (!cy_serial_driver) |
2198 | return -ENOMEM; | 2169 | return -ENOMEM; |
2199 | 2170 | ||
2200 | #if 0 | 2171 | #if 0 |
2201 | scrn[1] = '\0'; | 2172 | scrn[1] = '\0'; |
2202 | #endif | 2173 | #endif |
2203 | 2174 | ||
2204 | show_version(); | 2175 | show_version(); |
2205 | 2176 | ||
2206 | /* Has "console=0,9600n8" been used in bootinfo to change speed? */ | 2177 | /* Has "console=0,9600n8" been used in bootinfo to change speed? */ |
2207 | if (serial_console_cflag) | 2178 | if (serial_console_cflag) |
2208 | DefSpeed = serial_console_cflag & 0017; | 2179 | DefSpeed = serial_console_cflag & 0017; |
2209 | else { | 2180 | else { |
2210 | DefSpeed = initial_console_speed; | 2181 | DefSpeed = initial_console_speed; |
2211 | serial_console_info = &cy_port[0]; | 2182 | serial_console_info = &cy_port[0]; |
2212 | serial_console_cflag = DefSpeed | CS8; | 2183 | serial_console_cflag = DefSpeed | CS8; |
2213 | #if 0 | 2184 | #if 0 |
2214 | serial_console = 64; /*callout_driver.minor_start*/ | 2185 | serial_console = 64; /*callout_driver.minor_start */ |
2215 | #endif | 2186 | #endif |
2216 | } | 2187 | } |
2217 | |||
2218 | /* Initialize the tty_driver structure */ | ||
2219 | |||
2220 | cy_serial_driver->owner = THIS_MODULE; | ||
2221 | cy_serial_driver->name = "ttyS"; | ||
2222 | cy_serial_driver->major = TTY_MAJOR; | ||
2223 | cy_serial_driver->minor_start = 64; | ||
2224 | cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL; | ||
2225 | cy_serial_driver->subtype = SERIAL_TYPE_NORMAL; | ||
2226 | cy_serial_driver->init_termios = tty_std_termios; | ||
2227 | cy_serial_driver->init_termios.c_cflag = | ||
2228 | B9600 | CS8 | CREAD | HUPCL | CLOCAL; | ||
2229 | cy_serial_driver->flags = TTY_DRIVER_REAL_RAW; | ||
2230 | tty_set_operations(cy_serial_driver, &cy_ops); | ||
2231 | 2188 | ||
2232 | ret = tty_register_driver(cy_serial_driver); | 2189 | /* Initialize the tty_driver structure */ |
2233 | if (ret) { | ||
2234 | printk(KERN_ERR "Couldn't register MVME166/7 serial driver\n"); | ||
2235 | put_tty_driver(cy_serial_driver); | ||
2236 | return ret; | ||
2237 | } | ||
2238 | 2190 | ||
2239 | port_num = 0; | 2191 | cy_serial_driver->owner = THIS_MODULE; |
2240 | info = cy_port; | 2192 | cy_serial_driver->name = "ttyS"; |
2241 | for (index = 0; index < 1; index++) { | 2193 | cy_serial_driver->major = TTY_MAJOR; |
2194 | cy_serial_driver->minor_start = 64; | ||
2195 | cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL; | ||
2196 | cy_serial_driver->subtype = SERIAL_TYPE_NORMAL; | ||
2197 | cy_serial_driver->init_termios = tty_std_termios; | ||
2198 | cy_serial_driver->init_termios.c_cflag = | ||
2199 | B9600 | CS8 | CREAD | HUPCL | CLOCAL; | ||
2200 | cy_serial_driver->flags = TTY_DRIVER_REAL_RAW; | ||
2201 | tty_set_operations(cy_serial_driver, &cy_ops); | ||
2202 | |||
2203 | ret = tty_register_driver(cy_serial_driver); | ||
2204 | if (ret) { | ||
2205 | printk(KERN_ERR "Couldn't register MVME166/7 serial driver\n"); | ||
2206 | put_tty_driver(cy_serial_driver); | ||
2207 | return ret; | ||
2208 | } | ||
2242 | 2209 | ||
2243 | good_ports = 4; | 2210 | port_num = 0; |
2211 | info = cy_port; | ||
2212 | for (index = 0; index < 1; index++) { | ||
2244 | 2213 | ||
2245 | if(port_num < NR_PORTS){ | 2214 | good_ports = 4; |
2246 | while( good_ports-- && port_num < NR_PORTS){ | 2215 | |
2216 | if (port_num < NR_PORTS) { | ||
2217 | while (good_ports-- && port_num < NR_PORTS) { | ||
2247 | /*** initialize port ***/ | 2218 | /*** initialize port ***/ |
2248 | info->magic = CYCLADES_MAGIC; | 2219 | info->magic = CYCLADES_MAGIC; |
2249 | info->type = PORT_CIRRUS; | 2220 | info->type = PORT_CIRRUS; |
2250 | info->card = index; | 2221 | info->card = index; |
2251 | info->line = port_num; | 2222 | info->line = port_num; |
2252 | info->flags = STD_COM_FLAGS; | 2223 | info->flags = STD_COM_FLAGS; |
2253 | info->tty = NULL; | 2224 | info->tty = NULL; |
2254 | info->xmit_fifo_size = 12; | 2225 | info->xmit_fifo_size = 12; |
2255 | info->cor1 = CyPARITY_NONE|Cy_8_BITS; | 2226 | info->cor1 = CyPARITY_NONE | Cy_8_BITS; |
2256 | info->cor2 = CyETC; | 2227 | info->cor2 = CyETC; |
2257 | info->cor3 = Cy_1_STOP; | 2228 | info->cor3 = Cy_1_STOP; |
2258 | info->cor4 = 0x08; /* _very_ small receive threshold */ | 2229 | info->cor4 = 0x08; /* _very_ small receive threshold */ |
2259 | info->cor5 = 0; | 2230 | info->cor5 = 0; |
2260 | info->cor6 = 0; | 2231 | info->cor6 = 0; |
2261 | info->cor7 = 0; | 2232 | info->cor7 = 0; |
2262 | info->tbpr = baud_bpr[DefSpeed]; /* Tx BPR */ | 2233 | info->tbpr = baud_bpr[DefSpeed]; /* Tx BPR */ |
2263 | info->tco = baud_co[DefSpeed]; /* Tx CO */ | 2234 | info->tco = baud_co[DefSpeed]; /* Tx CO */ |
2264 | info->rbpr = baud_bpr[DefSpeed]; /* Rx BPR */ | 2235 | info->rbpr = baud_bpr[DefSpeed]; /* Rx BPR */ |
2265 | info->rco = baud_co[DefSpeed] >> 5; /* Rx CO */ | 2236 | info->rco = baud_co[DefSpeed] >> 5; /* Rx CO */ |
2266 | info->close_delay = 0; | 2237 | info->close_delay = 0; |
2267 | info->x_char = 0; | 2238 | info->x_char = 0; |
2268 | info->event = 0; | 2239 | info->event = 0; |
2269 | info->count = 0; | 2240 | info->count = 0; |
2270 | #ifdef SERIAL_DEBUG_COUNT | 2241 | #ifdef SERIAL_DEBUG_COUNT |
2271 | printk("cyc: %d: setting count to 0\n", __LINE__); | 2242 | printk("cyc: %d: setting count to 0\n", |
2272 | #endif | 2243 | __LINE__); |
2273 | info->blocked_open = 0; | 2244 | #endif |
2274 | info->default_threshold = 0; | 2245 | info->blocked_open = 0; |
2275 | info->default_timeout = 0; | 2246 | info->default_threshold = 0; |
2276 | INIT_WORK(&info->tqueue, do_softint); | 2247 | info->default_timeout = 0; |
2277 | init_waitqueue_head(&info->open_wait); | 2248 | INIT_WORK(&info->tqueue, do_softint); |
2278 | init_waitqueue_head(&info->close_wait); | 2249 | init_waitqueue_head(&info->open_wait); |
2279 | /* info->session */ | 2250 | init_waitqueue_head(&info->close_wait); |
2280 | /* info->pgrp */ | 2251 | /* info->session */ |
2252 | /* info->pgrp */ | ||
2281 | /*** !!!!!!!! this may expose new bugs !!!!!!!!! *********/ | 2253 | /*** !!!!!!!! this may expose new bugs !!!!!!!!! *********/ |
2282 | info->read_status_mask = CyTIMEOUT| CySPECHAR| CyBREAK | 2254 | info->read_status_mask = |
2283 | | CyPARITY| CyFRAME| CyOVERRUN; | 2255 | CyTIMEOUT | CySPECHAR | CyBREAK | CyPARITY | |
2284 | /* info->timeout */ | 2256 | CyFRAME | CyOVERRUN; |
2285 | 2257 | /* info->timeout */ | |
2286 | printk("ttyS%d ", info->line); | 2258 | |
2287 | port_num++;info++; | 2259 | printk("ttyS%d ", info->line); |
2288 | if(!(port_num & 7)){ | 2260 | port_num++; |
2289 | printk("\n "); | 2261 | info++; |
2262 | if (!(port_num & 7)) { | ||
2263 | printk("\n "); | ||
2264 | } | ||
2265 | } | ||
2290 | } | 2266 | } |
2291 | } | 2267 | printk("\n"); |
2292 | } | 2268 | } |
2293 | printk("\n"); | 2269 | while (port_num < NR_PORTS) { |
2294 | } | 2270 | info->line = -1; |
2295 | while( port_num < NR_PORTS){ | 2271 | port_num++; |
2296 | info->line = -1; | 2272 | info++; |
2297 | port_num++;info++; | 2273 | } |
2298 | } | ||
2299 | #ifdef CONFIG_REMOTE_DEBUG | 2274 | #ifdef CONFIG_REMOTE_DEBUG |
2300 | debug_setup(); | 2275 | debug_setup(); |
2301 | #endif | 2276 | #endif |
2302 | ret = request_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0, | 2277 | ret = request_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0, |
2303 | "cd2401_errors", cd2401_rxerr_interrupt); | 2278 | "cd2401_errors", cd2401_rxerr_interrupt); |
2304 | if (ret) { | 2279 | if (ret) { |
2305 | printk(KERN_ERR "Could't get cd2401_errors IRQ"); | 2280 | printk(KERN_ERR "Could't get cd2401_errors IRQ"); |
2306 | goto cleanup_serial_driver; | 2281 | goto cleanup_serial_driver; |
2307 | } | 2282 | } |
2308 | 2283 | ||
2309 | ret = request_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt, 0, | 2284 | ret = request_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt, 0, |
2310 | "cd2401_modem", cd2401_modem_interrupt); | 2285 | "cd2401_modem", cd2401_modem_interrupt); |
2311 | if (ret) { | 2286 | if (ret) { |
2312 | printk(KERN_ERR "Could't get cd2401_modem IRQ"); | 2287 | printk(KERN_ERR "Could't get cd2401_modem IRQ"); |
2313 | goto cleanup_irq_cd2401_errors; | 2288 | goto cleanup_irq_cd2401_errors; |
2314 | } | 2289 | } |
2315 | 2290 | ||
2316 | ret = request_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt, 0, | 2291 | ret = request_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt, 0, |
2317 | "cd2401_txints", cd2401_tx_interrupt); | 2292 | "cd2401_txints", cd2401_tx_interrupt); |
2318 | if (ret) { | 2293 | if (ret) { |
2319 | printk(KERN_ERR "Could't get cd2401_txints IRQ"); | 2294 | printk(KERN_ERR "Could't get cd2401_txints IRQ"); |
2320 | goto cleanup_irq_cd2401_modem; | 2295 | goto cleanup_irq_cd2401_modem; |
2321 | } | 2296 | } |
2322 | 2297 | ||
2323 | ret = request_irq(MVME167_IRQ_SER_RX, cd2401_rx_interrupt, 0, | 2298 | ret = request_irq(MVME167_IRQ_SER_RX, cd2401_rx_interrupt, 0, |
2324 | "cd2401_rxints", cd2401_rx_interrupt); | 2299 | "cd2401_rxints", cd2401_rx_interrupt); |
2325 | if (ret) { | 2300 | if (ret) { |
2326 | printk(KERN_ERR "Could't get cd2401_rxints IRQ"); | 2301 | printk(KERN_ERR "Could't get cd2401_rxints IRQ"); |
2327 | goto cleanup_irq_cd2401_txints; | 2302 | goto cleanup_irq_cd2401_txints; |
2328 | } | 2303 | } |
2329 | 2304 | ||
2330 | /* Now we have registered the interrupt handlers, allow the interrupts */ | 2305 | /* Now we have registered the interrupt handlers, allow the interrupts */ |
2331 | 2306 | ||
2332 | pcc2chip[PccSCCMICR] = 0x15; /* Serial ints are level 5 */ | 2307 | pcc2chip[PccSCCMICR] = 0x15; /* Serial ints are level 5 */ |
2333 | pcc2chip[PccSCCTICR] = 0x15; | 2308 | pcc2chip[PccSCCTICR] = 0x15; |
2334 | pcc2chip[PccSCCRICR] = 0x15; | 2309 | pcc2chip[PccSCCRICR] = 0x15; |
2335 | 2310 | ||
2336 | pcc2chip[PccIMLR] = 3; /* Allow PCC2 ints above 3!? */ | 2311 | pcc2chip[PccIMLR] = 3; /* Allow PCC2 ints above 3!? */ |
2337 | 2312 | ||
2338 | return 0; | 2313 | return 0; |
2339 | cleanup_irq_cd2401_txints: | 2314 | cleanup_irq_cd2401_txints: |
2340 | free_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt); | 2315 | free_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt); |
2341 | cleanup_irq_cd2401_modem: | 2316 | cleanup_irq_cd2401_modem: |
2342 | free_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt); | 2317 | free_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt); |
2343 | cleanup_irq_cd2401_errors: | 2318 | cleanup_irq_cd2401_errors: |
2344 | free_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt); | 2319 | free_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt); |
2345 | cleanup_serial_driver: | 2320 | cleanup_serial_driver: |
2346 | if (tty_unregister_driver(cy_serial_driver)) | 2321 | if (tty_unregister_driver(cy_serial_driver)) |
2347 | printk(KERN_ERR "Couldn't unregister MVME166/7 serial driver\n"); | 2322 | printk(KERN_ERR |
2348 | put_tty_driver(cy_serial_driver); | 2323 | "Couldn't unregister MVME166/7 serial driver\n"); |
2349 | return ret; | 2324 | put_tty_driver(cy_serial_driver); |
2350 | } /* serial167_init */ | 2325 | return ret; |
2326 | } /* serial167_init */ | ||
2351 | 2327 | ||
2352 | module_init(serial167_init); | 2328 | module_init(serial167_init); |
2353 | 2329 | ||
2354 | |||
2355 | #ifdef CYCLOM_SHOW_STATUS | 2330 | #ifdef CYCLOM_SHOW_STATUS |
2356 | static void | 2331 | static void show_status(int line_num) |
2357 | show_status(int line_num) | ||
2358 | { | 2332 | { |
2359 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; | 2333 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; |
2360 | int channel; | 2334 | int channel; |
2361 | struct cyclades_port * info; | 2335 | struct cyclades_port *info; |
2362 | unsigned long flags; | 2336 | unsigned long flags; |
2363 | 2337 | ||
2364 | info = &cy_port[line_num]; | 2338 | info = &cy_port[line_num]; |
2365 | channel = info->line; | 2339 | channel = info->line; |
2366 | printk(" channel %d\n", channel);/**/ | 2340 | printk(" channel %d\n", channel); |
2367 | 2341 | /**/ printk(" cy_port\n"); | |
2368 | printk(" cy_port\n"); | 2342 | printk(" card line flags = %d %d %x\n", |
2369 | printk(" card line flags = %d %d %x\n", | 2343 | info->card, info->line, info->flags); |
2370 | info->card, info->line, info->flags); | 2344 | printk |
2371 | printk(" *tty read_status_mask timeout xmit_fifo_size = %lx %x %x %x\n", | 2345 | (" *tty read_status_mask timeout xmit_fifo_size = %lx %x %x %x\n", |
2372 | (long)info->tty, info->read_status_mask, | 2346 | (long)info->tty, info->read_status_mask, info->timeout, |
2373 | info->timeout, info->xmit_fifo_size); | 2347 | info->xmit_fifo_size); |
2374 | printk(" cor1,cor2,cor3,cor4,cor5,cor6,cor7 = %x %x %x %x %x %x %x\n", | 2348 | printk(" cor1,cor2,cor3,cor4,cor5,cor6,cor7 = %x %x %x %x %x %x %x\n", |
2375 | info->cor1, info->cor2, info->cor3, info->cor4, info->cor5, | 2349 | info->cor1, info->cor2, info->cor3, info->cor4, info->cor5, |
2376 | info->cor6, info->cor7); | 2350 | info->cor6, info->cor7); |
2377 | printk(" tbpr,tco,rbpr,rco = %d %d %d %d\n", | 2351 | printk(" tbpr,tco,rbpr,rco = %d %d %d %d\n", info->tbpr, info->tco, |
2378 | info->tbpr, info->tco, info->rbpr, info->rco); | 2352 | info->rbpr, info->rco); |
2379 | printk(" close_delay event count = %d %d %d\n", | 2353 | printk(" close_delay event count = %d %d %d\n", info->close_delay, |
2380 | info->close_delay, info->event, info->count); | 2354 | info->event, info->count); |
2381 | printk(" x_char blocked_open = %x %x\n", | 2355 | printk(" x_char blocked_open = %x %x\n", info->x_char, |
2382 | info->x_char, info->blocked_open); | 2356 | info->blocked_open); |
2383 | printk(" open_wait = %lx %lx %lx\n", | 2357 | printk(" open_wait = %lx %lx %lx\n", (long)info->open_wait); |
2384 | (long)info->open_wait); | 2358 | |
2385 | 2359 | local_irq_save(flags); | |
2386 | |||
2387 | local_irq_save(flags); | ||
2388 | 2360 | ||
2389 | /* Global Registers */ | 2361 | /* Global Registers */ |
2390 | 2362 | ||
@@ -2398,7 +2370,7 @@ show_status(int line_num) | |||
2398 | printk(" CyMIR %x\n", base_addr[CyMIR]); | 2370 | printk(" CyMIR %x\n", base_addr[CyMIR]); |
2399 | printk(" CyTPR %x\n", base_addr[CyTPR]); | 2371 | printk(" CyTPR %x\n", base_addr[CyTPR]); |
2400 | 2372 | ||
2401 | base_addr[CyCAR] = (u_char)channel; | 2373 | base_addr[CyCAR] = (u_char) channel; |
2402 | 2374 | ||
2403 | /* Virtual Registers */ | 2375 | /* Virtual Registers */ |
2404 | 2376 | ||
@@ -2442,11 +2414,10 @@ show_status(int line_num) | |||
2442 | printk(" CyTBPR %x\n", base_addr[CyTBPR]); | 2414 | printk(" CyTBPR %x\n", base_addr[CyTBPR]); |
2443 | printk(" CyTCOR %x\n", base_addr[CyTCOR]); | 2415 | printk(" CyTCOR %x\n", base_addr[CyTCOR]); |
2444 | 2416 | ||
2445 | local_irq_restore(flags); | 2417 | local_irq_restore(flags); |
2446 | } /* show_status */ | 2418 | } /* show_status */ |
2447 | #endif | 2419 | #endif |
2448 | 2420 | ||
2449 | |||
2450 | #if 0 | 2421 | #if 0 |
2451 | /* Dummy routine in mvme16x/config.c for now */ | 2422 | /* Dummy routine in mvme16x/config.c for now */ |
2452 | 2423 | ||
@@ -2459,61 +2430,67 @@ void console_setup(char *str, int *ints) | |||
2459 | int cflag = 0; | 2430 | int cflag = 0; |
2460 | 2431 | ||
2461 | /* Sanity check. */ | 2432 | /* Sanity check. */ |
2462 | if (ints[0] > 3 || ints[1] > 3) return; | 2433 | if (ints[0] > 3 || ints[1] > 3) |
2434 | return; | ||
2463 | 2435 | ||
2464 | /* Get baud, bits and parity */ | 2436 | /* Get baud, bits and parity */ |
2465 | baud = 2400; | 2437 | baud = 2400; |
2466 | bits = 8; | 2438 | bits = 8; |
2467 | parity = 'n'; | 2439 | parity = 'n'; |
2468 | if (ints[2]) baud = ints[2]; | 2440 | if (ints[2]) |
2441 | baud = ints[2]; | ||
2469 | if ((s = strchr(str, ','))) { | 2442 | if ((s = strchr(str, ','))) { |
2470 | do { | 2443 | do { |
2471 | s++; | 2444 | s++; |
2472 | } while(*s >= '0' && *s <= '9'); | 2445 | } while (*s >= '0' && *s <= '9'); |
2473 | if (*s) parity = *s++; | 2446 | if (*s) |
2474 | if (*s) bits = *s - '0'; | 2447 | parity = *s++; |
2448 | if (*s) | ||
2449 | bits = *s - '0'; | ||
2475 | } | 2450 | } |
2476 | 2451 | ||
2477 | /* Now construct a cflag setting. */ | 2452 | /* Now construct a cflag setting. */ |
2478 | switch(baud) { | 2453 | switch (baud) { |
2479 | case 1200: | 2454 | case 1200: |
2480 | cflag |= B1200; | 2455 | cflag |= B1200; |
2481 | break; | 2456 | break; |
2482 | case 9600: | 2457 | case 9600: |
2483 | cflag |= B9600; | 2458 | cflag |= B9600; |
2484 | break; | 2459 | break; |
2485 | case 19200: | 2460 | case 19200: |
2486 | cflag |= B19200; | 2461 | cflag |= B19200; |
2487 | break; | 2462 | break; |
2488 | case 38400: | 2463 | case 38400: |
2489 | cflag |= B38400; | 2464 | cflag |= B38400; |
2490 | break; | 2465 | break; |
2491 | case 2400: | 2466 | case 2400: |
2492 | default: | 2467 | default: |
2493 | cflag |= B2400; | 2468 | cflag |= B2400; |
2494 | break; | 2469 | break; |
2495 | } | 2470 | } |
2496 | switch(bits) { | 2471 | switch (bits) { |
2497 | case 7: | 2472 | case 7: |
2498 | cflag |= CS7; | 2473 | cflag |= CS7; |
2499 | break; | 2474 | break; |
2500 | default: | 2475 | default: |
2501 | case 8: | 2476 | case 8: |
2502 | cflag |= CS8; | 2477 | cflag |= CS8; |
2503 | break; | 2478 | break; |
2504 | } | 2479 | } |
2505 | switch(parity) { | 2480 | switch (parity) { |
2506 | case 'o': case 'O': | 2481 | case 'o': |
2507 | cflag |= PARODD; | 2482 | case 'O': |
2508 | break; | 2483 | cflag |= PARODD; |
2509 | case 'e': case 'E': | 2484 | break; |
2510 | cflag |= PARENB; | 2485 | case 'e': |
2511 | break; | 2486 | case 'E': |
2487 | cflag |= PARENB; | ||
2488 | break; | ||
2512 | } | 2489 | } |
2513 | 2490 | ||
2514 | serial_console_info = &cy_port[ints[1]]; | 2491 | serial_console_info = &cy_port[ints[1]]; |
2515 | serial_console_cflag = cflag; | 2492 | serial_console_cflag = cflag; |
2516 | serial_console = ints[1] + 64; /*callout_driver.minor_start*/ | 2493 | serial_console = ints[1] + 64; /*callout_driver.minor_start */ |
2517 | } | 2494 | } |
2518 | #endif | 2495 | #endif |
2519 | 2496 | ||
@@ -2532,9 +2509,10 @@ void console_setup(char *str, int *ints) | |||
2532 | * The console must be locked when we get here. | 2509 | * The console must be locked when we get here. |
2533 | */ | 2510 | */ |
2534 | 2511 | ||
2535 | void serial167_console_write(struct console *co, const char *str, unsigned count) | 2512 | void serial167_console_write(struct console *co, const char *str, |
2513 | unsigned count) | ||
2536 | { | 2514 | { |
2537 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; | 2515 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; |
2538 | unsigned long flags; | 2516 | unsigned long flags; |
2539 | volatile u_char sink; | 2517 | volatile u_char sink; |
2540 | u_char ier; | 2518 | u_char ier; |
@@ -2547,7 +2525,7 @@ void serial167_console_write(struct console *co, const char *str, unsigned count | |||
2547 | /* Ensure transmitter is enabled! */ | 2525 | /* Ensure transmitter is enabled! */ |
2548 | 2526 | ||
2549 | port = 0; | 2527 | port = 0; |
2550 | base_addr[CyCAR] = (u_char)port; | 2528 | base_addr[CyCAR] = (u_char) port; |
2551 | while (base_addr[CyCCR]) | 2529 | while (base_addr[CyCCR]) |
2552 | ; | 2530 | ; |
2553 | base_addr[CyCCR] = CyENB_XMTR; | 2531 | base_addr[CyCCR] = CyENB_XMTR; |
@@ -2556,8 +2534,7 @@ void serial167_console_write(struct console *co, const char *str, unsigned count | |||
2556 | base_addr[CyIER] = CyTxMpty; | 2534 | base_addr[CyIER] = CyTxMpty; |
2557 | 2535 | ||
2558 | while (1) { | 2536 | while (1) { |
2559 | if (pcc2chip[PccSCCTICR] & 0x20) | 2537 | if (pcc2chip[PccSCCTICR] & 0x20) { |
2560 | { | ||
2561 | /* We have a Tx int. Acknowledge it */ | 2538 | /* We have a Tx int. Acknowledge it */ |
2562 | sink = pcc2chip[PccTPIACKR]; | 2539 | sink = pcc2chip[PccTPIACKR]; |
2563 | if ((base_addr[CyLICR] >> 2) == port) { | 2540 | if ((base_addr[CyLICR] >> 2) == port) { |
@@ -2571,18 +2548,15 @@ void serial167_console_write(struct console *co, const char *str, unsigned count | |||
2571 | str++; | 2548 | str++; |
2572 | i++; | 2549 | i++; |
2573 | do_lf = 0; | 2550 | do_lf = 0; |
2574 | } | 2551 | } else if (*str == '\n') { |
2575 | else if (*str == '\n') { | ||
2576 | base_addr[CyTDR] = '\r'; | 2552 | base_addr[CyTDR] = '\r'; |
2577 | do_lf = 1; | 2553 | do_lf = 1; |
2578 | } | 2554 | } else { |
2579 | else { | ||
2580 | base_addr[CyTDR] = *str++; | 2555 | base_addr[CyTDR] = *str++; |
2581 | i++; | 2556 | i++; |
2582 | } | 2557 | } |
2583 | base_addr[CyTEOIR] = 0; | 2558 | base_addr[CyTEOIR] = 0; |
2584 | } | 2559 | } else |
2585 | else | ||
2586 | base_addr[CyTEOIR] = CyNOTRANS; | 2560 | base_addr[CyTEOIR] = CyNOTRANS; |
2587 | } | 2561 | } |
2588 | } | 2562 | } |
@@ -2592,45 +2566,44 @@ void serial167_console_write(struct console *co, const char *str, unsigned count | |||
2592 | local_irq_restore(flags); | 2566 | local_irq_restore(flags); |
2593 | } | 2567 | } |
2594 | 2568 | ||
2595 | static struct tty_driver *serial167_console_device(struct console *c, int *index) | 2569 | static struct tty_driver *serial167_console_device(struct console *c, |
2570 | int *index) | ||
2596 | { | 2571 | { |
2597 | *index = c->index; | 2572 | *index = c->index; |
2598 | return cy_serial_driver; | 2573 | return cy_serial_driver; |
2599 | } | 2574 | } |
2600 | 2575 | ||
2601 | |||
2602 | static int __init serial167_console_setup(struct console *co, char *options) | 2576 | static int __init serial167_console_setup(struct console *co, char *options) |
2603 | { | 2577 | { |
2604 | return 0; | 2578 | return 0; |
2605 | } | 2579 | } |
2606 | 2580 | ||
2607 | |||
2608 | static struct console sercons = { | 2581 | static struct console sercons = { |
2609 | .name = "ttyS", | 2582 | .name = "ttyS", |
2610 | .write = serial167_console_write, | 2583 | .write = serial167_console_write, |
2611 | .device = serial167_console_device, | 2584 | .device = serial167_console_device, |
2612 | .setup = serial167_console_setup, | 2585 | .setup = serial167_console_setup, |
2613 | .flags = CON_PRINTBUFFER, | 2586 | .flags = CON_PRINTBUFFER, |
2614 | .index = -1, | 2587 | .index = -1, |
2615 | }; | 2588 | }; |
2616 | 2589 | ||
2617 | |||
2618 | static int __init serial167_console_init(void) | 2590 | static int __init serial167_console_init(void) |
2619 | { | 2591 | { |
2620 | if (vme_brdtype == VME_TYPE_MVME166 || | 2592 | if (vme_brdtype == VME_TYPE_MVME166 || |
2621 | vme_brdtype == VME_TYPE_MVME167 || | 2593 | vme_brdtype == VME_TYPE_MVME167 || |
2622 | vme_brdtype == VME_TYPE_MVME177) { | 2594 | vme_brdtype == VME_TYPE_MVME177) { |
2623 | mvme167_serial_console_setup(0); | 2595 | mvme167_serial_console_setup(0); |
2624 | register_console(&sercons); | 2596 | register_console(&sercons); |
2625 | } | 2597 | } |
2626 | return 0; | 2598 | return 0; |
2627 | } | 2599 | } |
2600 | |||
2628 | console_initcall(serial167_console_init); | 2601 | console_initcall(serial167_console_init); |
2629 | 2602 | ||
2630 | #ifdef CONFIG_REMOTE_DEBUG | 2603 | #ifdef CONFIG_REMOTE_DEBUG |
2631 | void putDebugChar (int c) | 2604 | void putDebugChar(int c) |
2632 | { | 2605 | { |
2633 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; | 2606 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; |
2634 | unsigned long flags; | 2607 | unsigned long flags; |
2635 | volatile u_char sink; | 2608 | volatile u_char sink; |
2636 | u_char ier; | 2609 | u_char ier; |
@@ -2641,7 +2614,7 @@ void putDebugChar (int c) | |||
2641 | /* Ensure transmitter is enabled! */ | 2614 | /* Ensure transmitter is enabled! */ |
2642 | 2615 | ||
2643 | port = DEBUG_PORT; | 2616 | port = DEBUG_PORT; |
2644 | base_addr[CyCAR] = (u_char)port; | 2617 | base_addr[CyCAR] = (u_char) port; |
2645 | while (base_addr[CyCCR]) | 2618 | while (base_addr[CyCCR]) |
2646 | ; | 2619 | ; |
2647 | base_addr[CyCCR] = CyENB_XMTR; | 2620 | base_addr[CyCCR] = CyENB_XMTR; |
@@ -2650,16 +2623,14 @@ void putDebugChar (int c) | |||
2650 | base_addr[CyIER] = CyTxMpty; | 2623 | base_addr[CyIER] = CyTxMpty; |
2651 | 2624 | ||
2652 | while (1) { | 2625 | while (1) { |
2653 | if (pcc2chip[PccSCCTICR] & 0x20) | 2626 | if (pcc2chip[PccSCCTICR] & 0x20) { |
2654 | { | ||
2655 | /* We have a Tx int. Acknowledge it */ | 2627 | /* We have a Tx int. Acknowledge it */ |
2656 | sink = pcc2chip[PccTPIACKR]; | 2628 | sink = pcc2chip[PccTPIACKR]; |
2657 | if ((base_addr[CyLICR] >> 2) == port) { | 2629 | if ((base_addr[CyLICR] >> 2) == port) { |
2658 | base_addr[CyTDR] = c; | 2630 | base_addr[CyTDR] = c; |
2659 | base_addr[CyTEOIR] = 0; | 2631 | base_addr[CyTEOIR] = 0; |
2660 | break; | 2632 | break; |
2661 | } | 2633 | } else |
2662 | else | ||
2663 | base_addr[CyTEOIR] = CyNOTRANS; | 2634 | base_addr[CyTEOIR] = CyNOTRANS; |
2664 | } | 2635 | } |
2665 | } | 2636 | } |
@@ -2671,7 +2642,7 @@ void putDebugChar (int c) | |||
2671 | 2642 | ||
2672 | int getDebugChar() | 2643 | int getDebugChar() |
2673 | { | 2644 | { |
2674 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; | 2645 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; |
2675 | unsigned long flags; | 2646 | unsigned long flags; |
2676 | volatile u_char sink; | 2647 | volatile u_char sink; |
2677 | u_char ier; | 2648 | u_char ier; |
@@ -2693,7 +2664,7 @@ int getDebugChar() | |||
2693 | /* Ensure receiver is enabled! */ | 2664 | /* Ensure receiver is enabled! */ |
2694 | 2665 | ||
2695 | port = DEBUG_PORT; | 2666 | port = DEBUG_PORT; |
2696 | base_addr[CyCAR] = (u_char)port; | 2667 | base_addr[CyCAR] = (u_char) port; |
2697 | #if 0 | 2668 | #if 0 |
2698 | while (base_addr[CyCCR]) | 2669 | while (base_addr[CyCCR]) |
2699 | ; | 2670 | ; |
@@ -2703,31 +2674,30 @@ int getDebugChar() | |||
2703 | base_addr[CyIER] = CyRxData; | 2674 | base_addr[CyIER] = CyRxData; |
2704 | 2675 | ||
2705 | while (1) { | 2676 | while (1) { |
2706 | if (pcc2chip[PccSCCRICR] & 0x20) | 2677 | if (pcc2chip[PccSCCRICR] & 0x20) { |
2707 | { | ||
2708 | /* We have a Rx int. Acknowledge it */ | 2678 | /* We have a Rx int. Acknowledge it */ |
2709 | sink = pcc2chip[PccRPIACKR]; | 2679 | sink = pcc2chip[PccRPIACKR]; |
2710 | if ((base_addr[CyLICR] >> 2) == port) { | 2680 | if ((base_addr[CyLICR] >> 2) == port) { |
2711 | int cnt = base_addr[CyRFOC]; | 2681 | int cnt = base_addr[CyRFOC]; |
2712 | while (cnt-- > 0) | 2682 | while (cnt-- > 0) { |
2713 | { | ||
2714 | c = base_addr[CyRDR]; | 2683 | c = base_addr[CyRDR]; |
2715 | if (c == 0) | 2684 | if (c == 0) |
2716 | printk ("!! debug char is null (cnt=%d) !!", cnt); | 2685 | printk |
2686 | ("!! debug char is null (cnt=%d) !!", | ||
2687 | cnt); | ||
2717 | else | 2688 | else |
2718 | queueDebugChar (c); | 2689 | queueDebugChar(c); |
2719 | } | 2690 | } |
2720 | base_addr[CyREOIR] = 0; | 2691 | base_addr[CyREOIR] = 0; |
2721 | i = debugiq.out; | 2692 | i = debugiq.out; |
2722 | if (i == debugiq.in) | 2693 | if (i == debugiq.in) |
2723 | panic ("Debug input queue empty!"); | 2694 | panic("Debug input queue empty!"); |
2724 | c = debugiq.buf[i]; | 2695 | c = debugiq.buf[i]; |
2725 | if (++i == DEBUG_LEN) | 2696 | if (++i == DEBUG_LEN) |
2726 | i = 0; | 2697 | i = 0; |
2727 | debugiq.out = i; | 2698 | debugiq.out = i; |
2728 | break; | 2699 | break; |
2729 | } | 2700 | } else |
2730 | else | ||
2731 | base_addr[CyREOIR] = CyNOTRANS; | 2701 | base_addr[CyREOIR] = CyNOTRANS; |
2732 | } | 2702 | } |
2733 | } | 2703 | } |
@@ -2739,7 +2709,7 @@ int getDebugChar() | |||
2739 | return (c); | 2709 | return (c); |
2740 | } | 2710 | } |
2741 | 2711 | ||
2742 | void queueDebugChar (int c) | 2712 | void queueDebugChar(int c) |
2743 | { | 2713 | { |
2744 | int i; | 2714 | int i; |
2745 | 2715 | ||
@@ -2751,73 +2721,71 @@ void queueDebugChar (int c) | |||
2751 | debugiq.in = i; | 2721 | debugiq.in = i; |
2752 | } | 2722 | } |
2753 | 2723 | ||
2754 | static void | 2724 | static void debug_setup() |
2755 | debug_setup() | ||
2756 | { | 2725 | { |
2757 | unsigned long flags; | 2726 | unsigned long flags; |
2758 | volatile unsigned char *base_addr = (u_char *)BASE_ADDR; | 2727 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; |
2759 | int i, cflag; | 2728 | int i, cflag; |
2760 | 2729 | ||
2761 | cflag = B19200; | 2730 | cflag = B19200; |
2762 | 2731 | ||
2763 | local_irq_save(flags); | 2732 | local_irq_save(flags); |
2764 | 2733 | ||
2765 | for (i = 0; i < 4; i++) | 2734 | for (i = 0; i < 4; i++) { |
2766 | { | 2735 | base_addr[CyCAR] = i; |
2767 | base_addr[CyCAR] = i; | 2736 | base_addr[CyLICR] = i << 2; |
2768 | base_addr[CyLICR] = i << 2; | 2737 | } |
2769 | } | ||
2770 | 2738 | ||
2771 | debugiq.in = debugiq.out = 0; | 2739 | debugiq.in = debugiq.out = 0; |
2772 | 2740 | ||
2773 | base_addr[CyCAR] = DEBUG_PORT; | 2741 | base_addr[CyCAR] = DEBUG_PORT; |
2774 | 2742 | ||
2775 | /* baud rate */ | 2743 | /* baud rate */ |
2776 | i = cflag & CBAUD; | 2744 | i = cflag & CBAUD; |
2777 | 2745 | ||
2778 | base_addr[CyIER] = 0; | 2746 | base_addr[CyIER] = 0; |
2779 | 2747 | ||
2780 | base_addr[CyCMR] = CyASYNC; | 2748 | base_addr[CyCMR] = CyASYNC; |
2781 | base_addr[CyLICR] = DEBUG_PORT << 2; | 2749 | base_addr[CyLICR] = DEBUG_PORT << 2; |
2782 | base_addr[CyLIVR] = 0x5c; | 2750 | base_addr[CyLIVR] = 0x5c; |
2783 | 2751 | ||
2784 | /* tx and rx baud rate */ | 2752 | /* tx and rx baud rate */ |
2785 | 2753 | ||
2786 | base_addr[CyTCOR] = baud_co[i]; | 2754 | base_addr[CyTCOR] = baud_co[i]; |
2787 | base_addr[CyTBPR] = baud_bpr[i]; | 2755 | base_addr[CyTBPR] = baud_bpr[i]; |
2788 | base_addr[CyRCOR] = baud_co[i] >> 5; | 2756 | base_addr[CyRCOR] = baud_co[i] >> 5; |
2789 | base_addr[CyRBPR] = baud_bpr[i]; | 2757 | base_addr[CyRBPR] = baud_bpr[i]; |
2790 | 2758 | ||
2791 | /* set line characteristics according configuration */ | 2759 | /* set line characteristics according configuration */ |
2792 | 2760 | ||
2793 | base_addr[CySCHR1] = 0; | 2761 | base_addr[CySCHR1] = 0; |
2794 | base_addr[CySCHR2] = 0; | 2762 | base_addr[CySCHR2] = 0; |
2795 | base_addr[CySCRL] = 0; | 2763 | base_addr[CySCRL] = 0; |
2796 | base_addr[CySCRH] = 0; | 2764 | base_addr[CySCRH] = 0; |
2797 | base_addr[CyCOR1] = Cy_8_BITS | CyPARITY_NONE; | 2765 | base_addr[CyCOR1] = Cy_8_BITS | CyPARITY_NONE; |
2798 | base_addr[CyCOR2] = 0; | 2766 | base_addr[CyCOR2] = 0; |
2799 | base_addr[CyCOR3] = Cy_1_STOP; | 2767 | base_addr[CyCOR3] = Cy_1_STOP; |
2800 | base_addr[CyCOR4] = baud_cor4[i]; | 2768 | base_addr[CyCOR4] = baud_cor4[i]; |
2801 | base_addr[CyCOR5] = 0; | 2769 | base_addr[CyCOR5] = 0; |
2802 | base_addr[CyCOR6] = 0; | 2770 | base_addr[CyCOR6] = 0; |
2803 | base_addr[CyCOR7] = 0; | 2771 | base_addr[CyCOR7] = 0; |
2804 | 2772 | ||
2805 | write_cy_cmd(base_addr,CyINIT_CHAN); | 2773 | write_cy_cmd(base_addr, CyINIT_CHAN); |
2806 | write_cy_cmd(base_addr,CyENB_RCVR); | 2774 | write_cy_cmd(base_addr, CyENB_RCVR); |
2807 | 2775 | ||
2808 | base_addr[CyCAR] = DEBUG_PORT; /* !!! Is this needed? */ | 2776 | base_addr[CyCAR] = DEBUG_PORT; /* !!! Is this needed? */ |
2809 | 2777 | ||
2810 | base_addr[CyRTPRL] = 2; | 2778 | base_addr[CyRTPRL] = 2; |
2811 | base_addr[CyRTPRH] = 0; | 2779 | base_addr[CyRTPRH] = 0; |
2812 | 2780 | ||
2813 | base_addr[CyMSVR1] = CyRTS; | 2781 | base_addr[CyMSVR1] = CyRTS; |
2814 | base_addr[CyMSVR2] = CyDTR; | 2782 | base_addr[CyMSVR2] = CyDTR; |
2815 | 2783 | ||
2816 | base_addr[CyIER] = CyRxData; | 2784 | base_addr[CyIER] = CyRxData; |
2817 | 2785 | ||
2818 | local_irq_restore(flags); | 2786 | local_irq_restore(flags); |
2819 | 2787 | ||
2820 | } /* debug_setup */ | 2788 | } /* debug_setup */ |
2821 | 2789 | ||
2822 | #endif | 2790 | #endif |
2823 | 2791 | ||
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 20946f5127e0..baf7234b6e66 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c | |||
@@ -459,10 +459,9 @@ void missed_irq (unsigned long data) | |||
459 | if (irq) { | 459 | if (irq) { |
460 | printk (KERN_INFO "Missed interrupt... Calling int from timer. \n"); | 460 | printk (KERN_INFO "Missed interrupt... Calling int from timer. \n"); |
461 | sx_interrupt (((struct specialix_board *)data)->irq, | 461 | sx_interrupt (((struct specialix_board *)data)->irq, |
462 | (void*)data, NULL); | 462 | (void*)data); |
463 | } | 463 | } |
464 | missed_irq_timer.expires = jiffies + sx_poll; | 464 | mod_timer(&missed_irq_timer, jiffies + sx_poll); |
465 | add_timer (&missed_irq_timer); | ||
466 | } | 465 | } |
467 | #endif | 466 | #endif |
468 | 467 | ||
@@ -597,11 +596,8 @@ static int sx_probe(struct specialix_board *bp) | |||
597 | dprintk (SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR) ); | 596 | dprintk (SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR) ); |
598 | 597 | ||
599 | #ifdef SPECIALIX_TIMER | 598 | #ifdef SPECIALIX_TIMER |
600 | init_timer (&missed_irq_timer); | 599 | setup_timer(&missed_irq_timer, missed_irq, (unsigned long)bp); |
601 | missed_irq_timer.function = missed_irq; | 600 | mod_timer(&missed_irq_timer, jiffies + sx_poll); |
602 | missed_irq_timer.data = (unsigned long) bp; | ||
603 | missed_irq_timer.expires = jiffies + sx_poll; | ||
604 | add_timer (&missed_irq_timer); | ||
605 | #endif | 601 | #endif |
606 | 602 | ||
607 | printk(KERN_INFO"sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n", | 603 | printk(KERN_INFO"sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n", |
@@ -2350,10 +2346,8 @@ static void do_softint(struct work_struct *work) | |||
2350 | return; | 2346 | return; |
2351 | } | 2347 | } |
2352 | 2348 | ||
2353 | if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) { | 2349 | if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) |
2354 | tty_wakeup(tty); | 2350 | tty_wakeup(tty); |
2355 | //wake_up_interruptible(&tty->write_wait); | ||
2356 | } | ||
2357 | 2351 | ||
2358 | func_exit(); | 2352 | func_exit(); |
2359 | } | 2353 | } |
@@ -2561,7 +2555,7 @@ static void __exit specialix_exit_module(void) | |||
2561 | if (sx_board[i].flags & SX_BOARD_PRESENT) | 2555 | if (sx_board[i].flags & SX_BOARD_PRESENT) |
2562 | sx_release_io_range(&sx_board[i]); | 2556 | sx_release_io_range(&sx_board[i]); |
2563 | #ifdef SPECIALIX_TIMER | 2557 | #ifdef SPECIALIX_TIMER |
2564 | del_timer (&missed_irq_timer); | 2558 | del_timer_sync(&missed_irq_timer); |
2565 | #endif | 2559 | #endif |
2566 | 2560 | ||
2567 | func_exit(); | 2561 | func_exit(); |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 3fa625db9e4b..ce4db6f52362 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -1148,10 +1148,8 @@ static void mgsl_bh_transmit(struct mgsl_struct *info) | |||
1148 | printk( "%s(%d):mgsl_bh_transmit() entry on %s\n", | 1148 | printk( "%s(%d):mgsl_bh_transmit() entry on %s\n", |
1149 | __FILE__,__LINE__,info->device_name); | 1149 | __FILE__,__LINE__,info->device_name); |
1150 | 1150 | ||
1151 | if (tty) { | 1151 | if (tty) |
1152 | tty_wakeup(tty); | 1152 | tty_wakeup(tty); |
1153 | wake_up_interruptible(&tty->write_wait); | ||
1154 | } | ||
1155 | 1153 | ||
1156 | /* if transmitter idle and loopmode_send_done_requested | 1154 | /* if transmitter idle and loopmode_send_done_requested |
1157 | * then start echoing RxD to TxD | 1155 | * then start echoing RxD to TxD |
@@ -1800,9 +1798,7 @@ static int startup(struct mgsl_struct * info) | |||
1800 | 1798 | ||
1801 | memset(&info->icount, 0, sizeof(info->icount)); | 1799 | memset(&info->icount, 0, sizeof(info->icount)); |
1802 | 1800 | ||
1803 | init_timer(&info->tx_timer); | 1801 | setup_timer(&info->tx_timer, mgsl_tx_timeout, (unsigned long)info); |
1804 | info->tx_timer.data = (unsigned long)info; | ||
1805 | info->tx_timer.function = mgsl_tx_timeout; | ||
1806 | 1802 | ||
1807 | /* Allocate and claim adapter resources */ | 1803 | /* Allocate and claim adapter resources */ |
1808 | retval = mgsl_claim_resources(info); | 1804 | retval = mgsl_claim_resources(info); |
@@ -1853,7 +1849,7 @@ static void shutdown(struct mgsl_struct * info) | |||
1853 | wake_up_interruptible(&info->status_event_wait_q); | 1849 | wake_up_interruptible(&info->status_event_wait_q); |
1854 | wake_up_interruptible(&info->event_wait_q); | 1850 | wake_up_interruptible(&info->event_wait_q); |
1855 | 1851 | ||
1856 | del_timer(&info->tx_timer); | 1852 | del_timer_sync(&info->tx_timer); |
1857 | 1853 | ||
1858 | if (info->xmit_buf) { | 1854 | if (info->xmit_buf) { |
1859 | free_page((unsigned long) info->xmit_buf); | 1855 | free_page((unsigned long) info->xmit_buf); |
@@ -2340,7 +2336,6 @@ static void mgsl_flush_buffer(struct tty_struct *tty) | |||
2340 | del_timer(&info->tx_timer); | 2336 | del_timer(&info->tx_timer); |
2341 | spin_unlock_irqrestore(&info->irq_spinlock,flags); | 2337 | spin_unlock_irqrestore(&info->irq_spinlock,flags); |
2342 | 2338 | ||
2343 | wake_up_interruptible(&tty->write_wait); | ||
2344 | tty_wakeup(tty); | 2339 | tty_wakeup(tty); |
2345 | } | 2340 | } |
2346 | 2341 | ||
@@ -5713,8 +5708,8 @@ static void usc_start_transmitter( struct mgsl_struct *info ) | |||
5713 | 5708 | ||
5714 | usc_TCmd( info, TCmd_SendFrame ); | 5709 | usc_TCmd( info, TCmd_SendFrame ); |
5715 | 5710 | ||
5716 | info->tx_timer.expires = jiffies + msecs_to_jiffies(5000); | 5711 | mod_timer(&info->tx_timer, jiffies + |
5717 | add_timer(&info->tx_timer); | 5712 | msecs_to_jiffies(5000)); |
5718 | } | 5713 | } |
5719 | info->tx_active = 1; | 5714 | info->tx_active = 1; |
5720 | } | 5715 | } |
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 792c79c315e0..0a367cd4121f 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -1045,7 +1045,6 @@ static void flush_buffer(struct tty_struct *tty) | |||
1045 | info->tx_count = 0; | 1045 | info->tx_count = 0; |
1046 | spin_unlock_irqrestore(&info->lock,flags); | 1046 | spin_unlock_irqrestore(&info->lock,flags); |
1047 | 1047 | ||
1048 | wake_up_interruptible(&tty->write_wait); | ||
1049 | tty_wakeup(tty); | 1048 | tty_wakeup(tty); |
1050 | } | 1049 | } |
1051 | 1050 | ||
@@ -1826,8 +1825,7 @@ static void rx_async(struct slgt_info *info) | |||
1826 | if (i < count) { | 1825 | if (i < count) { |
1827 | /* receive buffer not completed */ | 1826 | /* receive buffer not completed */ |
1828 | info->rbuf_index += i; | 1827 | info->rbuf_index += i; |
1829 | info->rx_timer.expires = jiffies + 1; | 1828 | mod_timer(&info->rx_timer, jiffies + 1); |
1830 | add_timer(&info->rx_timer); | ||
1831 | break; | 1829 | break; |
1832 | } | 1830 | } |
1833 | 1831 | ||
@@ -1933,10 +1931,8 @@ static void bh_transmit(struct slgt_info *info) | |||
1933 | struct tty_struct *tty = info->tty; | 1931 | struct tty_struct *tty = info->tty; |
1934 | 1932 | ||
1935 | DBGBH(("%s bh_transmit\n", info->device_name)); | 1933 | DBGBH(("%s bh_transmit\n", info->device_name)); |
1936 | if (tty) { | 1934 | if (tty) |
1937 | tty_wakeup(tty); | 1935 | tty_wakeup(tty); |
1938 | wake_up_interruptible(&tty->write_wait); | ||
1939 | } | ||
1940 | } | 1936 | } |
1941 | 1937 | ||
1942 | static void dsr_change(struct slgt_info *info) | 1938 | static void dsr_change(struct slgt_info *info) |
@@ -3343,13 +3339,8 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev | |||
3343 | info->adapter_num = adapter_num; | 3339 | info->adapter_num = adapter_num; |
3344 | info->port_num = port_num; | 3340 | info->port_num = port_num; |
3345 | 3341 | ||
3346 | init_timer(&info->tx_timer); | 3342 | setup_timer(&info->tx_timer, tx_timeout, (unsigned long)info); |
3347 | info->tx_timer.data = (unsigned long)info; | 3343 | setup_timer(&info->rx_timer, rx_timeout, (unsigned long)info); |
3348 | info->tx_timer.function = tx_timeout; | ||
3349 | |||
3350 | init_timer(&info->rx_timer); | ||
3351 | info->rx_timer.data = (unsigned long)info; | ||
3352 | info->rx_timer.function = rx_timeout; | ||
3353 | 3344 | ||
3354 | /* Copy configuration info to device instance data */ | 3345 | /* Copy configuration info to device instance data */ |
3355 | info->pdev = pdev; | 3346 | info->pdev = pdev; |
@@ -3797,10 +3788,9 @@ static void tx_start(struct slgt_info *info) | |||
3797 | } | 3788 | } |
3798 | } | 3789 | } |
3799 | 3790 | ||
3800 | if (info->params.mode == MGSL_MODE_HDLC) { | 3791 | if (info->params.mode == MGSL_MODE_HDLC) |
3801 | info->tx_timer.expires = jiffies + msecs_to_jiffies(5000); | 3792 | mod_timer(&info->tx_timer, jiffies + |
3802 | add_timer(&info->tx_timer); | 3793 | msecs_to_jiffies(5000)); |
3803 | } | ||
3804 | } else { | 3794 | } else { |
3805 | tdma_reset(info); | 3795 | tdma_reset(info); |
3806 | /* set 1st descriptor address */ | 3796 | /* set 1st descriptor address */ |
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 8f4d67afe5bf..ef93d055bdd7 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c | |||
@@ -1258,7 +1258,6 @@ static void flush_buffer(struct tty_struct *tty) | |||
1258 | del_timer(&info->tx_timer); | 1258 | del_timer(&info->tx_timer); |
1259 | spin_unlock_irqrestore(&info->lock,flags); | 1259 | spin_unlock_irqrestore(&info->lock,flags); |
1260 | 1260 | ||
1261 | wake_up_interruptible(&tty->write_wait); | ||
1262 | tty_wakeup(tty); | 1261 | tty_wakeup(tty); |
1263 | } | 1262 | } |
1264 | 1263 | ||
@@ -2127,10 +2126,8 @@ void bh_transmit(SLMP_INFO *info) | |||
2127 | printk( "%s(%d):%s bh_transmit() entry\n", | 2126 | printk( "%s(%d):%s bh_transmit() entry\n", |
2128 | __FILE__,__LINE__,info->device_name); | 2127 | __FILE__,__LINE__,info->device_name); |
2129 | 2128 | ||
2130 | if (tty) { | 2129 | if (tty) |
2131 | tty_wakeup(tty); | 2130 | tty_wakeup(tty); |
2132 | wake_up_interruptible(&tty->write_wait); | ||
2133 | } | ||
2134 | } | 2131 | } |
2135 | 2132 | ||
2136 | void bh_status(SLMP_INFO *info) | 2133 | void bh_status(SLMP_INFO *info) |
@@ -2747,8 +2744,7 @@ static int startup(SLMP_INFO * info) | |||
2747 | 2744 | ||
2748 | change_params(info); | 2745 | change_params(info); |
2749 | 2746 | ||
2750 | info->status_timer.expires = jiffies + msecs_to_jiffies(10); | 2747 | mod_timer(&info->status_timer, jiffies + msecs_to_jiffies(10)); |
2751 | add_timer(&info->status_timer); | ||
2752 | 2748 | ||
2753 | if (info->tty) | 2749 | if (info->tty) |
2754 | clear_bit(TTY_IO_ERROR, &info->tty->flags); | 2750 | clear_bit(TTY_IO_ERROR, &info->tty->flags); |
@@ -3844,13 +3840,9 @@ static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev) | |||
3844 | info->bus_type = MGSL_BUS_TYPE_PCI; | 3840 | info->bus_type = MGSL_BUS_TYPE_PCI; |
3845 | info->irq_flags = IRQF_SHARED; | 3841 | info->irq_flags = IRQF_SHARED; |
3846 | 3842 | ||
3847 | init_timer(&info->tx_timer); | 3843 | setup_timer(&info->tx_timer, tx_timeout, (unsigned long)info); |
3848 | info->tx_timer.data = (unsigned long)info; | 3844 | setup_timer(&info->status_timer, status_timeout, |
3849 | info->tx_timer.function = tx_timeout; | 3845 | (unsigned long)info); |
3850 | |||
3851 | init_timer(&info->status_timer); | ||
3852 | info->status_timer.data = (unsigned long)info; | ||
3853 | info->status_timer.function = status_timeout; | ||
3854 | 3846 | ||
3855 | /* Store the PCI9050 misc control register value because a flaw | 3847 | /* Store the PCI9050 misc control register value because a flaw |
3856 | * in the PCI9050 prevents LCR registers from being read if | 3848 | * in the PCI9050 prevents LCR registers from being read if |
@@ -4294,8 +4286,8 @@ void tx_start(SLMP_INFO *info) | |||
4294 | write_reg(info, TXDMA + DIR, 0x40); /* enable Tx DMA interrupts (EOM) */ | 4286 | write_reg(info, TXDMA + DIR, 0x40); /* enable Tx DMA interrupts (EOM) */ |
4295 | write_reg(info, TXDMA + DSR, 0xf2); /* clear Tx DMA IRQs, enable Tx DMA */ | 4287 | write_reg(info, TXDMA + DSR, 0xf2); /* clear Tx DMA IRQs, enable Tx DMA */ |
4296 | 4288 | ||
4297 | info->tx_timer.expires = jiffies + msecs_to_jiffies(5000); | 4289 | mod_timer(&info->tx_timer, jiffies + |
4298 | add_timer(&info->tx_timer); | 4290 | msecs_to_jiffies(5000)); |
4299 | } | 4291 | } |
4300 | else { | 4292 | else { |
4301 | tx_load_fifo(info); | 4293 | tx_load_fifo(info); |
@@ -5577,10 +5569,7 @@ void status_timeout(unsigned long context) | |||
5577 | if (status) | 5569 | if (status) |
5578 | isr_io_pin(info,status); | 5570 | isr_io_pin(info,status); |
5579 | 5571 | ||
5580 | info->status_timer.data = (unsigned long)info; | 5572 | mod_timer(&info->status_timer, jiffies + msecs_to_jiffies(10)); |
5581 | info->status_timer.function = status_timeout; | ||
5582 | info->status_timer.expires = jiffies + msecs_to_jiffies(10); | ||
5583 | add_timer(&info->status_timer); | ||
5584 | } | 5573 | } |
5585 | 5574 | ||
5586 | 5575 | ||
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 7fd3cd5ddf21..3757610b7835 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c | |||
@@ -88,9 +88,9 @@ static struct sysrq_key_op sysrq_loglevel_op = { | |||
88 | #ifdef CONFIG_VT | 88 | #ifdef CONFIG_VT |
89 | static void sysrq_handle_SAK(int key, struct tty_struct *tty) | 89 | static void sysrq_handle_SAK(int key, struct tty_struct *tty) |
90 | { | 90 | { |
91 | if (tty) | 91 | struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work; |
92 | do_SAK(tty); | 92 | PREPARE_WORK(SAK_work, vc_SAK); |
93 | reset_vc(vc_cons[fg_console].d); | 93 | schedule_work(SAK_work); |
94 | } | 94 | } |
95 | static struct sysrq_key_op sysrq_SAK_op = { | 95 | static struct sysrq_key_op sysrq_SAK_op = { |
96 | .handler = sysrq_handle_SAK, | 96 | .handler = sysrq_handle_SAK, |
diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c index 07067c31c4ec..c346ec5a3dc9 100644 --- a/drivers/char/toshiba.c +++ b/drivers/char/toshiba.c | |||
@@ -68,6 +68,7 @@ | |||
68 | #include <linux/init.h> | 68 | #include <linux/init.h> |
69 | #include <linux/stat.h> | 69 | #include <linux/stat.h> |
70 | #include <linux/proc_fs.h> | 70 | #include <linux/proc_fs.h> |
71 | #include <linux/seq_file.h> | ||
71 | 72 | ||
72 | #include <linux/toshiba.h> | 73 | #include <linux/toshiba.h> |
73 | 74 | ||
@@ -298,12 +299,10 @@ static int tosh_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, | |||
298 | * Print the information for /proc/toshiba | 299 | * Print the information for /proc/toshiba |
299 | */ | 300 | */ |
300 | #ifdef CONFIG_PROC_FS | 301 | #ifdef CONFIG_PROC_FS |
301 | static int tosh_get_info(char *buffer, char **start, off_t fpos, int length) | 302 | static int proc_toshiba_show(struct seq_file *m, void *v) |
302 | { | 303 | { |
303 | char *temp; | ||
304 | int key; | 304 | int key; |
305 | 305 | ||
306 | temp = buffer; | ||
307 | key = tosh_fn_status(); | 306 | key = tosh_fn_status(); |
308 | 307 | ||
309 | /* Arguments | 308 | /* Arguments |
@@ -314,8 +313,7 @@ static int tosh_get_info(char *buffer, char **start, off_t fpos, int length) | |||
314 | 4) BIOS date (in SCI date format) | 313 | 4) BIOS date (in SCI date format) |
315 | 5) Fn Key status | 314 | 5) Fn Key status |
316 | */ | 315 | */ |
317 | 316 | seq_printf(m, "1.1 0x%04x %d.%d %d.%d 0x%04x 0x%02x\n", | |
318 | temp += sprintf(temp, "1.1 0x%04x %d.%d %d.%d 0x%04x 0x%02x\n", | ||
319 | tosh_id, | 317 | tosh_id, |
320 | (tosh_sci & 0xff00)>>8, | 318 | (tosh_sci & 0xff00)>>8, |
321 | tosh_sci & 0xff, | 319 | tosh_sci & 0xff, |
@@ -323,9 +321,21 @@ static int tosh_get_info(char *buffer, char **start, off_t fpos, int length) | |||
323 | tosh_bios & 0xff, | 321 | tosh_bios & 0xff, |
324 | tosh_date, | 322 | tosh_date, |
325 | key); | 323 | key); |
324 | return 0; | ||
325 | } | ||
326 | 326 | ||
327 | return temp-buffer; | 327 | static int proc_toshiba_open(struct inode *inode, struct file *file) |
328 | { | ||
329 | return single_open(file, proc_toshiba_show, NULL); | ||
328 | } | 330 | } |
331 | |||
332 | static const struct file_operations proc_toshiba_fops = { | ||
333 | .owner = THIS_MODULE, | ||
334 | .open = proc_toshiba_open, | ||
335 | .read = seq_read, | ||
336 | .llseek = seq_lseek, | ||
337 | .release = single_release, | ||
338 | }; | ||
329 | #endif | 339 | #endif |
330 | 340 | ||
331 | 341 | ||
@@ -508,10 +518,15 @@ static int __init toshiba_init(void) | |||
508 | return retval; | 518 | return retval; |
509 | 519 | ||
510 | #ifdef CONFIG_PROC_FS | 520 | #ifdef CONFIG_PROC_FS |
511 | /* register the proc entry */ | 521 | { |
512 | if (create_proc_info_entry("toshiba", 0, NULL, tosh_get_info) == NULL) { | 522 | struct proc_dir_entry *pde; |
513 | misc_deregister(&tosh_device); | 523 | |
514 | return -ENOMEM; | 524 | pde = create_proc_entry("toshiba", 0, NULL); |
525 | if (!pde) { | ||
526 | misc_deregister(&tosh_device); | ||
527 | return -ENOMEM; | ||
528 | } | ||
529 | pde->proc_fops = &proc_toshiba_fops; | ||
515 | } | 530 | } |
516 | #endif | 531 | #endif |
517 | 532 | ||
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 33e1f66e39cb..2f572b97c16d 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -1107,9 +1107,8 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend | |||
1107 | 1107 | ||
1108 | INIT_WORK(&chip->work, timeout_work); | 1108 | INIT_WORK(&chip->work, timeout_work); |
1109 | 1109 | ||
1110 | init_timer(&chip->user_read_timer); | 1110 | setup_timer(&chip->user_read_timer, user_reader_timeout, |
1111 | chip->user_read_timer.function = user_reader_timeout; | 1111 | (unsigned long)chip); |
1112 | chip->user_read_timer.data = (unsigned long) chip; | ||
1113 | 1112 | ||
1114 | memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific)); | 1113 | memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific)); |
1115 | 1114 | ||
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c index a611972024e6..4eba32b23b29 100644 --- a/drivers/char/tpm/tpm_bios.c +++ b/drivers/char/tpm/tpm_bios.c | |||
@@ -372,10 +372,8 @@ static int read_log(struct tpm_bios_log *log) | |||
372 | } | 372 | } |
373 | 373 | ||
374 | /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */ | 374 | /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */ |
375 | status = acpi_get_firmware_table(ACPI_TCPA_SIG, 1, | 375 | status = acpi_get_table(ACPI_SIG_TCPA, 1, |
376 | ACPI_LOGICAL_ADDRESSING, | 376 | (struct acpi_table_header **)&buff); |
377 | (struct acpi_table_header **) | ||
378 | &buff); | ||
379 | 377 | ||
380 | if (ACPI_FAILURE(status)) { | 378 | if (ACPI_FAILURE(status)) { |
381 | printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n", | 379 | printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n", |
@@ -409,7 +407,7 @@ static int read_log(struct tpm_bios_log *log) | |||
409 | 407 | ||
410 | log->bios_event_log_end = log->bios_event_log + len; | 408 | log->bios_event_log_end = log->bios_event_log + len; |
411 | 409 | ||
412 | acpi_os_map_memory(start, len, (void *) &virt); | 410 | virt = acpi_os_map_memory(start, len); |
413 | 411 | ||
414 | memcpy(log->bios_event_log, virt, len); | 412 | memcpy(log->bios_event_log, virt, len); |
415 | 413 | ||
@@ -443,7 +441,7 @@ static int tpm_ascii_bios_measurements_open(struct inode *inode, | |||
443 | return err; | 441 | return err; |
444 | } | 442 | } |
445 | 443 | ||
446 | struct file_operations tpm_ascii_bios_measurements_ops = { | 444 | const struct file_operations tpm_ascii_bios_measurements_ops = { |
447 | .open = tpm_ascii_bios_measurements_open, | 445 | .open = tpm_ascii_bios_measurements_open, |
448 | .read = seq_read, | 446 | .read = seq_read, |
449 | .llseek = seq_lseek, | 447 | .llseek = seq_lseek, |
@@ -476,7 +474,7 @@ static int tpm_binary_bios_measurements_open(struct inode *inode, | |||
476 | return err; | 474 | return err; |
477 | } | 475 | } |
478 | 476 | ||
479 | struct file_operations tpm_binary_bios_measurements_ops = { | 477 | const struct file_operations tpm_binary_bios_measurements_ops = { |
480 | .open = tpm_binary_bios_measurements_open, | 478 | .open = tpm_binary_bios_measurements_open, |
481 | .read = seq_read, | 479 | .read = seq_read, |
482 | .llseek = seq_lseek, | 480 | .llseek = seq_lseek, |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 47a6eacb10bc..65672c57470b 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -154,7 +154,9 @@ static int tty_release(struct inode *, struct file *); | |||
154 | int tty_ioctl(struct inode * inode, struct file * file, | 154 | int tty_ioctl(struct inode * inode, struct file * file, |
155 | unsigned int cmd, unsigned long arg); | 155 | unsigned int cmd, unsigned long arg); |
156 | static int tty_fasync(int fd, struct file * filp, int on); | 156 | static int tty_fasync(int fd, struct file * filp, int on); |
157 | static void release_mem(struct tty_struct *tty, int idx); | 157 | static void release_tty(struct tty_struct *tty, int idx); |
158 | static struct pid *__proc_set_tty(struct task_struct *tsk, | ||
159 | struct tty_struct *tty); | ||
158 | 160 | ||
159 | /** | 161 | /** |
160 | * alloc_tty_struct - allocate a tty object | 162 | * alloc_tty_struct - allocate a tty object |
@@ -1109,17 +1111,17 @@ int tty_check_change(struct tty_struct * tty) | |||
1109 | { | 1111 | { |
1110 | if (current->signal->tty != tty) | 1112 | if (current->signal->tty != tty) |
1111 | return 0; | 1113 | return 0; |
1112 | if (tty->pgrp <= 0) { | 1114 | if (!tty->pgrp) { |
1113 | printk(KERN_WARNING "tty_check_change: tty->pgrp <= 0!\n"); | 1115 | printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n"); |
1114 | return 0; | 1116 | return 0; |
1115 | } | 1117 | } |
1116 | if (process_group(current) == tty->pgrp) | 1118 | if (task_pgrp(current) == tty->pgrp) |
1117 | return 0; | 1119 | return 0; |
1118 | if (is_ignored(SIGTTOU)) | 1120 | if (is_ignored(SIGTTOU)) |
1119 | return 0; | 1121 | return 0; |
1120 | if (is_orphaned_pgrp(process_group(current))) | 1122 | if (is_current_pgrp_orphaned()) |
1121 | return -EIO; | 1123 | return -EIO; |
1122 | (void) kill_pg(process_group(current), SIGTTOU, 1); | 1124 | (void) kill_pgrp(task_pgrp(current), SIGTTOU, 1); |
1123 | return -ERESTARTSYS; | 1125 | return -ERESTARTSYS; |
1124 | } | 1126 | } |
1125 | 1127 | ||
@@ -1354,8 +1356,8 @@ static void do_tty_hangup(struct work_struct *work) | |||
1354 | tty_release is called */ | 1356 | tty_release is called */ |
1355 | 1357 | ||
1356 | read_lock(&tasklist_lock); | 1358 | read_lock(&tasklist_lock); |
1357 | if (tty->session > 0) { | 1359 | if (tty->session) { |
1358 | do_each_task_pid(tty->session, PIDTYPE_SID, p) { | 1360 | do_each_pid_task(tty->session, PIDTYPE_SID, p) { |
1359 | spin_lock_irq(&p->sighand->siglock); | 1361 | spin_lock_irq(&p->sighand->siglock); |
1360 | if (p->signal->tty == tty) | 1362 | if (p->signal->tty == tty) |
1361 | p->signal->tty = NULL; | 1363 | p->signal->tty = NULL; |
@@ -1365,16 +1367,17 @@ static void do_tty_hangup(struct work_struct *work) | |||
1365 | } | 1367 | } |
1366 | __group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p); | 1368 | __group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p); |
1367 | __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p); | 1369 | __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p); |
1368 | if (tty->pgrp > 0) | 1370 | put_pid(p->signal->tty_old_pgrp); /* A noop */ |
1369 | p->signal->tty_old_pgrp = tty->pgrp; | 1371 | if (tty->pgrp) |
1372 | p->signal->tty_old_pgrp = get_pid(tty->pgrp); | ||
1370 | spin_unlock_irq(&p->sighand->siglock); | 1373 | spin_unlock_irq(&p->sighand->siglock); |
1371 | } while_each_task_pid(tty->session, PIDTYPE_SID, p); | 1374 | } while_each_pid_task(tty->session, PIDTYPE_SID, p); |
1372 | } | 1375 | } |
1373 | read_unlock(&tasklist_lock); | 1376 | read_unlock(&tasklist_lock); |
1374 | 1377 | ||
1375 | tty->flags = 0; | 1378 | tty->flags = 0; |
1376 | tty->session = 0; | 1379 | tty->session = NULL; |
1377 | tty->pgrp = -1; | 1380 | tty->pgrp = NULL; |
1378 | tty->ctrl_status = 0; | 1381 | tty->ctrl_status = 0; |
1379 | /* | 1382 | /* |
1380 | * If one of the devices matches a console pointer, we | 1383 | * If one of the devices matches a console pointer, we |
@@ -1459,12 +1462,12 @@ int tty_hung_up_p(struct file * filp) | |||
1459 | 1462 | ||
1460 | EXPORT_SYMBOL(tty_hung_up_p); | 1463 | EXPORT_SYMBOL(tty_hung_up_p); |
1461 | 1464 | ||
1462 | static void session_clear_tty(pid_t session) | 1465 | static void session_clear_tty(struct pid *session) |
1463 | { | 1466 | { |
1464 | struct task_struct *p; | 1467 | struct task_struct *p; |
1465 | do_each_task_pid(session, PIDTYPE_SID, p) { | 1468 | do_each_pid_task(session, PIDTYPE_SID, p) { |
1466 | proc_clear_tty(p); | 1469 | proc_clear_tty(p); |
1467 | } while_each_task_pid(session, PIDTYPE_SID, p); | 1470 | } while_each_pid_task(session, PIDTYPE_SID, p); |
1468 | } | 1471 | } |
1469 | 1472 | ||
1470 | /** | 1473 | /** |
@@ -1494,46 +1497,54 @@ static void session_clear_tty(pid_t session) | |||
1494 | void disassociate_ctty(int on_exit) | 1497 | void disassociate_ctty(int on_exit) |
1495 | { | 1498 | { |
1496 | struct tty_struct *tty; | 1499 | struct tty_struct *tty; |
1497 | int tty_pgrp = -1; | 1500 | struct pid *tty_pgrp = NULL; |
1498 | int session; | ||
1499 | 1501 | ||
1500 | lock_kernel(); | 1502 | lock_kernel(); |
1501 | 1503 | ||
1502 | mutex_lock(&tty_mutex); | 1504 | mutex_lock(&tty_mutex); |
1503 | tty = get_current_tty(); | 1505 | tty = get_current_tty(); |
1504 | if (tty) { | 1506 | if (tty) { |
1505 | tty_pgrp = tty->pgrp; | 1507 | tty_pgrp = get_pid(tty->pgrp); |
1506 | mutex_unlock(&tty_mutex); | 1508 | mutex_unlock(&tty_mutex); |
1507 | /* XXX: here we race, there is nothing protecting tty */ | 1509 | /* XXX: here we race, there is nothing protecting tty */ |
1508 | if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) | 1510 | if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) |
1509 | tty_vhangup(tty); | 1511 | tty_vhangup(tty); |
1510 | } else { | 1512 | } else if (on_exit) { |
1511 | pid_t old_pgrp = current->signal->tty_old_pgrp; | 1513 | struct pid *old_pgrp; |
1514 | spin_lock_irq(¤t->sighand->siglock); | ||
1515 | old_pgrp = current->signal->tty_old_pgrp; | ||
1516 | current->signal->tty_old_pgrp = NULL; | ||
1517 | spin_unlock_irq(¤t->sighand->siglock); | ||
1512 | if (old_pgrp) { | 1518 | if (old_pgrp) { |
1513 | kill_pg(old_pgrp, SIGHUP, on_exit); | 1519 | kill_pgrp(old_pgrp, SIGHUP, on_exit); |
1514 | kill_pg(old_pgrp, SIGCONT, on_exit); | 1520 | kill_pgrp(old_pgrp, SIGCONT, on_exit); |
1521 | put_pid(old_pgrp); | ||
1515 | } | 1522 | } |
1516 | mutex_unlock(&tty_mutex); | 1523 | mutex_unlock(&tty_mutex); |
1517 | unlock_kernel(); | 1524 | unlock_kernel(); |
1518 | return; | 1525 | return; |
1519 | } | 1526 | } |
1520 | if (tty_pgrp > 0) { | 1527 | if (tty_pgrp) { |
1521 | kill_pg(tty_pgrp, SIGHUP, on_exit); | 1528 | kill_pgrp(tty_pgrp, SIGHUP, on_exit); |
1522 | if (!on_exit) | 1529 | if (!on_exit) |
1523 | kill_pg(tty_pgrp, SIGCONT, on_exit); | 1530 | kill_pgrp(tty_pgrp, SIGCONT, on_exit); |
1531 | put_pid(tty_pgrp); | ||
1524 | } | 1532 | } |
1525 | 1533 | ||
1526 | spin_lock_irq(¤t->sighand->siglock); | 1534 | spin_lock_irq(¤t->sighand->siglock); |
1535 | tty_pgrp = current->signal->tty_old_pgrp; | ||
1527 | current->signal->tty_old_pgrp = 0; | 1536 | current->signal->tty_old_pgrp = 0; |
1528 | session = process_session(current); | ||
1529 | spin_unlock_irq(¤t->sighand->siglock); | 1537 | spin_unlock_irq(¤t->sighand->siglock); |
1538 | put_pid(tty_pgrp); | ||
1530 | 1539 | ||
1531 | mutex_lock(&tty_mutex); | 1540 | mutex_lock(&tty_mutex); |
1532 | /* It is possible that do_tty_hangup has free'd this tty */ | 1541 | /* It is possible that do_tty_hangup has free'd this tty */ |
1533 | tty = get_current_tty(); | 1542 | tty = get_current_tty(); |
1534 | if (tty) { | 1543 | if (tty) { |
1535 | tty->session = 0; | 1544 | put_pid(tty->session); |
1536 | tty->pgrp = 0; | 1545 | put_pid(tty->pgrp); |
1546 | tty->session = NULL; | ||
1547 | tty->pgrp = NULL; | ||
1537 | } else { | 1548 | } else { |
1538 | #ifdef TTY_DEBUG_HANGUP | 1549 | #ifdef TTY_DEBUG_HANGUP |
1539 | printk(KERN_DEBUG "error attempted to write to tty [0x%p]" | 1550 | printk(KERN_DEBUG "error attempted to write to tty [0x%p]" |
@@ -1544,7 +1555,7 @@ void disassociate_ctty(int on_exit) | |||
1544 | 1555 | ||
1545 | /* Now clear signal->tty under the lock */ | 1556 | /* Now clear signal->tty under the lock */ |
1546 | read_lock(&tasklist_lock); | 1557 | read_lock(&tasklist_lock); |
1547 | session_clear_tty(session); | 1558 | session_clear_tty(task_session(current)); |
1548 | read_unlock(&tasklist_lock); | 1559 | read_unlock(&tasklist_lock); |
1549 | unlock_kernel(); | 1560 | unlock_kernel(); |
1550 | } | 1561 | } |
@@ -1612,7 +1623,6 @@ void start_tty(struct tty_struct *tty) | |||
1612 | 1623 | ||
1613 | /* If we have a running line discipline it may need kicking */ | 1624 | /* If we have a running line discipline it may need kicking */ |
1614 | tty_wakeup(tty); | 1625 | tty_wakeup(tty); |
1615 | wake_up_interruptible(&tty->write_wait); | ||
1616 | } | 1626 | } |
1617 | 1627 | ||
1618 | EXPORT_SYMBOL(start_tty); | 1628 | EXPORT_SYMBOL(start_tty); |
@@ -2003,7 +2013,7 @@ static int init_dev(struct tty_driver *driver, int idx, | |||
2003 | 2013 | ||
2004 | /* | 2014 | /* |
2005 | * All structures have been allocated, so now we install them. | 2015 | * All structures have been allocated, so now we install them. |
2006 | * Failures after this point use release_mem to clean up, so | 2016 | * Failures after this point use release_tty to clean up, so |
2007 | * there's no need to null out the local pointers. | 2017 | * there's no need to null out the local pointers. |
2008 | */ | 2018 | */ |
2009 | if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM)) { | 2019 | if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM)) { |
@@ -2024,8 +2034,8 @@ static int init_dev(struct tty_driver *driver, int idx, | |||
2024 | 2034 | ||
2025 | /* | 2035 | /* |
2026 | * Structures all installed ... call the ldisc open routines. | 2036 | * Structures all installed ... call the ldisc open routines. |
2027 | * If we fail here just call release_mem to clean up. No need | 2037 | * If we fail here just call release_tty to clean up. No need |
2028 | * to decrement the use counts, as release_mem doesn't care. | 2038 | * to decrement the use counts, as release_tty doesn't care. |
2029 | */ | 2039 | */ |
2030 | 2040 | ||
2031 | if (tty->ldisc.open) { | 2041 | if (tty->ldisc.open) { |
@@ -2095,17 +2105,17 @@ fail_no_mem: | |||
2095 | retval = -ENOMEM; | 2105 | retval = -ENOMEM; |
2096 | goto end_init; | 2106 | goto end_init; |
2097 | 2107 | ||
2098 | /* call the tty release_mem routine to clean out this slot */ | 2108 | /* call the tty release_tty routine to clean out this slot */ |
2099 | release_mem_out: | 2109 | release_mem_out: |
2100 | if (printk_ratelimit()) | 2110 | if (printk_ratelimit()) |
2101 | printk(KERN_INFO "init_dev: ldisc open failed, " | 2111 | printk(KERN_INFO "init_dev: ldisc open failed, " |
2102 | "clearing slot %d\n", idx); | 2112 | "clearing slot %d\n", idx); |
2103 | release_mem(tty, idx); | 2113 | release_tty(tty, idx); |
2104 | goto end_init; | 2114 | goto end_init; |
2105 | } | 2115 | } |
2106 | 2116 | ||
2107 | /** | 2117 | /** |
2108 | * release_mem - release tty structure memory | 2118 | * release_one_tty - release tty structure memory |
2109 | * | 2119 | * |
2110 | * Releases memory associated with a tty structure, and clears out the | 2120 | * Releases memory associated with a tty structure, and clears out the |
2111 | * driver table slots. This function is called when a device is no longer | 2121 | * driver table slots. This function is called when a device is no longer |
@@ -2117,37 +2127,14 @@ release_mem_out: | |||
2117 | * of ttys that the driver keeps. | 2127 | * of ttys that the driver keeps. |
2118 | * FIXME: should we require tty_mutex is held here ?? | 2128 | * FIXME: should we require tty_mutex is held here ?? |
2119 | */ | 2129 | */ |
2120 | 2130 | static void release_one_tty(struct tty_struct *tty, int idx) | |
2121 | static void release_mem(struct tty_struct *tty, int idx) | ||
2122 | { | 2131 | { |
2123 | struct tty_struct *o_tty; | ||
2124 | struct ktermios *tp; | ||
2125 | int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM; | 2132 | int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM; |
2126 | 2133 | struct ktermios *tp; | |
2127 | if ((o_tty = tty->link) != NULL) { | ||
2128 | if (!devpts) | ||
2129 | o_tty->driver->ttys[idx] = NULL; | ||
2130 | if (o_tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { | ||
2131 | tp = o_tty->termios; | ||
2132 | if (!devpts) | ||
2133 | o_tty->driver->termios[idx] = NULL; | ||
2134 | kfree(tp); | ||
2135 | |||
2136 | tp = o_tty->termios_locked; | ||
2137 | if (!devpts) | ||
2138 | o_tty->driver->termios_locked[idx] = NULL; | ||
2139 | kfree(tp); | ||
2140 | } | ||
2141 | o_tty->magic = 0; | ||
2142 | o_tty->driver->refcount--; | ||
2143 | file_list_lock(); | ||
2144 | list_del_init(&o_tty->tty_files); | ||
2145 | file_list_unlock(); | ||
2146 | free_tty_struct(o_tty); | ||
2147 | } | ||
2148 | 2134 | ||
2149 | if (!devpts) | 2135 | if (!devpts) |
2150 | tty->driver->ttys[idx] = NULL; | 2136 | tty->driver->ttys[idx] = NULL; |
2137 | |||
2151 | if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { | 2138 | if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { |
2152 | tp = tty->termios; | 2139 | tp = tty->termios; |
2153 | if (!devpts) | 2140 | if (!devpts) |
@@ -2160,15 +2147,39 @@ static void release_mem(struct tty_struct *tty, int idx) | |||
2160 | kfree(tp); | 2147 | kfree(tp); |
2161 | } | 2148 | } |
2162 | 2149 | ||
2150 | |||
2163 | tty->magic = 0; | 2151 | tty->magic = 0; |
2164 | tty->driver->refcount--; | 2152 | tty->driver->refcount--; |
2153 | |||
2165 | file_list_lock(); | 2154 | file_list_lock(); |
2166 | list_del_init(&tty->tty_files); | 2155 | list_del_init(&tty->tty_files); |
2167 | file_list_unlock(); | 2156 | file_list_unlock(); |
2168 | module_put(tty->driver->owner); | 2157 | |
2169 | free_tty_struct(tty); | 2158 | free_tty_struct(tty); |
2170 | } | 2159 | } |
2171 | 2160 | ||
2161 | /** | ||
2162 | * release_tty - release tty structure memory | ||
2163 | * | ||
2164 | * Release both @tty and a possible linked partner (think pty pair), | ||
2165 | * and decrement the refcount of the backing module. | ||
2166 | * | ||
2167 | * Locking: | ||
2168 | * tty_mutex - sometimes only | ||
2169 | * takes the file list lock internally when working on the list | ||
2170 | * of ttys that the driver keeps. | ||
2171 | * FIXME: should we require tty_mutex is held here ?? | ||
2172 | */ | ||
2173 | static void release_tty(struct tty_struct *tty, int idx) | ||
2174 | { | ||
2175 | struct tty_driver *driver = tty->driver; | ||
2176 | |||
2177 | if (tty->link) | ||
2178 | release_one_tty(tty->link, idx); | ||
2179 | release_one_tty(tty, idx); | ||
2180 | module_put(driver->owner); | ||
2181 | } | ||
2182 | |||
2172 | /* | 2183 | /* |
2173 | * Even releasing the tty structures is a tricky business.. We have | 2184 | * Even releasing the tty structures is a tricky business.. We have |
2174 | * to be very careful that the structures are all released at the | 2185 | * to be very careful that the structures are all released at the |
@@ -2436,10 +2447,10 @@ static void release_dev(struct file * filp) | |||
2436 | tty_set_termios_ldisc(o_tty,N_TTY); | 2447 | tty_set_termios_ldisc(o_tty,N_TTY); |
2437 | } | 2448 | } |
2438 | /* | 2449 | /* |
2439 | * The release_mem function takes care of the details of clearing | 2450 | * The release_tty function takes care of the details of clearing |
2440 | * the slots and preserving the termios structure. | 2451 | * the slots and preserving the termios structure. |
2441 | */ | 2452 | */ |
2442 | release_mem(tty, idx); | 2453 | release_tty(tty, idx); |
2443 | 2454 | ||
2444 | #ifdef CONFIG_UNIX98_PTYS | 2455 | #ifdef CONFIG_UNIX98_PTYS |
2445 | /* Make this pty number available for reallocation */ | 2456 | /* Make this pty number available for reallocation */ |
@@ -2481,6 +2492,7 @@ static int tty_open(struct inode * inode, struct file * filp) | |||
2481 | int index; | 2492 | int index; |
2482 | dev_t device = inode->i_rdev; | 2493 | dev_t device = inode->i_rdev; |
2483 | unsigned short saved_flags = filp->f_flags; | 2494 | unsigned short saved_flags = filp->f_flags; |
2495 | struct pid *old_pgrp; | ||
2484 | 2496 | ||
2485 | nonseekable_open(inode, filp); | 2497 | nonseekable_open(inode, filp); |
2486 | 2498 | ||
@@ -2574,15 +2586,17 @@ got_driver: | |||
2574 | goto retry_open; | 2586 | goto retry_open; |
2575 | } | 2587 | } |
2576 | 2588 | ||
2589 | old_pgrp = NULL; | ||
2577 | mutex_lock(&tty_mutex); | 2590 | mutex_lock(&tty_mutex); |
2578 | spin_lock_irq(¤t->sighand->siglock); | 2591 | spin_lock_irq(¤t->sighand->siglock); |
2579 | if (!noctty && | 2592 | if (!noctty && |
2580 | current->signal->leader && | 2593 | current->signal->leader && |
2581 | !current->signal->tty && | 2594 | !current->signal->tty && |
2582 | tty->session == 0) | 2595 | tty->session == NULL) |
2583 | __proc_set_tty(current, tty); | 2596 | old_pgrp = __proc_set_tty(current, tty); |
2584 | spin_unlock_irq(¤t->sighand->siglock); | 2597 | spin_unlock_irq(¤t->sighand->siglock); |
2585 | mutex_unlock(&tty_mutex); | 2598 | mutex_unlock(&tty_mutex); |
2599 | put_pid(old_pgrp); | ||
2586 | return 0; | 2600 | return 0; |
2587 | } | 2601 | } |
2588 | 2602 | ||
@@ -2721,9 +2735,18 @@ static int tty_fasync(int fd, struct file * filp, int on) | |||
2721 | return retval; | 2735 | return retval; |
2722 | 2736 | ||
2723 | if (on) { | 2737 | if (on) { |
2738 | enum pid_type type; | ||
2739 | struct pid *pid; | ||
2724 | if (!waitqueue_active(&tty->read_wait)) | 2740 | if (!waitqueue_active(&tty->read_wait)) |
2725 | tty->minimum_to_wake = 1; | 2741 | tty->minimum_to_wake = 1; |
2726 | retval = f_setown(filp, (-tty->pgrp) ? : current->pid, 0); | 2742 | if (tty->pgrp) { |
2743 | pid = tty->pgrp; | ||
2744 | type = PIDTYPE_PGID; | ||
2745 | } else { | ||
2746 | pid = task_pid(current); | ||
2747 | type = PIDTYPE_PID; | ||
2748 | } | ||
2749 | retval = __f_setown(filp, pid, type, 0); | ||
2727 | if (retval) | 2750 | if (retval) |
2728 | return retval; | 2751 | return retval; |
2729 | } else { | 2752 | } else { |
@@ -2825,10 +2848,10 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, | |||
2825 | } | 2848 | } |
2826 | } | 2849 | } |
2827 | #endif | 2850 | #endif |
2828 | if (tty->pgrp > 0) | 2851 | if (tty->pgrp) |
2829 | kill_pg(tty->pgrp, SIGWINCH, 1); | 2852 | kill_pgrp(tty->pgrp, SIGWINCH, 1); |
2830 | if ((real_tty->pgrp != tty->pgrp) && (real_tty->pgrp > 0)) | 2853 | if ((real_tty->pgrp != tty->pgrp) && real_tty->pgrp) |
2831 | kill_pg(real_tty->pgrp, SIGWINCH, 1); | 2854 | kill_pgrp(real_tty->pgrp, SIGWINCH, 1); |
2832 | tty->winsize = tmp_ws; | 2855 | tty->winsize = tmp_ws; |
2833 | real_tty->winsize = tmp_ws; | 2856 | real_tty->winsize = tmp_ws; |
2834 | done: | 2857 | done: |
@@ -2913,8 +2936,7 @@ static int fionbio(struct file *file, int __user *p) | |||
2913 | static int tiocsctty(struct tty_struct *tty, int arg) | 2936 | static int tiocsctty(struct tty_struct *tty, int arg) |
2914 | { | 2937 | { |
2915 | int ret = 0; | 2938 | int ret = 0; |
2916 | if (current->signal->leader && | 2939 | if (current->signal->leader && (task_session(current) == tty->session)) |
2917 | (process_session(current) == tty->session)) | ||
2918 | return ret; | 2940 | return ret; |
2919 | 2941 | ||
2920 | mutex_lock(&tty_mutex); | 2942 | mutex_lock(&tty_mutex); |
@@ -2927,7 +2949,7 @@ static int tiocsctty(struct tty_struct *tty, int arg) | |||
2927 | goto unlock; | 2949 | goto unlock; |
2928 | } | 2950 | } |
2929 | 2951 | ||
2930 | if (tty->session > 0) { | 2952 | if (tty->session) { |
2931 | /* | 2953 | /* |
2932 | * This tty is already the controlling | 2954 | * This tty is already the controlling |
2933 | * tty for another session group! | 2955 | * tty for another session group! |
@@ -2970,7 +2992,7 @@ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t | |||
2970 | */ | 2992 | */ |
2971 | if (tty == real_tty && current->signal->tty != real_tty) | 2993 | if (tty == real_tty && current->signal->tty != real_tty) |
2972 | return -ENOTTY; | 2994 | return -ENOTTY; |
2973 | return put_user(real_tty->pgrp, p); | 2995 | return put_user(pid_nr(real_tty->pgrp), p); |
2974 | } | 2996 | } |
2975 | 2997 | ||
2976 | /** | 2998 | /** |
@@ -2987,7 +3009,8 @@ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t | |||
2987 | 3009 | ||
2988 | static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) | 3010 | static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) |
2989 | { | 3011 | { |
2990 | pid_t pgrp; | 3012 | struct pid *pgrp; |
3013 | pid_t pgrp_nr; | ||
2991 | int retval = tty_check_change(real_tty); | 3014 | int retval = tty_check_change(real_tty); |
2992 | 3015 | ||
2993 | if (retval == -EIO) | 3016 | if (retval == -EIO) |
@@ -2996,16 +3019,26 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t | |||
2996 | return retval; | 3019 | return retval; |
2997 | if (!current->signal->tty || | 3020 | if (!current->signal->tty || |
2998 | (current->signal->tty != real_tty) || | 3021 | (current->signal->tty != real_tty) || |
2999 | (real_tty->session != process_session(current))) | 3022 | (real_tty->session != task_session(current))) |
3000 | return -ENOTTY; | 3023 | return -ENOTTY; |
3001 | if (get_user(pgrp, p)) | 3024 | if (get_user(pgrp_nr, p)) |
3002 | return -EFAULT; | 3025 | return -EFAULT; |
3003 | if (pgrp < 0) | 3026 | if (pgrp_nr < 0) |
3004 | return -EINVAL; | 3027 | return -EINVAL; |
3005 | if (session_of_pgrp(pgrp) != process_session(current)) | 3028 | rcu_read_lock(); |
3006 | return -EPERM; | 3029 | pgrp = find_pid(pgrp_nr); |
3007 | real_tty->pgrp = pgrp; | 3030 | retval = -ESRCH; |
3008 | return 0; | 3031 | if (!pgrp) |
3032 | goto out_unlock; | ||
3033 | retval = -EPERM; | ||
3034 | if (session_of_pgrp(pgrp) != task_session(current)) | ||
3035 | goto out_unlock; | ||
3036 | retval = 0; | ||
3037 | put_pid(real_tty->pgrp); | ||
3038 | real_tty->pgrp = get_pid(pgrp); | ||
3039 | out_unlock: | ||
3040 | rcu_read_unlock(); | ||
3041 | return retval; | ||
3009 | } | 3042 | } |
3010 | 3043 | ||
3011 | /** | 3044 | /** |
@@ -3028,9 +3061,9 @@ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t _ | |||
3028 | */ | 3061 | */ |
3029 | if (tty == real_tty && current->signal->tty != real_tty) | 3062 | if (tty == real_tty && current->signal->tty != real_tty) |
3030 | return -ENOTTY; | 3063 | return -ENOTTY; |
3031 | if (real_tty->session <= 0) | 3064 | if (!real_tty->session) |
3032 | return -ENOTTY; | 3065 | return -ENOTTY; |
3033 | return put_user(real_tty->session, p); | 3066 | return put_user(pid_nr(real_tty->session), p); |
3034 | } | 3067 | } |
3035 | 3068 | ||
3036 | /** | 3069 | /** |
@@ -3324,15 +3357,13 @@ int tty_ioctl(struct inode * inode, struct file * file, | |||
3324 | * Nasty bug: do_SAK is being called in interrupt context. This can | 3357 | * Nasty bug: do_SAK is being called in interrupt context. This can |
3325 | * deadlock. We punt it up to process context. AKPM - 16Mar2001 | 3358 | * deadlock. We punt it up to process context. AKPM - 16Mar2001 |
3326 | */ | 3359 | */ |
3327 | static void __do_SAK(struct work_struct *work) | 3360 | void __do_SAK(struct tty_struct *tty) |
3328 | { | 3361 | { |
3329 | struct tty_struct *tty = | ||
3330 | container_of(work, struct tty_struct, SAK_work); | ||
3331 | #ifdef TTY_SOFT_SAK | 3362 | #ifdef TTY_SOFT_SAK |
3332 | tty_hangup(tty); | 3363 | tty_hangup(tty); |
3333 | #else | 3364 | #else |
3334 | struct task_struct *g, *p; | 3365 | struct task_struct *g, *p; |
3335 | int session; | 3366 | struct pid *session; |
3336 | int i; | 3367 | int i; |
3337 | struct file *filp; | 3368 | struct file *filp; |
3338 | struct fdtable *fdt; | 3369 | struct fdtable *fdt; |
@@ -3348,12 +3379,12 @@ static void __do_SAK(struct work_struct *work) | |||
3348 | 3379 | ||
3349 | read_lock(&tasklist_lock); | 3380 | read_lock(&tasklist_lock); |
3350 | /* Kill the entire session */ | 3381 | /* Kill the entire session */ |
3351 | do_each_task_pid(session, PIDTYPE_SID, p) { | 3382 | do_each_pid_task(session, PIDTYPE_SID, p) { |
3352 | printk(KERN_NOTICE "SAK: killed process %d" | 3383 | printk(KERN_NOTICE "SAK: killed process %d" |
3353 | " (%s): process_session(p)==tty->session\n", | 3384 | " (%s): process_session(p)==tty->session\n", |
3354 | p->pid, p->comm); | 3385 | p->pid, p->comm); |
3355 | send_sig(SIGKILL, p, 1); | 3386 | send_sig(SIGKILL, p, 1); |
3356 | } while_each_task_pid(session, PIDTYPE_SID, p); | 3387 | } while_each_pid_task(session, PIDTYPE_SID, p); |
3357 | /* Now kill any processes that happen to have the | 3388 | /* Now kill any processes that happen to have the |
3358 | * tty open. | 3389 | * tty open. |
3359 | */ | 3390 | */ |
@@ -3394,6 +3425,13 @@ static void __do_SAK(struct work_struct *work) | |||
3394 | #endif | 3425 | #endif |
3395 | } | 3426 | } |
3396 | 3427 | ||
3428 | static void do_SAK_work(struct work_struct *work) | ||
3429 | { | ||
3430 | struct tty_struct *tty = | ||
3431 | container_of(work, struct tty_struct, SAK_work); | ||
3432 | __do_SAK(tty); | ||
3433 | } | ||
3434 | |||
3397 | /* | 3435 | /* |
3398 | * The tq handling here is a little racy - tty->SAK_work may already be queued. | 3436 | * The tq handling here is a little racy - tty->SAK_work may already be queued. |
3399 | * Fortunately we don't need to worry, because if ->SAK_work is already queued, | 3437 | * Fortunately we don't need to worry, because if ->SAK_work is already queued, |
@@ -3404,7 +3442,7 @@ void do_SAK(struct tty_struct *tty) | |||
3404 | { | 3442 | { |
3405 | if (!tty) | 3443 | if (!tty) |
3406 | return; | 3444 | return; |
3407 | PREPARE_WORK(&tty->SAK_work, __do_SAK); | 3445 | PREPARE_WORK(&tty->SAK_work, do_SAK_work); |
3408 | schedule_work(&tty->SAK_work); | 3446 | schedule_work(&tty->SAK_work); |
3409 | } | 3447 | } |
3410 | 3448 | ||
@@ -3515,7 +3553,8 @@ static void initialize_tty_struct(struct tty_struct *tty) | |||
3515 | memset(tty, 0, sizeof(struct tty_struct)); | 3553 | memset(tty, 0, sizeof(struct tty_struct)); |
3516 | tty->magic = TTY_MAGIC; | 3554 | tty->magic = TTY_MAGIC; |
3517 | tty_ldisc_assign(tty, tty_ldisc_get(N_TTY)); | 3555 | tty_ldisc_assign(tty, tty_ldisc_get(N_TTY)); |
3518 | tty->pgrp = -1; | 3556 | tty->session = NULL; |
3557 | tty->pgrp = NULL; | ||
3519 | tty->overrun_time = jiffies; | 3558 | tty->overrun_time = jiffies; |
3520 | tty->buf.head = tty->buf.tail = NULL; | 3559 | tty->buf.head = tty->buf.tail = NULL; |
3521 | tty_buffer_init(tty); | 3560 | tty_buffer_init(tty); |
@@ -3786,21 +3825,28 @@ void proc_clear_tty(struct task_struct *p) | |||
3786 | } | 3825 | } |
3787 | EXPORT_SYMBOL(proc_clear_tty); | 3826 | EXPORT_SYMBOL(proc_clear_tty); |
3788 | 3827 | ||
3789 | void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) | 3828 | static struct pid *__proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) |
3790 | { | 3829 | { |
3830 | struct pid *old_pgrp; | ||
3791 | if (tty) { | 3831 | if (tty) { |
3792 | tty->session = process_session(tsk); | 3832 | tty->session = get_pid(task_session(tsk)); |
3793 | tty->pgrp = process_group(tsk); | 3833 | tty->pgrp = get_pid(task_pgrp(tsk)); |
3794 | } | 3834 | } |
3835 | old_pgrp = tsk->signal->tty_old_pgrp; | ||
3795 | tsk->signal->tty = tty; | 3836 | tsk->signal->tty = tty; |
3796 | tsk->signal->tty_old_pgrp = 0; | 3837 | tsk->signal->tty_old_pgrp = NULL; |
3838 | return old_pgrp; | ||
3797 | } | 3839 | } |
3798 | 3840 | ||
3799 | void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) | 3841 | void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) |
3800 | { | 3842 | { |
3843 | struct pid *old_pgrp; | ||
3844 | |||
3801 | spin_lock_irq(&tsk->sighand->siglock); | 3845 | spin_lock_irq(&tsk->sighand->siglock); |
3802 | __proc_set_tty(tsk, tty); | 3846 | old_pgrp = __proc_set_tty(tsk, tty); |
3803 | spin_unlock_irq(&tsk->sighand->siglock); | 3847 | spin_unlock_irq(&tsk->sighand->siglock); |
3848 | |||
3849 | put_pid(old_pgrp); | ||
3804 | } | 3850 | } |
3805 | 3851 | ||
3806 | struct tty_struct *get_current_tty(void) | 3852 | struct tty_struct *get_current_tty(void) |
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index dee47f40c6a3..fd471cb3338f 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c | |||
@@ -225,7 +225,7 @@ EXPORT_SYMBOL(tty_termios_input_baud_rate); | |||
225 | 225 | ||
226 | /** | 226 | /** |
227 | * tty_termios_encode_baud_rate | 227 | * tty_termios_encode_baud_rate |
228 | * @termios: termios structure | 228 | * @termios: ktermios structure holding user requested state |
229 | * @ispeed: input speed | 229 | * @ispeed: input speed |
230 | * @ospeed: output speed | 230 | * @ospeed: output speed |
231 | * | 231 | * |
@@ -233,7 +233,10 @@ EXPORT_SYMBOL(tty_termios_input_baud_rate); | |||
233 | * used as a library helper for drivers os that they can report back | 233 | * used as a library helper for drivers os that they can report back |
234 | * the actual speed selected when it differs from the speed requested | 234 | * the actual speed selected when it differs from the speed requested |
235 | * | 235 | * |
236 | * For now input and output speed must agree. | 236 | * For maximal back compatibility with legacy SYS5/POSIX *nix behaviour |
237 | * we need to carefully set the bits when the user does not get the | ||
238 | * desired speed. We allow small margins and preserve as much of possible | ||
239 | * of the input intent to keep compatiblity. | ||
237 | * | 240 | * |
238 | * Locking: Caller should hold termios lock. This is already held | 241 | * Locking: Caller should hold termios lock. This is already held |
239 | * when calling this function from the driver termios handler. | 242 | * when calling this function from the driver termios handler. |
@@ -242,32 +245,44 @@ EXPORT_SYMBOL(tty_termios_input_baud_rate); | |||
242 | void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed_t obaud) | 245 | void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed_t obaud) |
243 | { | 246 | { |
244 | int i = 0; | 247 | int i = 0; |
245 | int ifound = 0, ofound = 0; | 248 | int ifound = -1, ofound = -1; |
249 | int iclose = ibaud/50, oclose = obaud/50; | ||
250 | int ibinput = 0; | ||
246 | 251 | ||
247 | termios->c_ispeed = ibaud; | 252 | termios->c_ispeed = ibaud; |
248 | termios->c_ospeed = obaud; | 253 | termios->c_ospeed = obaud; |
249 | 254 | ||
255 | /* If the user asked for a precise weird speed give a precise weird | ||
256 | answer. If they asked for a Bfoo speed they many have problems | ||
257 | digesting non-exact replies so fuzz a bit */ | ||
258 | |||
259 | if ((termios->c_cflag & CBAUD) == BOTHER) | ||
260 | oclose = 0; | ||
261 | if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER) | ||
262 | iclose = 0; | ||
263 | if ((termios->c_cflag >> IBSHIFT) & CBAUD) | ||
264 | ibinput = 1; /* An input speed was specified */ | ||
265 | |||
250 | termios->c_cflag &= ~CBAUD; | 266 | termios->c_cflag &= ~CBAUD; |
251 | /* Identical speed means no input encoding (ie B0 << IBSHIFT)*/ | ||
252 | if (termios->c_ispeed == termios->c_ospeed) | ||
253 | ifound = 1; | ||
254 | 267 | ||
255 | do { | 268 | do { |
256 | if (obaud == baud_table[i]) { | 269 | if (obaud - oclose >= baud_table[i] && obaud + oclose <= baud_table[i]) { |
257 | termios->c_cflag |= baud_bits[i]; | 270 | termios->c_cflag |= baud_bits[i]; |
258 | ofound = 1; | 271 | ofound = i; |
259 | /* So that if ibaud == obaud we don't set it */ | ||
260 | continue; | ||
261 | } | 272 | } |
262 | if (ibaud == baud_table[i]) { | 273 | if (ibaud - iclose >= baud_table[i] && ibaud + iclose <= baud_table[i]) { |
263 | termios->c_cflag |= (baud_bits[i] << IBSHIFT); | 274 | /* For the case input == output don't set IBAUD bits if the user didn't do so */ |
264 | ifound = 1; | 275 | if (ofound != i || ibinput) |
276 | termios->c_cflag |= (baud_bits[i] << IBSHIFT); | ||
277 | ifound = i; | ||
265 | } | 278 | } |
266 | } | 279 | } |
267 | while(++i < n_baud_table); | 280 | while(++i < n_baud_table); |
268 | if (!ofound) | 281 | if (ofound == -1) |
269 | termios->c_cflag |= BOTHER; | 282 | termios->c_cflag |= BOTHER; |
270 | if (!ifound) | 283 | /* Set exact input bits only if the input and output differ or the |
284 | user already did */ | ||
285 | if (ifound == -1 && (ibaud != obaud || ibinput)) | ||
271 | termios->c_cflag |= (BOTHER << IBSHIFT); | 286 | termios->c_cflag |= (BOTHER << IBSHIFT); |
272 | } | 287 | } |
273 | 288 | ||
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index 9438512b17f1..13faf8d17482 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c | |||
@@ -872,7 +872,7 @@ free_op: | |||
872 | return ret; | 872 | return ret; |
873 | } | 873 | } |
874 | 874 | ||
875 | struct file_operations viotap_fops = { | 875 | const struct file_operations viotap_fops = { |
876 | owner: THIS_MODULE, | 876 | owner: THIS_MODULE, |
877 | read: viotap_read, | 877 | read: viotap_read, |
878 | write: viotap_write, | 878 | write: viotap_write, |
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 06c32a3e3ca4..94ce3e7fc9e4 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -136,9 +136,6 @@ const struct consw *conswitchp; | |||
136 | #define DEFAULT_BELL_PITCH 750 | 136 | #define DEFAULT_BELL_PITCH 750 |
137 | #define DEFAULT_BELL_DURATION (HZ/8) | 137 | #define DEFAULT_BELL_DURATION (HZ/8) |
138 | 138 | ||
139 | extern void vcs_make_sysfs(struct tty_struct *tty); | ||
140 | extern void vcs_remove_sysfs(struct tty_struct *tty); | ||
141 | |||
142 | struct vc vc_cons [MAX_NR_CONSOLES]; | 139 | struct vc vc_cons [MAX_NR_CONSOLES]; |
143 | 140 | ||
144 | #ifndef VT_SINGLE_DRIVER | 141 | #ifndef VT_SINGLE_DRIVER |
@@ -213,7 +210,7 @@ static int scrollback_delta; | |||
213 | */ | 210 | */ |
214 | int (*console_blank_hook)(int); | 211 | int (*console_blank_hook)(int); |
215 | 212 | ||
216 | static struct timer_list console_timer; | 213 | static DEFINE_TIMER(console_timer, blank_screen_t, 0, 0); |
217 | static int blank_state; | 214 | static int blank_state; |
218 | static int blank_timer_expired; | 215 | static int blank_timer_expired; |
219 | enum { | 216 | enum { |
@@ -869,8 +866,8 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) | |||
869 | ws.ws_col = vc->vc_cols; | 866 | ws.ws_col = vc->vc_cols; |
870 | ws.ws_ypixel = vc->vc_scan_lines; | 867 | ws.ws_ypixel = vc->vc_scan_lines; |
871 | if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) && | 868 | if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) && |
872 | vc->vc_tty->pgrp > 0) | 869 | vc->vc_tty->pgrp) |
873 | kill_pg(vc->vc_tty->pgrp, SIGWINCH, 1); | 870 | kill_pgrp(vc->vc_tty->pgrp, SIGWINCH, 1); |
874 | *cws = ws; | 871 | *cws = ws; |
875 | } | 872 | } |
876 | 873 | ||
@@ -2628,8 +2625,6 @@ static int __init con_init(void) | |||
2628 | for (i = 0; i < MAX_NR_CONSOLES; i++) | 2625 | for (i = 0; i < MAX_NR_CONSOLES; i++) |
2629 | con_driver_map[i] = conswitchp; | 2626 | con_driver_map[i] = conswitchp; |
2630 | 2627 | ||
2631 | init_timer(&console_timer); | ||
2632 | console_timer.function = blank_screen_t; | ||
2633 | if (blankinterval) { | 2628 | if (blankinterval) { |
2634 | blank_state = blank_normal_wait; | 2629 | blank_state = blank_normal_wait; |
2635 | mod_timer(&console_timer, jiffies + blankinterval); | 2630 | mod_timer(&console_timer, jiffies + blankinterval); |
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index dc8368ebb1ac..3a5d301e783b 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c | |||
@@ -672,7 +672,8 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
672 | vc->vt_mode = tmp; | 672 | vc->vt_mode = tmp; |
673 | /* the frsig is ignored, so we set it to 0 */ | 673 | /* the frsig is ignored, so we set it to 0 */ |
674 | vc->vt_mode.frsig = 0; | 674 | vc->vt_mode.frsig = 0; |
675 | put_pid(xchg(&vc->vt_pid, get_pid(task_pid(current)))); | 675 | put_pid(vc->vt_pid); |
676 | vc->vt_pid = get_pid(task_pid(current)); | ||
676 | /* no switch is required -- saw@shade.msu.ru */ | 677 | /* no switch is required -- saw@shade.msu.ru */ |
677 | vc->vt_newvt = -1; | 678 | vc->vt_newvt = -1; |
678 | release_console_sem(); | 679 | release_console_sem(); |
@@ -1063,12 +1064,35 @@ void reset_vc(struct vc_data *vc) | |||
1063 | vc->vt_mode.relsig = 0; | 1064 | vc->vt_mode.relsig = 0; |
1064 | vc->vt_mode.acqsig = 0; | 1065 | vc->vt_mode.acqsig = 0; |
1065 | vc->vt_mode.frsig = 0; | 1066 | vc->vt_mode.frsig = 0; |
1066 | put_pid(xchg(&vc->vt_pid, NULL)); | 1067 | put_pid(vc->vt_pid); |
1068 | vc->vt_pid = NULL; | ||
1067 | vc->vt_newvt = -1; | 1069 | vc->vt_newvt = -1; |
1068 | if (!in_interrupt()) /* Via keyboard.c:SAK() - akpm */ | 1070 | if (!in_interrupt()) /* Via keyboard.c:SAK() - akpm */ |
1069 | reset_palette(vc); | 1071 | reset_palette(vc); |
1070 | } | 1072 | } |
1071 | 1073 | ||
1074 | void vc_SAK(struct work_struct *work) | ||
1075 | { | ||
1076 | struct vc *vc_con = | ||
1077 | container_of(work, struct vc, SAK_work); | ||
1078 | struct vc_data *vc; | ||
1079 | struct tty_struct *tty; | ||
1080 | |||
1081 | acquire_console_sem(); | ||
1082 | vc = vc_con->d; | ||
1083 | if (vc) { | ||
1084 | tty = vc->vc_tty; | ||
1085 | /* | ||
1086 | * SAK should also work in all raw modes and reset | ||
1087 | * them properly. | ||
1088 | */ | ||
1089 | if (tty) | ||
1090 | __do_SAK(tty); | ||
1091 | reset_vc(vc); | ||
1092 | } | ||
1093 | release_console_sem(); | ||
1094 | } | ||
1095 | |||
1072 | /* | 1096 | /* |
1073 | * Performs the back end of a vt switch | 1097 | * Performs the back end of a vt switch |
1074 | */ | 1098 | */ |
diff --git a/drivers/char/watchdog/alim7101_wdt.c b/drivers/char/watchdog/alim7101_wdt.c index bf25d0a55a99..e5b2c2ee292c 100644 --- a/drivers/char/watchdog/alim7101_wdt.c +++ b/drivers/char/watchdog/alim7101_wdt.c | |||
@@ -417,10 +417,8 @@ module_init(alim7101_wdt_init); | |||
417 | module_exit(alim7101_wdt_unload); | 417 | module_exit(alim7101_wdt_unload); |
418 | 418 | ||
419 | static struct pci_device_id alim7101_pci_tbl[] __devinitdata = { | 419 | static struct pci_device_id alim7101_pci_tbl[] __devinitdata = { |
420 | { PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, | 420 | { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533) }, |
421 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 421 | { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) }, |
422 | { PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, | ||
423 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
424 | { } | 422 | { } |
425 | }; | 423 | }; |
426 | 424 | ||
diff --git a/drivers/char/watchdog/booke_wdt.c b/drivers/char/watchdog/booke_wdt.c index 488902231cc2..0e23f29f71ab 100644 --- a/drivers/char/watchdog/booke_wdt.c +++ b/drivers/char/watchdog/booke_wdt.c | |||
@@ -35,7 +35,7 @@ | |||
35 | #ifdef CONFIG_FSL_BOOKE | 35 | #ifdef CONFIG_FSL_BOOKE |
36 | #define WDT_PERIOD_DEFAULT 63 /* Ex. wdt_period=28 bus=333Mhz , reset=~40sec */ | 36 | #define WDT_PERIOD_DEFAULT 63 /* Ex. wdt_period=28 bus=333Mhz , reset=~40sec */ |
37 | #else | 37 | #else |
38 | #define WDT_PERIOD_DEFAULT 4 /* Refer to the PPC40x and PPC4xx manuals */ | 38 | #define WDT_PERIOD_DEFAULT 3 /* Refer to the PPC40x and PPC4xx manuals */ |
39 | #endif /* for timing information */ | 39 | #endif /* for timing information */ |
40 | 40 | ||
41 | u32 booke_wdt_enabled = 0; | 41 | u32 booke_wdt_enabled = 0; |
@@ -48,12 +48,22 @@ u32 booke_wdt_period = WDT_PERIOD_DEFAULT; | |||
48 | #endif | 48 | #endif |
49 | 49 | ||
50 | /* | 50 | /* |
51 | * booke_wdt_ping: | ||
52 | */ | ||
53 | static __inline__ void booke_wdt_ping(void) | ||
54 | { | ||
55 | mtspr(SPRN_TSR, TSR_ENW|TSR_WIS); | ||
56 | } | ||
57 | |||
58 | /* | ||
51 | * booke_wdt_enable: | 59 | * booke_wdt_enable: |
52 | */ | 60 | */ |
53 | static __inline__ void booke_wdt_enable(void) | 61 | static __inline__ void booke_wdt_enable(void) |
54 | { | 62 | { |
55 | u32 val; | 63 | u32 val; |
56 | 64 | ||
65 | /* clear status before enabling watchdog */ | ||
66 | booke_wdt_ping(); | ||
57 | val = mfspr(SPRN_TCR); | 67 | val = mfspr(SPRN_TCR); |
58 | val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period)); | 68 | val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period)); |
59 | 69 | ||
@@ -61,14 +71,6 @@ static __inline__ void booke_wdt_enable(void) | |||
61 | } | 71 | } |
62 | 72 | ||
63 | /* | 73 | /* |
64 | * booke_wdt_ping: | ||
65 | */ | ||
66 | static __inline__ void booke_wdt_ping(void) | ||
67 | { | ||
68 | mtspr(SPRN_TSR, TSR_ENW|TSR_WIS); | ||
69 | } | ||
70 | |||
71 | /* | ||
72 | * booke_wdt_write: | 74 | * booke_wdt_write: |
73 | */ | 75 | */ |
74 | static ssize_t booke_wdt_write (struct file *file, const char __user *buf, | 76 | static ssize_t booke_wdt_write (struct file *file, const char __user *buf, |
diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/char/watchdog/iTCO_wdt.c index 7eac922df867..fd8a44a08cd3 100644 --- a/drivers/char/watchdog/iTCO_wdt.c +++ b/drivers/char/watchdog/iTCO_wdt.c | |||
@@ -539,7 +539,7 @@ static int iTCO_wdt_ioctl (struct inode *inode, struct file *file, | |||
539 | * Kernel Interfaces | 539 | * Kernel Interfaces |
540 | */ | 540 | */ |
541 | 541 | ||
542 | static struct file_operations iTCO_wdt_fops = { | 542 | static const struct file_operations iTCO_wdt_fops = { |
543 | .owner = THIS_MODULE, | 543 | .owner = THIS_MODULE, |
544 | .llseek = no_llseek, | 544 | .llseek = no_llseek, |
545 | .write = iTCO_wdt_write, | 545 | .write = iTCO_wdt_write, |
diff --git a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c index 276577d08fba..4d730fdbd528 100644 --- a/drivers/char/watchdog/machzwd.c +++ b/drivers/char/watchdog/machzwd.c | |||
@@ -325,7 +325,7 @@ static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
325 | return put_user(0, p); | 325 | return put_user(0, p); |
326 | 326 | ||
327 | case WDIOC_KEEPALIVE: | 327 | case WDIOC_KEEPALIVE: |
328 | zf_ping(0); | 328 | zf_ping(NULL); |
329 | break; | 329 | break; |
330 | 330 | ||
331 | default: | 331 | default: |
diff --git a/drivers/char/watchdog/omap_wdt.c b/drivers/char/watchdog/omap_wdt.c index 6c6f97332dbb..84074a697dce 100644 --- a/drivers/char/watchdog/omap_wdt.c +++ b/drivers/char/watchdog/omap_wdt.c | |||
@@ -230,7 +230,7 @@ omap_wdt_ioctl(struct inode *inode, struct file *file, | |||
230 | } | 230 | } |
231 | } | 231 | } |
232 | 232 | ||
233 | static struct file_operations omap_wdt_fops = { | 233 | static const struct file_operations omap_wdt_fops = { |
234 | .owner = THIS_MODULE, | 234 | .owner = THIS_MODULE, |
235 | .write = omap_wdt_write, | 235 | .write = omap_wdt_write, |
236 | .ioctl = omap_wdt_ioctl, | 236 | .ioctl = omap_wdt_ioctl, |
diff --git a/drivers/char/watchdog/pc87413_wdt.c b/drivers/char/watchdog/pc87413_wdt.c index 1d447e32af41..a77a90717ad2 100644 --- a/drivers/char/watchdog/pc87413_wdt.c +++ b/drivers/char/watchdog/pc87413_wdt.c | |||
@@ -526,7 +526,7 @@ static int pc87413_notify_sys(struct notifier_block *this, | |||
526 | 526 | ||
527 | /* -- Module's structures ---------------------------------------*/ | 527 | /* -- Module's structures ---------------------------------------*/ |
528 | 528 | ||
529 | static struct file_operations pc87413_fops = { | 529 | static const struct file_operations pc87413_fops = { |
530 | .owner = THIS_MODULE, | 530 | .owner = THIS_MODULE, |
531 | .llseek = no_llseek, | 531 | .llseek = no_llseek, |
532 | .write = pc87413_write, | 532 | .write = pc87413_write, |
diff --git a/drivers/char/watchdog/pnx4008_wdt.c b/drivers/char/watchdog/pnx4008_wdt.c index 3a55fc6abcd8..ff6f1ca1e5e7 100644 --- a/drivers/char/watchdog/pnx4008_wdt.c +++ b/drivers/char/watchdog/pnx4008_wdt.c | |||
@@ -238,7 +238,7 @@ static int pnx4008_wdt_release(struct inode *inode, struct file *file) | |||
238 | return 0; | 238 | return 0; |
239 | } | 239 | } |
240 | 240 | ||
241 | static struct file_operations pnx4008_wdt_fops = { | 241 | static const struct file_operations pnx4008_wdt_fops = { |
242 | .owner = THIS_MODULE, | 242 | .owner = THIS_MODULE, |
243 | .llseek = no_llseek, | 243 | .llseek = no_llseek, |
244 | .write = pnx4008_wdt_write, | 244 | .write = pnx4008_wdt_write, |
diff --git a/drivers/char/watchdog/rm9k_wdt.c b/drivers/char/watchdog/rm9k_wdt.c index 7576a13e86bc..b4678839d3bb 100644 --- a/drivers/char/watchdog/rm9k_wdt.c +++ b/drivers/char/watchdog/rm9k_wdt.c | |||
@@ -95,7 +95,7 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be disabled once started"); | |||
95 | 95 | ||
96 | 96 | ||
97 | /* Kernel interfaces */ | 97 | /* Kernel interfaces */ |
98 | static struct file_operations fops = { | 98 | static const struct file_operations fops = { |
99 | .owner = THIS_MODULE, | 99 | .owner = THIS_MODULE, |
100 | .open = wdt_gpi_open, | 100 | .open = wdt_gpi_open, |
101 | .release = wdt_gpi_release, | 101 | .release = wdt_gpi_release, |
diff --git a/drivers/char/watchdog/smsc37b787_wdt.c b/drivers/char/watchdog/smsc37b787_wdt.c index 9f56913b484f..a9681d580dd3 100644 --- a/drivers/char/watchdog/smsc37b787_wdt.c +++ b/drivers/char/watchdog/smsc37b787_wdt.c | |||
@@ -510,7 +510,7 @@ static int wb_smsc_wdt_notify_sys(struct notifier_block *this, unsigned long cod | |||
510 | 510 | ||
511 | /* -- Module's structures ---------------------------------------*/ | 511 | /* -- Module's structures ---------------------------------------*/ |
512 | 512 | ||
513 | static struct file_operations wb_smsc_wdt_fops = | 513 | static const struct file_operations wb_smsc_wdt_fops = |
514 | { | 514 | { |
515 | .owner = THIS_MODULE, | 515 | .owner = THIS_MODULE, |
516 | .llseek = no_llseek, | 516 | .llseek = no_llseek, |
diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 7768b55487c8..c960ec110dd7 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c | |||
@@ -323,7 +323,7 @@ wdt_notify_sys(struct notifier_block *this, unsigned long code, | |||
323 | * Kernel Interfaces | 323 | * Kernel Interfaces |
324 | */ | 324 | */ |
325 | 325 | ||
326 | static struct file_operations wdt_fops = { | 326 | static const struct file_operations wdt_fops = { |
327 | .owner = THIS_MODULE, | 327 | .owner = THIS_MODULE, |
328 | .llseek = no_llseek, | 328 | .llseek = no_llseek, |
329 | .write = wdt_write, | 329 | .write = wdt_write, |