This source file includes following definitions.
- lp_char_polled
- lp_char_interrupt
- lp_interrupt
- lp_write
- lp_write
- lp_write
- lp_lseek
- lp_open
- lp_release
- lp_ioctl
- lp_init
- lp_setup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 #include <linux/config.h>
38 #include <linux/errno.h>
39 #include <linux/kernel.h>
40 #include <linux/major.h>
41 #include <linux/sched.h>
42 #include <asm/irq.h>
43
44 #ifdef CONFIG_AMIGA
45 #include <asm/amigaints.h>
46 #ifdef CONFIG_MULTIFACE_III_LP
47 #include <linux/lp_mfc.h>
48 #endif
49 #endif
50 #ifdef CONFIG_ATARI
51 #include <asm/atarihw.h>
52 #include <asm/atariints.h>
53 #endif
54
55 #include <linux/lp_m68k.h>
56 #include <linux/lp_intern.h>
57 #include <linux/malloc.h>
58 #include <linux/interrupt.h>
59
60 #include <asm/segment.h>
61 #include <asm/system.h>
62
63
64
65
66
67
68
69 #define FORCE_POLLING 0
70 #define FORCE_INTERRUPT 1
71 #define PREFER_INTERRUPT 2
72
73 #define WHICH_DRIVER FORCE_INTERRUPT
74
75 #define MAX_LP 3
76
77 struct lp_struct lp_table[MAX_LP] = {{0,},};
78
79 static int max_lp;
80
81
82
83
84
85
86 #define LP_DEBUG
87 #undef LP_DEBUG
88
89
90 #if WHICH_DRIVER != FORCE_INTERRUPT
91 #ifdef LP_DEBUG
92 static int lp_max_count = 1;
93 #endif
94
95 static int lp_char_polled(char lpchar, int dev)
96 {
97 unsigned long count = 0;
98
99 do {
100 count ++;
101 if(need_resched)
102 schedule();
103 } while (lp_table[dev].lp_is_busy(dev) && count < lp_table[dev].chars);
104
105 if (count == lp_table[dev].chars) {
106 return 0;
107
108 }
109 #ifdef LP_DEBUG
110 if (count > lp_max_count) {
111 printk("lp success after %d counts.\n",count);
112 lp_max_count = count;
113 }
114 #endif
115 lp_table[dev].lp_out(lpchar, dev);
116 return 1;
117 }
118 #endif
119
120
121 #ifdef LP_DEBUG
122 unsigned int lp_total_chars = 0;
123 unsigned int lp_last_call = 0;
124 #endif
125
126
127 #if WHICH_DRIVER != FORCE_POLLING
128 static __inline__ int lp_char_interrupt(char lpchar, int dev)
129 {
130 if (!lp_table[dev].lp_is_busy(dev)) {
131 lp_table[dev].lp_out(lpchar,dev);
132 return 1;
133 }
134 return 0;
135 }
136
137 static int lp_error;
138
139 static void lp_interrupt(int irq, struct pt_regs *fp, void *dummy)
140 {
141 unsigned long flags;
142 int dev;
143
144 for (dev = 0; dev < max_lp; dev++) {
145 if (lp_table[dev].lp_my_interrupt(dev) != 0)
146 if (lp_table[dev].do_print)
147 {
148 if (lp_table[dev].copy_size)
149 {
150 save_flags(flags);
151 cli();
152 if (lp_char_interrupt(lp_table[dev].lp_buffer[lp_table[dev].bytes_written], dev)) {
153 --lp_table[dev].copy_size;
154 ++lp_table[dev].bytes_written;
155 restore_flags(flags);
156 }
157 else
158 {
159 lp_table[dev].do_print = 0;
160 restore_flags(flags);
161 lp_error = 1;
162 wake_up_interruptible(&lp_table[dev].lp_wait_q);
163 }
164 }
165 else
166 {
167 lp_table[dev].do_print = 0;
168 lp_error = 0;
169 wake_up_interruptible(&lp_table[dev].lp_wait_q);
170 }
171
172 }
173 }
174 }
175
176 #if WHICH_DRIVER == FORCE_INTERRUPT
177 static int lp_write(struct inode *inode, struct file *file,
178 const char *buf, int count)
179 #else
180 static int lp_write_interrupt(struct inode *inode, struct file *file,
181 const char *buf, int count)
182 #endif
183 {
184 unsigned long total_bytes_written = 0;
185 unsigned int flags;
186 int rc;
187 int dev = MINOR(inode->i_rdev);
188
189 do {
190 lp_table[dev].do_print = 0;
191 lp_table[dev].bytes_written = 0;
192 lp_error = 0;
193 lp_table[dev].copy_size = (count <= LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE);
194 memcpy_fromfs(lp_table[dev].lp_buffer, buf, lp_table[dev].copy_size);
195 while (lp_table[dev].copy_size) {
196 save_flags(flags);
197 cli();
198 lp_table[dev].do_print = 1;
199 if (lp_char_interrupt(lp_table[dev].lp_buffer[lp_table[dev].bytes_written], dev)) {
200 ++lp_table[dev].bytes_written;
201 --lp_table[dev].copy_size;
202 lp_error = 0;
203 } else {
204 lp_table[dev].do_print = 0;
205 lp_error = 1;
206 }
207 if (lp_error) {
208
209
210
211
212 current->timeout = jiffies + LP_TIMEOUT_POLLED;
213 } else {
214 current->timeout = jiffies + LP_TIMEOUT_INTERRUPT;
215 }
216
217 interruptible_sleep_on(&lp_table[dev].lp_wait_q);
218 restore_flags(flags);
219
220
221
222
223 lp_table[dev].do_print = 0;
224 rc = total_bytes_written + lp_table[dev].bytes_written;
225
226 if (current->signal & ~current->blocked) {
227 if (rc)
228 return rc;
229 else
230 return -EINTR;
231 }
232 if (lp_error) {
233
234
235
236
237
238 if (lp_table[dev].lp_has_pout(dev)) {
239 printk(KERN_NOTICE "lp%d: paper-out\n",dev);
240 if (!rc) rc = -ENOSPC;
241 } else if (!lp_table[dev].lp_is_online(dev)) {
242 printk(KERN_NOTICE "lp%d: off-line\n",dev);
243 if (!rc) rc = -EIO;
244 } else if (lp_table[dev].lp_is_busy(dev)) {
245 printk(KERN_NOTICE "lp%d: on fire\n",dev);
246 if (!rc) rc = -EIO;
247 }
248 if (lp_table[dev].flags & LP_ABORT)
249 return rc;
250 }
251
252
253
254
255
256 if (!lp_table[dev].copy_size) {
257 total_bytes_written += lp_table[dev].bytes_written;
258 buf += lp_table[dev].bytes_written;
259 count -= lp_table[dev].bytes_written;
260 }
261 }
262 } while (count > 0);
263 return total_bytes_written;
264 }
265 #endif
266
267 #if WHICH_DRIVER != FORCE_INTERRUPT
268 #if WHICH_DRIVER == FORCE_POLLING
269 static int lp_write(struct inode *inode, struct file *file,
270 const char *buf, int count)
271 #else
272 static int lp_write_polled(struct inode *inode, struct file *file,
273 const char *buf, int count)
274 #endif
275 {
276 char *temp = buf;
277 int dev = MINOR(inode->i_rdev);
278
279 #ifdef LP_DEBUG
280 if (jiffies-lp_last_call > lp_table[dev].time) {
281 lp_total_chars = 0;
282 lp_max_count = 1;
283 }
284 lp_last_call = jiffies;
285 #endif
286
287 temp = buf;
288 while (count > 0) {
289 if (lp_char_polled(get_user(temp), dev)) {
290
291 count--; temp++;
292 #ifdef LP_DEBUG
293 lp_total_chars++;
294 #endif
295 } else {
296 if (lp_table[dev].lp_has_pout(dev)) {
297 printk(KERN_NOTICE "lp%d: out of paper\n",dev);
298 if (lp_table[dev].flags & LP_ABORT)
299 return temp - buf ? temp-buf : -ENOSPC;
300 current->state = TASK_INTERRUPTIBLE;
301 current->timeout = jiffies + LP_TIMEOUT_POLLED;
302 schedule();
303 } else if (!lp_table[dev].lp_is_online(dev)) {
304 printk(KERN_NOTICE "lp%d: off-line\n",dev);
305 if (lp_table[dev].flags & LP_ABORT)
306 return temp - buf ? temp-buf : -EIO;
307 current->state = TASK_INTERRUPTIBLE;
308 current->timeout = jiffies + LP_TIMEOUT_POLLED;
309 schedule();
310 } else
311
312 if (lp_table[dev].lp_is_busy(dev)) {
313 printk(KERN_NOTICE "lp%d: on fire\n",dev);
314 if (lp_table[dev].flags & LP_ABORT)
315 return temp - buf ? temp-buf : -EFAULT;
316 current->state = TASK_INTERRUPTIBLE;
317 current->timeout = jiffies + LP_TIMEOUT_POLLED;
318 schedule();
319 }
320
321
322 if (current->signal & ~current->blocked) {
323 if (temp != buf)
324 return temp-buf;
325 else
326 return -EINTR;
327 }
328 #ifdef LP_DEBUG
329 printk("lp sleeping at %d characters for %d jiffies\n",
330 lp_total_chars, lp_table[dev].time);
331 lp_total_chars = 0;
332 #endif
333 current->state = TASK_INTERRUPTIBLE;
334 current->timeout = jiffies + lp_table[dev].time;
335 schedule();
336 }
337 }
338 return temp - buf;
339 }
340 #endif
341
342 static unsigned int lp_irq = 0;
343
344 #if WHICH_DRIVER == PREFER_INTERRUPT
345 static int lp_write(struct inode *inode, struct file *file,
346 const char *buf, int count)
347 {
348 if (lp_irq)
349 return lp_write_interrupt(inode, file, buf, count);
350 else
351 return lp_write_polled(inode, file, buf, count);
352 }
353 #endif
354
355 static int lp_lseek(struct inode *inode, struct file *file,
356 off_t offset, int origin)
357 {
358 return -ESPIPE;
359 }
360
361 static int lp_open(struct inode *inode, struct file *file)
362 {
363 int dev = MINOR(inode->i_rdev);
364
365 if (dev >= max_lp)
366 return -ENODEV;
367 if (!(lp_table[dev].flags & LP_EXIST))
368 return -ENODEV;
369 if (lp_table[dev].flags & LP_BUSY)
370 return -EBUSY;
371
372 lp_table[dev].flags |= LP_BUSY;
373
374 return 0;
375 }
376
377 static void lp_release(struct inode *inode, struct file *file)
378 {
379 lp_table[MINOR(inode->i_rdev)].flags &= ~LP_BUSY;
380 }
381
382
383 static int lp_ioctl(struct inode *inode, struct file *file,
384 unsigned int cmd, unsigned long arg)
385 {
386 unsigned int minor = MINOR(inode->i_rdev);
387 int retval = 0;
388
389 #ifdef LP_DEBUG
390 printk("lp%d ioctl, cmd: 0x%x, arg: 0x%x\n", minor, cmd, arg);
391 #endif
392 if (minor >= max_lp)
393 return -ENODEV;
394 if (!(lp_table[minor].flags & LP_EXIST))
395 return -ENODEV;
396 switch (cmd) {
397 case LPTIME:
398 lp_table[minor].time = arg;
399 break;
400 case LPCHAR:
401 lp_table[minor].chars = arg;
402 break;
403 case LPABORT:
404 if (arg)
405 lp_table[minor].flags |= LP_ABORT;
406 else
407 lp_table[minor].flags &= ~LP_ABORT;
408 break;
409 case LPWAIT:
410 lp_table[minor].wait = arg;
411 break;
412 case LPSETIRQ:
413 case LPGETIRQ:
414 retval = lp_irq;
415 break;
416 default:
417 retval = -EINVAL;
418 }
419 return retval;
420 }
421
422
423 static struct file_operations lp_fops = {
424 lp_lseek,
425 NULL,
426 lp_write,
427 NULL,
428 NULL,
429 lp_ioctl,
430 NULL,
431 lp_open,
432 lp_release
433 };
434
435
436 int lp_init(void)
437 {
438 extern char m68k_debug_device[];
439
440 if (!strcmp( m68k_debug_device, "par" ))
441 return -EBUSY;
442
443 if (register_chrdev(LP_MAJOR,"lp", &lp_fops)) {
444 printk("unable to get major %d for line printer\n", LP_MAJOR);
445 return -EBUSY;
446 }
447
448 #if WHICH_DRIVER == FORCE_POLLING
449 lp_irq = 0;
450 printk(KERN_INFO "lp_init: lp using polling driver\n");
451 #else
452
453 #ifdef CONFIG_AMIGA
454 if (MACH_IS_AMIGA && AMIGAHW_PRESENT(AMI_PARALLEL))
455 lp_irq = add_isr(IRQ_AMIGA_CIAA_FLG, lp_interrupt, 0,
456 NULL, "printer");
457 #endif
458 #ifdef CONFIG_ATARI
459 if (MACH_IS_ATARI)
460 lp_irq = add_isr(IRQ_MFP_BUSY, lp_interrupt, IRQ_TYPE_SLOW,
461 NULL, "printer");
462 #endif
463
464 if (lp_irq)
465 printk(KERN_INFO "lp_init: lp using interrupt\n");
466 else
467
468 #if WHICH_DRIVER == PREFER_INTERRUPT
469 printk(KERN_INFO "lp_init: lp using polling driver\n");
470 #else
471 printk(KERN_WARNING "lp_init: can't get interrupt, and polling driver not configured\n");
472 #endif
473 #endif
474
475 max_lp = 0;
476 max_lp += lp_internal_init(lp_table, max_lp, MAX_LP, WHICH_DRIVER);
477 #ifdef CONFIG_MULTIFACE_III_LP
478 max_lp += lp_mfc_init(lp_table, max_lp, MAX_LP, WHICH_DRIVER);
479 #if WHICH_DRIVER != FORCE_POLLING
480 add_isr(IRQ_AMIGA_PORTS, lp_interrupt, 0, NULL,
481 "Multiface III printer");
482 #endif
483 #endif
484 return 0;
485 }
486
487
488
489
490 void lp_setup(char *str, int *ints)
491 {
492 }