This source file includes following definitions.
- lp_reset
- lp_char
- lp_write
- lp_lseek
- lp_open
- lp_release
- lp_ioctl
- lp_init
1
2
3
4 #include <linux/lp.h>
5
6
7
8
9
10
11
12 #undef LP_DEBUG
13
14 static int lp_reset(int minor)
15 {
16 int testvalue;
17
18
19 outb(0, LP_C(minor));
20 for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
21 ;
22 outb(LP_PSELECP | LP_PINITP, LP_C(minor));
23 return LP_S(minor);
24 }
25
26 #ifdef LP_DEBUG
27 static int lp_max_count = 1;
28 #endif
29
30 static int lp_char(char lpchar, int minor)
31 {
32 int retval = 0, wait = 0;
33 unsigned long count = 0;
34
35 outb(lpchar, LP_B(minor));
36 do {
37 retval = LP_S(minor);
38 count ++;
39 if(need_resched)
40 schedule();
41 } while(!(retval & LP_PBUSY) && count < LP_CHAR(minor));
42
43 if (count == LP_CHAR(minor)) {
44 return 0;
45
46 }
47 #ifdef LP_DEBUG
48 if (count > lp_max_count) {
49 printk("lp success after %d counts.\n",count);
50 lp_max_count=count;
51 }
52 #endif
53
54
55 while(wait != LP_WAIT(minor)) wait++;
56
57 outb(( LP_PSELECP | LP_PINITP | LP_PSTROBE ), ( LP_C( minor )));
58 while(wait) wait--;
59
60 outb(( LP_PSELECP | LP_PINITP ), ( LP_C( minor )));
61
62 return LP_S(minor);
63 }
64
65 #ifdef LP_DEBUG
66 unsigned int lp_total_chars = 0;
67 unsigned int lp_last_call = 0;
68 #endif
69
70 static int lp_write(struct inode * inode, struct file * file, char * buf, int count)
71 {
72 int retval;
73 unsigned int minor = MINOR(inode->i_rdev);
74 char c, *temp = buf;
75
76 #ifdef LP_DEBUG
77 if (jiffies-lp_last_call > LP_TIME(minor)) {
78 lp_total_chars = 0;
79 lp_max_count = 1;
80 }
81 lp_last_call = jiffies;
82 #endif
83
84 temp = buf;
85 while (count > 0) {
86 c = get_fs_byte(temp);
87 retval = lp_char(c, minor);
88
89 if (retval) { count--; temp++;
90 #ifdef LP_DEBUG
91 lp_total_chars++;
92 #endif
93 }
94 if (!retval) {
95
96 if (current->signal & ~current->blocked) {
97 if (count > 0) return -EINTR;
98 }
99 #ifdef LP_DEBUG
100 printk("lp sleeping at %d characters for %d jiffies\n",
101 lp_total_chars, LP_TIME(minor));
102 lp_total_chars=0;
103 #endif
104 current->state = TASK_INTERRUPTIBLE;
105 current->timeout = jiffies + LP_TIME(minor);
106 schedule();
107
108
109
110
111 if (!(LP_S(minor) & LP_BUSY)) {
112 current->state = TASK_INTERRUPTIBLE;
113 current->timeout = jiffies + LP_TIMEOUT;
114 schedule();
115 if (!(LP_S(minor) & LP_BUSY))
116 printk("lp%d timeout\n", minor);
117 }
118 } else {
119 if (retval & LP_POUTPA) {
120 printk("lp%d out of paper\n", minor);
121 if(LP_F(minor) && LP_ABORT)
122 return temp-buf?temp-buf:-ENOSPC;
123 current->state = TASK_INTERRUPTIBLE;
124 current->timeout = jiffies + LP_TIMEOUT;
125 schedule();
126 } else
127
128 if (!(retval & LP_PSELECD)) {
129 printk("lp%d off-line\n", minor);
130 if(LP_F(minor) && LP_ABORT)
131 return temp-buf?temp-buf:-EIO;
132 current->state = TASK_INTERRUPTIBLE;
133 current->timeout = jiffies + LP_TIMEOUT;
134 schedule();
135 } else
136
137
138 if (!(retval & LP_PERRORP)) {
139 printk("lp%d on fire\n", minor);
140 if(LP_F(minor) && LP_ABORT)
141 return temp-buf?temp-buf:-EFAULT;
142 current->state = TASK_INTERRUPTIBLE;
143 current->timeout = jiffies + LP_TIMEOUT;
144 schedule();
145 }
146 }
147 }
148 return temp-buf;
149 }
150
151
152 static int lp_lseek(struct inode * inode, struct file * file,
153 off_t offset, int origin)
154 {
155 return -EINVAL;
156 }
157
158 static int lp_open(struct inode * inode, struct file * file)
159 {
160 unsigned int minor = MINOR(inode->i_rdev);
161
162 if (minor >= LP_NO)
163 return -ENODEV;
164 if ((LP_F(minor) & LP_EXIST) == 0)
165 return -ENODEV;
166 if (LP_F(minor) & LP_BUSY)
167 return -EBUSY;
168 LP_F(minor) |= LP_BUSY;
169 return 0;
170 }
171
172 static void lp_release(struct inode * inode, struct file * file)
173 {
174 unsigned int minor = MINOR(inode->i_rdev);
175
176 LP_F(minor) &= ~LP_BUSY;
177 }
178
179
180 static int lp_ioctl(struct inode *inode, struct file *file,
181 unsigned int cmd, unsigned int arg)
182 {
183 unsigned int minor = MINOR(inode->i_rdev);
184
185 #ifdef LP_DEBUG
186 printk("lp%d ioctl, cmd: 0x%x, arg: 0x%x\n", minor, cmd, arg);
187 #endif
188 if (minor >= LP_NO)
189 return -ENODEV;
190 if ((LP_F(minor) & LP_EXIST) == 0)
191 return -ENODEV;
192 switch ( cmd ) {
193 case LPTIME:
194 LP_TIME(minor) = arg;
195 break;
196 case LPCHAR:
197 LP_CHAR(minor) = arg;
198 break;
199 case LPABORT:
200 if(arg)
201 LP_F(minor) |= LP_ABORT;
202 else LP_F(minor) &= ~LP_ABORT;
203 break;
204 case LPWAIT:
205 LP_WAIT(minor) = arg;
206 break;
207 default: arg = -EINVAL;
208 }
209 return arg;
210 }
211
212
213 static struct file_operations lp_fops = {
214 lp_lseek,
215 NULL,
216 lp_write,
217 NULL,
218 NULL,
219 lp_ioctl,
220 NULL,
221 lp_open,
222 lp_release
223 };
224
225 long lp_init(long kmem_start)
226 {
227 int offset = 0;
228 unsigned int testvalue = 0;
229 int count = 0;
230
231 chrdev_fops[6] = &lp_fops;
232
233 for (offset = 0; offset < LP_NO; offset++) {
234
235 outb( LP_DUMMY, LP_B(offset));
236 for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
237 ;
238 testvalue = inb(LP_B(offset));
239 if (testvalue != 255) {
240 LP_F(offset) |= LP_EXIST;
241 lp_reset(offset);
242 printk("lp_init: lp%d exists (%d)\n", offset, testvalue);
243 count++;
244 }
245 }
246 if (count == 0)
247 printk("lp_init: no lp devices found\n");
248 return kmem_start;
249 }