Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * drivers/sbus/char/bpp.c | |
3 | * | |
4 | * Copyright (c) 1995 Picture Elements | |
5 | * Stephen Williams (steve@icarus.com) | |
6 | * Gus Baldauf (gbaldauf@ix.netcom.com) | |
7 | * | |
8 | * Linux/SPARC port by Peter Zaitcev. | |
9 | * Integration into SPARC tree by Tom Dyas. | |
10 | */ | |
11 | ||
12 | ||
13 | #include <linux/kernel.h> | |
14 | #include <linux/module.h> | |
15 | #include <linux/fs.h> | |
16 | #include <linux/errno.h> | |
17 | #include <linux/sched.h> | |
1da177e4 LT |
18 | #include <linux/spinlock.h> |
19 | #include <linux/timer.h> | |
20 | #include <linux/ioport.h> | |
21 | #include <linux/major.h> | |
1da177e4 LT |
22 | |
23 | #include <asm/uaccess.h> | |
24 | #include <asm/io.h> | |
25 | ||
26 | #if defined(__i386__) | |
27 | # include <asm/system.h> | |
28 | #endif | |
29 | ||
30 | #if defined(__sparc__) | |
31 | # include <linux/init.h> | |
32 | # include <linux/delay.h> /* udelay() */ | |
33 | ||
34 | # include <asm/oplib.h> /* OpenProm Library */ | |
35 | # include <asm/sbus.h> | |
36 | #endif | |
37 | ||
38 | #include <asm/bpp.h> | |
39 | ||
40 | #define BPP_PROBE_CODE 0x55 | |
41 | #define BPP_DELAY 100 | |
42 | ||
43 | static const unsigned BPP_MAJOR = LP_MAJOR; | |
0a6db7dc | 44 | static const char *bpp_dev_name = "bpp"; |
1da177e4 LT |
45 | |
46 | /* When switching from compatibility to a mode where I can read, try | |
47 | the following mode first. */ | |
48 | ||
49 | /* const unsigned char DEFAULT_ECP = 0x10; */ | |
50 | static const unsigned char DEFAULT_ECP = 0x30; | |
51 | static const unsigned char DEFAULT_NIBBLE = 0x00; | |
52 | ||
53 | /* | |
54 | * These are 1284 time constraints, in units of jiffies. | |
55 | */ | |
56 | ||
57 | static const unsigned long TIME_PSetup = 1; | |
58 | static const unsigned long TIME_PResponse = 6; | |
59 | static const unsigned long TIME_IDLE_LIMIT = 2000; | |
60 | ||
61 | /* | |
62 | * One instance per supported subdevice... | |
63 | */ | |
64 | # define BPP_NO 3 | |
65 | ||
66 | enum IEEE_Mode { COMPATIBILITY, NIBBLE, ECP, ECP_RLE, EPP }; | |
67 | ||
68 | struct inst { | |
69 | unsigned present : 1; /* True if the hardware exists */ | |
70 | unsigned enhanced : 1; /* True if the hardware in "enhanced" */ | |
71 | unsigned opened : 1; /* True if the device is opened already */ | |
72 | unsigned run_flag : 1; /* True if waiting for a repeate byte */ | |
73 | ||
74 | unsigned char direction; /* 0 --> out, 0x20 --> IN */ | |
75 | unsigned char pp_state; /* State of host controlled pins. */ | |
76 | enum IEEE_Mode mode; | |
77 | ||
78 | unsigned char run_length; | |
79 | unsigned char repeat_byte; | |
1da177e4 LT |
80 | }; |
81 | ||
82 | static struct inst instances[BPP_NO]; | |
83 | ||
84 | #if defined(__i386__) | |
85 | ||
86 | static const unsigned short base_addrs[BPP_NO] = { 0x278, 0x378, 0x3bc }; | |
87 | ||
88 | /* | |
89 | * These are for data access. | |
90 | * Control lines accesses are hidden in set_bits() and get_bits(). | |
91 | * The exception is the probe procedure, which is system-dependent. | |
92 | */ | |
93 | #define bpp_outb_p(data, base) outb_p((data), (base)) | |
94 | #define bpp_inb(base) inb(base) | |
95 | #define bpp_inb_p(base) inb_p(base) | |
96 | ||
97 | /* | |
98 | * This method takes the pin values mask and sets the hardware pins to | |
99 | * the requested value: 1 == high voltage, 0 == low voltage. This | |
100 | * burries the annoying PC bit inversion and preserves the direction | |
101 | * flag. | |
102 | */ | |
103 | static void set_pins(unsigned short pins, unsigned minor) | |
104 | { | |
105 | unsigned char bits = instances[minor].direction; /* == 0x20 */ | |
106 | ||
107 | if (! (pins & BPP_PP_nStrobe)) bits |= 1; | |
108 | if (! (pins & BPP_PP_nAutoFd)) bits |= 2; | |
109 | if ( pins & BPP_PP_nInit) bits |= 4; | |
110 | if (! (pins & BPP_PP_nSelectIn)) bits |= 8; | |
111 | ||
112 | instances[minor].pp_state = bits; | |
113 | ||
114 | outb_p(bits, base_addrs[minor]+2); | |
115 | } | |
116 | ||
117 | static unsigned short get_pins(unsigned minor) | |
118 | { | |
119 | unsigned short bits = 0; | |
120 | ||
121 | unsigned value = instances[minor].pp_state; | |
122 | if (! (value & 0x01)) bits |= BPP_PP_nStrobe; | |
123 | if (! (value & 0x02)) bits |= BPP_PP_nAutoFd; | |
124 | if (value & 0x04) bits |= BPP_PP_nInit; | |
125 | if (! (value & 0x08)) bits |= BPP_PP_nSelectIn; | |
126 | ||
127 | value = inb_p(base_addrs[minor]+1); | |
128 | if (value & 0x08) bits |= BPP_GP_nFault; | |
129 | if (value & 0x10) bits |= BPP_GP_Select; | |
130 | if (value & 0x20) bits |= BPP_GP_PError; | |
131 | if (value & 0x40) bits |= BPP_GP_nAck; | |
132 | if (! (value & 0x80)) bits |= BPP_GP_Busy; | |
133 | ||
134 | return bits; | |
135 | } | |
136 | ||
137 | #endif /* __i386__ */ | |
138 | ||
139 | #if defined(__sparc__) | |
140 | ||
141 | /* | |
142 | * Register block | |
143 | */ | |
144 | /* DMA registers */ | |
145 | #define BPP_CSR 0x00 | |
146 | #define BPP_ADDR 0x04 | |
147 | #define BPP_BCNT 0x08 | |
148 | #define BPP_TST_CSR 0x0C | |
149 | /* Parallel Port registers */ | |
150 | #define BPP_HCR 0x10 | |
151 | #define BPP_OCR 0x12 | |
152 | #define BPP_DR 0x14 | |
153 | #define BPP_TCR 0x15 | |
154 | #define BPP_OR 0x16 | |
155 | #define BPP_IR 0x17 | |
156 | #define BPP_ICR 0x18 | |
157 | #define BPP_SIZE 0x1A | |
158 | ||
beb7dd86 | 159 | /* BPP_CSR. Bits of type RW1 are cleared with writing '1'. */ |
1da177e4 LT |
160 | #define P_DEV_ID_MASK 0xf0000000 /* R */ |
161 | #define P_DEV_ID_ZEBRA 0x40000000 | |
162 | #define P_DEV_ID_L64854 0xa0000000 /* == NCR 89C100+89C105. Pity. */ | |
163 | #define P_NA_LOADED 0x08000000 /* R NA wirtten but was not used */ | |
164 | #define P_A_LOADED 0x04000000 /* R */ | |
165 | #define P_DMA_ON 0x02000000 /* R DMA is not disabled */ | |
166 | #define P_EN_NEXT 0x01000000 /* RW */ | |
167 | #define P_TCI_DIS 0x00800000 /* RW TCI forbidden from interrupts */ | |
168 | #define P_DIAG 0x00100000 /* RW Disables draining and resetting | |
169 | of P-FIFO on loading of P_ADDR*/ | |
170 | #define P_BURST_SIZE 0x000c0000 /* RW SBus burst size */ | |
171 | #define P_BURST_8 0x00000000 | |
172 | #define P_BURST_4 0x00040000 | |
173 | #define P_BURST_1 0x00080000 /* "No burst" write */ | |
174 | #define P_TC 0x00004000 /* RW1 Term Count, can be cleared when | |
175 | P_EN_NEXT=1 */ | |
176 | #define P_EN_CNT 0x00002000 /* RW */ | |
177 | #define P_EN_DMA 0x00000200 /* RW */ | |
178 | #define P_WRITE 0x00000100 /* R DMA dir, 1=to ram, 0=to port */ | |
179 | #define P_RESET 0x00000080 /* RW */ | |
180 | #define P_SLAVE_ERR 0x00000040 /* RW1 Access size error */ | |
181 | #define P_INVALIDATE 0x00000020 /* W Drop P-FIFO */ | |
182 | #define P_INT_EN 0x00000010 /* RW OK to P_INT_PEND||P_ERR_PEND */ | |
183 | #define P_DRAINING 0x0000000c /* R P-FIFO is draining to memory */ | |
184 | #define P_ERR_PEND 0x00000002 /* R */ | |
185 | #define P_INT_PEND 0x00000001 /* R */ | |
186 | ||
187 | /* BPP_HCR. Time is in increments of SBus clock. */ | |
188 | #define P_HCR_TEST 0x8000 /* Allows buried counters to be read */ | |
189 | #define P_HCR_DSW 0x7f00 /* Data strobe width (in ticks) */ | |
190 | #define P_HCR_DDS 0x007f /* Data setup before strobe (in ticks) */ | |
191 | ||
192 | /* BPP_OCR. */ | |
193 | #define P_OCR_MEM_CLR 0x8000 | |
194 | #define P_OCR_DATA_SRC 0x4000 /* ) */ | |
195 | #define P_OCR_DS_DSEL 0x2000 /* ) Bidirectional */ | |
196 | #define P_OCR_BUSY_DSEL 0x1000 /* ) selects */ | |
197 | #define P_OCR_ACK_DSEL 0x0800 /* ) */ | |
198 | #define P_OCR_EN_DIAG 0x0400 | |
199 | #define P_OCR_BUSY_OP 0x0200 /* Busy operation */ | |
200 | #define P_OCR_ACK_OP 0x0100 /* Ack operation */ | |
201 | #define P_OCR_SRST 0x0080 /* Reset state machines. Not selfcleaning. */ | |
202 | #define P_OCR_IDLE 0x0008 /* PP data transfer state machine is idle */ | |
203 | #define P_OCR_V_ILCK 0x0002 /* Versatec faded. Zebra only. */ | |
204 | #define P_OCR_EN_VER 0x0001 /* Enable Versatec (0 - enable). Zebra only. */ | |
205 | ||
206 | /* BPP_TCR */ | |
207 | #define P_TCR_DIR 0x08 | |
208 | #define P_TCR_BUSY 0x04 | |
209 | #define P_TCR_ACK 0x02 | |
210 | #define P_TCR_DS 0x01 /* Strobe */ | |
211 | ||
212 | /* BPP_OR */ | |
213 | #define P_OR_V3 0x20 /* ) */ | |
214 | #define P_OR_V2 0x10 /* ) on Zebra only */ | |
215 | #define P_OR_V1 0x08 /* ) */ | |
216 | #define P_OR_INIT 0x04 | |
217 | #define P_OR_AFXN 0x02 /* Auto Feed */ | |
218 | #define P_OR_SLCT_IN 0x01 | |
219 | ||
220 | /* BPP_IR */ | |
221 | #define P_IR_PE 0x04 | |
222 | #define P_IR_SLCT 0x02 | |
223 | #define P_IR_ERR 0x01 | |
224 | ||
225 | /* BPP_ICR */ | |
226 | #define P_DS_IRQ 0x8000 /* RW1 */ | |
227 | #define P_ACK_IRQ 0x4000 /* RW1 */ | |
228 | #define P_BUSY_IRQ 0x2000 /* RW1 */ | |
229 | #define P_PE_IRQ 0x1000 /* RW1 */ | |
230 | #define P_SLCT_IRQ 0x0800 /* RW1 */ | |
231 | #define P_ERR_IRQ 0x0400 /* RW1 */ | |
232 | #define P_DS_IRQ_EN 0x0200 /* RW Always on rising edge */ | |
233 | #define P_ACK_IRQ_EN 0x0100 /* RW Always on rising edge */ | |
234 | #define P_BUSY_IRP 0x0080 /* RW 1= rising edge */ | |
235 | #define P_BUSY_IRQ_EN 0x0040 /* RW */ | |
236 | #define P_PE_IRP 0x0020 /* RW 1= rising edge */ | |
237 | #define P_PE_IRQ_EN 0x0010 /* RW */ | |
238 | #define P_SLCT_IRP 0x0008 /* RW 1= rising edge */ | |
239 | #define P_SLCT_IRQ_EN 0x0004 /* RW */ | |
240 | #define P_ERR_IRP 0x0002 /* RW1 1= rising edge */ | |
241 | #define P_ERR_IRQ_EN 0x0001 /* RW */ | |
242 | ||
243 | static void __iomem *base_addrs[BPP_NO]; | |
244 | ||
245 | #define bpp_outb_p(data, base) sbus_writeb(data, (base) + BPP_DR) | |
246 | #define bpp_inb_p(base) sbus_readb((base) + BPP_DR) | |
247 | #define bpp_inb(base) sbus_readb((base) + BPP_DR) | |
248 | ||
249 | static void set_pins(unsigned short pins, unsigned minor) | |
250 | { | |
251 | void __iomem *base = base_addrs[minor]; | |
252 | unsigned char bits_tcr = 0, bits_or = 0; | |
253 | ||
254 | if (instances[minor].direction & 0x20) bits_tcr |= P_TCR_DIR; | |
255 | if ( pins & BPP_PP_nStrobe) bits_tcr |= P_TCR_DS; | |
256 | ||
257 | if ( pins & BPP_PP_nAutoFd) bits_or |= P_OR_AFXN; | |
258 | if (! (pins & BPP_PP_nInit)) bits_or |= P_OR_INIT; | |
259 | if (! (pins & BPP_PP_nSelectIn)) bits_or |= P_OR_SLCT_IN; | |
260 | ||
261 | sbus_writeb(bits_or, base + BPP_OR); | |
262 | sbus_writeb(bits_tcr, base + BPP_TCR); | |
263 | } | |
264 | ||
265 | /* | |
266 | * i386 people read output pins from a software image. | |
267 | * We may get them back from hardware. | |
268 | * Again, inversion of pins must he buried here. | |
269 | */ | |
270 | static unsigned short get_pins(unsigned minor) | |
271 | { | |
272 | void __iomem *base = base_addrs[minor]; | |
273 | unsigned short bits = 0; | |
274 | unsigned value_tcr = sbus_readb(base + BPP_TCR); | |
275 | unsigned value_ir = sbus_readb(base + BPP_IR); | |
276 | unsigned value_or = sbus_readb(base + BPP_OR); | |
277 | ||
278 | if (value_tcr & P_TCR_DS) bits |= BPP_PP_nStrobe; | |
279 | if (value_or & P_OR_AFXN) bits |= BPP_PP_nAutoFd; | |
280 | if (! (value_or & P_OR_INIT)) bits |= BPP_PP_nInit; | |
281 | if (! (value_or & P_OR_SLCT_IN)) bits |= BPP_PP_nSelectIn; | |
282 | ||
283 | if (value_ir & P_IR_ERR) bits |= BPP_GP_nFault; | |
284 | if (! (value_ir & P_IR_SLCT)) bits |= BPP_GP_Select; | |
285 | if (! (value_ir & P_IR_PE)) bits |= BPP_GP_PError; | |
286 | if (! (value_tcr & P_TCR_ACK)) bits |= BPP_GP_nAck; | |
287 | if (value_tcr & P_TCR_BUSY) bits |= BPP_GP_Busy; | |
288 | ||
289 | return bits; | |
290 | } | |
291 | ||
292 | #endif /* __sparc__ */ | |
293 | ||
1da177e4 LT |
294 | static void snooze(unsigned long snooze_time, unsigned minor) |
295 | { | |
074c5279 | 296 | schedule_timeout_uninterruptible(snooze_time + 1); |
1da177e4 LT |
297 | } |
298 | ||
299 | static int wait_for(unsigned short set, unsigned short clr, | |
300 | unsigned long delay, unsigned minor) | |
301 | { | |
302 | unsigned short pins = get_pins(minor); | |
303 | ||
304 | unsigned long extime = 0; | |
305 | ||
306 | /* | |
307 | * Try a real fast scan for the first jiffy, in case the device | |
308 | * responds real good. The first while loop guesses an expire | |
309 | * time accounting for possible wraparound of jiffies. | |
310 | */ | |
311 | while (time_after_eq(jiffies, extime)) extime = jiffies + 1; | |
312 | while ( (time_before(jiffies, extime)) | |
313 | && (((pins & set) != set) || ((pins & clr) != 0)) ) { | |
314 | pins = get_pins(minor); | |
315 | } | |
316 | ||
317 | delay -= 1; | |
318 | ||
319 | /* | |
320 | * If my delay expired or the pins are still not where I want | |
321 | * them, then resort to using the timer and greatly reduce my | |
322 | * sample rate. If the peripheral is going to be slow, this will | |
323 | * give the CPU up to some more worthy process. | |
324 | */ | |
325 | while ( delay && (((pins & set) != set) || ((pins & clr) != 0)) ) { | |
326 | ||
327 | snooze(1, minor); | |
328 | pins = get_pins(minor); | |
329 | delay -= 1; | |
330 | } | |
331 | ||
332 | if (delay == 0) return -1; | |
333 | else return pins; | |
334 | } | |
335 | ||
336 | /* | |
337 | * Return ZERO(0) If the negotiation succeeds, an errno otherwise. An | |
338 | * errno means something broke, and I do not yet know how to fix it. | |
339 | */ | |
340 | static int negotiate(unsigned char mode, unsigned minor) | |
341 | { | |
342 | int rc; | |
343 | unsigned short pins = get_pins(minor); | |
344 | if (pins & BPP_PP_nSelectIn) return -EIO; | |
345 | ||
346 | ||
347 | /* Event 0: Write the mode to the data lines */ | |
348 | bpp_outb_p(mode, base_addrs[minor]); | |
349 | ||
350 | snooze(TIME_PSetup, minor); | |
351 | ||
352 | /* Event 1: Strobe the mode code into the peripheral */ | |
353 | set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe|BPP_PP_nInit, minor); | |
354 | ||
355 | /* Wait for Event 2: Peripheral responds as a 1284 device. */ | |
356 | rc = wait_for(BPP_GP_PError|BPP_GP_Select|BPP_GP_nFault, | |
357 | BPP_GP_nAck, | |
358 | TIME_PResponse, | |
359 | minor); | |
360 | ||
361 | if (rc == -1) return -ETIMEDOUT; | |
362 | ||
363 | /* Event 3: latch extensibility request */ | |
364 | set_pins(BPP_PP_nSelectIn|BPP_PP_nInit, minor); | |
365 | ||
366 | /* ... quick nap while peripheral ponders the byte i'm sending...*/ | |
367 | snooze(1, minor); | |
368 | ||
369 | /* Event 4: restore strobe, to ACK peripheral's response. */ | |
370 | set_pins(BPP_PP_nSelectIn|BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor); | |
371 | ||
372 | /* Wait for Event 6: Peripheral latches response bits */ | |
373 | rc = wait_for(BPP_GP_nAck, 0, TIME_PSetup+TIME_PResponse, minor); | |
374 | if (rc == -1) return -EIO; | |
375 | ||
376 | /* A 1284 device cannot refuse nibble mode */ | |
377 | if (mode == DEFAULT_NIBBLE) return 0; | |
378 | ||
379 | if (pins & BPP_GP_Select) return 0; | |
380 | ||
381 | return -EPROTONOSUPPORT; | |
382 | } | |
383 | ||
384 | static int terminate(unsigned minor) | |
385 | { | |
386 | int rc; | |
387 | ||
388 | /* Event 22: Request termination of 1284 mode */ | |
389 | set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor); | |
390 | ||
391 | /* Wait for Events 23 and 24: ACK termination request. */ | |
392 | rc = wait_for(BPP_GP_Busy|BPP_GP_nFault, | |
393 | BPP_GP_nAck, | |
394 | TIME_PSetup+TIME_PResponse, | |
395 | minor); | |
396 | ||
397 | instances[minor].direction = 0; | |
398 | instances[minor].mode = COMPATIBILITY; | |
399 | ||
400 | if (rc == -1) { | |
401 | return -EIO; | |
402 | } | |
403 | ||
404 | /* Event 25: Handshake by lowering nAutoFd */ | |
405 | set_pins(BPP_PP_nStrobe|BPP_PP_nInit, minor); | |
406 | ||
407 | /* Event 26: Peripheral wiggles lines... */ | |
408 | ||
409 | /* Event 27: Peripheral sets nAck HIGH to ack handshake */ | |
410 | rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor); | |
411 | if (rc == -1) { | |
412 | set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor); | |
413 | return -EIO; | |
414 | } | |
415 | ||
416 | /* Event 28: Finish phase by raising nAutoFd */ | |
417 | set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor); | |
418 | ||
419 | return 0; | |
420 | } | |
421 | ||
422 | static DEFINE_SPINLOCK(bpp_open_lock); | |
423 | ||
424 | /* | |
425 | * Allow only one process to open the device at a time. | |
426 | */ | |
427 | static int bpp_open(struct inode *inode, struct file *f) | |
428 | { | |
429 | unsigned minor = iminor(inode); | |
430 | int ret; | |
431 | ||
432 | spin_lock(&bpp_open_lock); | |
433 | ret = 0; | |
434 | if (minor >= BPP_NO) { | |
435 | ret = -ENODEV; | |
436 | } else { | |
437 | if (! instances[minor].present) { | |
438 | ret = -ENODEV; | |
439 | } else { | |
440 | if (instances[minor].opened) | |
441 | ret = -EBUSY; | |
442 | else | |
443 | instances[minor].opened = 1; | |
444 | } | |
445 | } | |
446 | spin_unlock(&bpp_open_lock); | |
447 | ||
448 | return ret; | |
449 | } | |
450 | ||
451 | /* | |
452 | * When the process closes the device, this method is called to clean | |
453 | * up and reset the hardware. Always leave the device in compatibility | |
454 | * mode as this is a reasonable place to clean up from messes made by | |
455 | * ioctls, or other mayhem. | |
456 | */ | |
457 | static int bpp_release(struct inode *inode, struct file *f) | |
458 | { | |
459 | unsigned minor = iminor(inode); | |
460 | ||
461 | spin_lock(&bpp_open_lock); | |
462 | instances[minor].opened = 0; | |
463 | ||
464 | if (instances[minor].mode != COMPATIBILITY) | |
465 | terminate(minor); | |
466 | ||
467 | spin_unlock(&bpp_open_lock); | |
468 | ||
469 | return 0; | |
470 | } | |
471 | ||
472 | static long read_nibble(unsigned minor, char __user *c, unsigned long cnt) | |
473 | { | |
474 | unsigned long remaining = cnt; | |
475 | long rc; | |
476 | ||
477 | while (remaining > 0) { | |
478 | unsigned char byte = 0; | |
479 | int pins; | |
480 | ||
481 | /* Event 7: request nibble */ | |
482 | set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe, minor); | |
483 | ||
484 | /* Wait for event 9: Peripher strobes first nibble */ | |
485 | pins = wait_for(0, BPP_GP_nAck, TIME_IDLE_LIMIT, minor); | |
486 | if (pins == -1) return -ETIMEDOUT; | |
487 | ||
488 | /* Event 10: I handshake nibble */ | |
489 | set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe|BPP_PP_nAutoFd, minor); | |
490 | if (pins & BPP_GP_nFault) byte |= 0x01; | |
491 | if (pins & BPP_GP_Select) byte |= 0x02; | |
492 | if (pins & BPP_GP_PError) byte |= 0x04; | |
493 | if (pins & BPP_GP_Busy) byte |= 0x08; | |
494 | ||
495 | /* Wait for event 11: Peripheral handshakes nibble */ | |
496 | rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor); | |
497 | ||
498 | /* Event 7: request nibble */ | |
499 | set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe, minor); | |
500 | ||
501 | /* Wait for event 9: Peripher strobes first nibble */ | |
502 | pins = wait_for(0, BPP_GP_nAck, TIME_PResponse, minor); | |
503 | if (rc == -1) return -ETIMEDOUT; | |
504 | ||
505 | /* Event 10: I handshake nibble */ | |
506 | set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe|BPP_PP_nAutoFd, minor); | |
507 | if (pins & BPP_GP_nFault) byte |= 0x10; | |
508 | if (pins & BPP_GP_Select) byte |= 0x20; | |
509 | if (pins & BPP_GP_PError) byte |= 0x40; | |
510 | if (pins & BPP_GP_Busy) byte |= 0x80; | |
511 | ||
512 | if (put_user(byte, c)) | |
513 | return -EFAULT; | |
514 | c += 1; | |
515 | remaining -= 1; | |
516 | ||
517 | /* Wait for event 11: Peripheral handshakes nibble */ | |
518 | rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor); | |
519 | if (rc == -1) return -EIO; | |
520 | } | |
521 | ||
522 | return cnt - remaining; | |
523 | } | |
524 | ||
525 | static long read_ecp(unsigned minor, char __user *c, unsigned long cnt) | |
526 | { | |
527 | unsigned long remaining; | |
528 | long rc; | |
529 | ||
530 | /* Turn ECP mode from forward to reverse if needed. */ | |
531 | if (! instances[minor].direction) { | |
532 | unsigned short pins = get_pins(minor); | |
533 | ||
534 | /* Event 38: Turn the bus around */ | |
535 | instances[minor].direction = 0x20; | |
536 | pins &= ~BPP_PP_nAutoFd; | |
537 | set_pins(pins, minor); | |
538 | ||
539 | /* Event 39: Set pins for reverse mode. */ | |
540 | snooze(TIME_PSetup, minor); | |
541 | set_pins(BPP_PP_nStrobe|BPP_PP_nSelectIn, minor); | |
542 | ||
543 | /* Wait for event 40: Peripheral ready to be strobed */ | |
544 | rc = wait_for(0, BPP_GP_PError, TIME_PResponse, minor); | |
545 | if (rc == -1) return -ETIMEDOUT; | |
546 | } | |
547 | ||
548 | remaining = cnt; | |
549 | ||
550 | while (remaining > 0) { | |
551 | ||
552 | /* If there is a run length for a repeated byte, repeat */ | |
553 | /* that byte a few times. */ | |
554 | if (instances[minor].run_length && !instances[minor].run_flag) { | |
555 | ||
556 | char buffer[128]; | |
557 | unsigned idx; | |
558 | unsigned repeat = remaining < instances[minor].run_length | |
559 | ? remaining | |
560 | : instances[minor].run_length; | |
561 | ||
562 | for (idx = 0 ; idx < repeat ; idx += 1) | |
563 | buffer[idx] = instances[minor].repeat_byte; | |
564 | ||
565 | if (copy_to_user(c, buffer, repeat)) | |
566 | return -EFAULT; | |
567 | remaining -= repeat; | |
568 | c += repeat; | |
569 | instances[minor].run_length -= repeat; | |
570 | } | |
571 | ||
572 | if (remaining == 0) break; | |
573 | ||
574 | ||
575 | /* Wait for Event 43: Data active on the bus. */ | |
576 | rc = wait_for(0, BPP_GP_nAck, TIME_IDLE_LIMIT, minor); | |
577 | if (rc == -1) break; | |
578 | ||
579 | if (rc & BPP_GP_Busy) { | |
580 | /* OK, this is data. read it in. */ | |
581 | unsigned char byte = bpp_inb(base_addrs[minor]); | |
582 | if (put_user(byte, c)) | |
583 | return -EFAULT; | |
584 | c += 1; | |
585 | remaining -= 1; | |
586 | ||
587 | if (instances[minor].run_flag) { | |
588 | instances[minor].repeat_byte = byte; | |
589 | instances[minor].run_flag = 0; | |
590 | } | |
591 | ||
592 | } else { | |
593 | unsigned char byte = bpp_inb(base_addrs[minor]); | |
594 | if (byte & 0x80) { | |
595 | printk("bpp%d: " | |
596 | "Ignoring ECP channel %u from device.\n", | |
597 | minor, byte & 0x7f); | |
598 | } else { | |
599 | instances[minor].run_length = byte; | |
600 | instances[minor].run_flag = 1; | |
601 | } | |
602 | } | |
603 | ||
604 | /* Event 44: I got it. */ | |
605 | set_pins(BPP_PP_nStrobe|BPP_PP_nAutoFd|BPP_PP_nSelectIn, minor); | |
606 | ||
607 | /* Wait for event 45: peripheral handshake */ | |
608 | rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor); | |
609 | if (rc == -1) return -ETIMEDOUT; | |
610 | ||
611 | /* Event 46: Finish handshake */ | |
612 | set_pins(BPP_PP_nStrobe|BPP_PP_nSelectIn, minor); | |
613 | ||
614 | } | |
615 | ||
616 | ||
617 | return cnt - remaining; | |
618 | } | |
619 | ||
620 | static ssize_t bpp_read(struct file *f, char __user *c, size_t cnt, loff_t * ppos) | |
621 | { | |
622 | long rc; | |
7fa95f72 | 623 | unsigned minor = iminor(f->f_path.dentry->d_inode); |
1da177e4 LT |
624 | if (minor >= BPP_NO) return -ENODEV; |
625 | if (!instances[minor].present) return -ENODEV; | |
626 | ||
627 | switch (instances[minor].mode) { | |
628 | ||
629 | default: | |
630 | if (instances[minor].mode != COMPATIBILITY) | |
631 | terminate(minor); | |
632 | ||
633 | if (instances[minor].enhanced) { | |
634 | /* For now, do all reads with ECP-RLE mode */ | |
635 | unsigned short pins; | |
636 | ||
637 | rc = negotiate(DEFAULT_ECP, minor); | |
638 | if (rc < 0) break; | |
639 | ||
640 | instances[minor].mode = ECP_RLE; | |
641 | ||
642 | /* Event 30: set nAutoFd low to setup for ECP mode */ | |
643 | pins = get_pins(minor); | |
644 | pins &= ~BPP_PP_nAutoFd; | |
645 | set_pins(pins, minor); | |
646 | ||
647 | /* Wait for Event 31: peripheral ready */ | |
648 | rc = wait_for(BPP_GP_PError, 0, TIME_PResponse, minor); | |
649 | if (rc == -1) return -ETIMEDOUT; | |
650 | ||
651 | rc = read_ecp(minor, c, cnt); | |
652 | ||
653 | } else { | |
654 | rc = negotiate(DEFAULT_NIBBLE, minor); | |
655 | if (rc < 0) break; | |
656 | ||
657 | instances[minor].mode = NIBBLE; | |
658 | ||
659 | rc = read_nibble(minor, c, cnt); | |
660 | } | |
661 | break; | |
662 | ||
663 | case NIBBLE: | |
664 | rc = read_nibble(minor, c, cnt); | |
665 | break; | |
666 | ||
667 | case ECP: | |
668 | case ECP_RLE: | |
669 | rc = read_ecp(minor, c, cnt); | |
670 | break; | |
671 | ||
672 | } | |
673 | ||
674 | ||
675 | return rc; | |
676 | } | |
677 | ||
678 | /* | |
679 | * Compatibility mode handshaking is a matter of writing data, | |
680 | * strobing it, and waiting for the printer to stop being busy. | |
681 | */ | |
682 | static long write_compat(unsigned minor, const char __user *c, unsigned long cnt) | |
683 | { | |
684 | long rc; | |
685 | unsigned short pins = get_pins(minor); | |
686 | ||
687 | unsigned long remaining = cnt; | |
688 | ||
689 | ||
690 | while (remaining > 0) { | |
691 | unsigned char byte; | |
692 | ||
693 | if (get_user(byte, c)) | |
694 | return -EFAULT; | |
695 | c += 1; | |
696 | ||
697 | rc = wait_for(BPP_GP_nAck, BPP_GP_Busy, TIME_IDLE_LIMIT, minor); | |
698 | if (rc == -1) return -ETIMEDOUT; | |
699 | ||
700 | bpp_outb_p(byte, base_addrs[minor]); | |
701 | remaining -= 1; | |
702 | /* snooze(1, minor); */ | |
703 | ||
704 | pins &= ~BPP_PP_nStrobe; | |
705 | set_pins(pins, minor); | |
706 | ||
707 | rc = wait_for(BPP_GP_Busy, 0, TIME_PResponse, minor); | |
708 | ||
709 | pins |= BPP_PP_nStrobe; | |
710 | set_pins(pins, minor); | |
711 | } | |
712 | ||
713 | return cnt - remaining; | |
714 | } | |
715 | ||
716 | /* | |
717 | * Write data using ECP mode. Watch out that the port may be set up | |
718 | * for reading. If so, turn the port around. | |
719 | */ | |
720 | static long write_ecp(unsigned minor, const char __user *c, unsigned long cnt) | |
721 | { | |
722 | unsigned short pins = get_pins(minor); | |
723 | unsigned long remaining = cnt; | |
724 | ||
725 | if (instances[minor].direction) { | |
726 | int rc; | |
727 | ||
728 | /* Event 47 Request bus be turned around */ | |
729 | pins |= BPP_PP_nInit; | |
730 | set_pins(pins, minor); | |
731 | ||
732 | /* Wait for Event 49: Peripheral relinquished bus */ | |
733 | rc = wait_for(BPP_GP_PError, 0, TIME_PResponse, minor); | |
734 | ||
735 | pins |= BPP_PP_nAutoFd; | |
736 | instances[minor].direction = 0; | |
737 | set_pins(pins, minor); | |
738 | } | |
739 | ||
740 | while (remaining > 0) { | |
741 | unsigned char byte; | |
742 | int rc; | |
743 | ||
744 | if (get_user(byte, c)) | |
745 | return -EFAULT; | |
746 | ||
747 | rc = wait_for(0, BPP_GP_Busy, TIME_PResponse, minor); | |
748 | if (rc == -1) return -ETIMEDOUT; | |
749 | ||
750 | c += 1; | |
751 | ||
752 | bpp_outb_p(byte, base_addrs[minor]); | |
753 | ||
754 | pins &= ~BPP_PP_nStrobe; | |
755 | set_pins(pins, minor); | |
756 | ||
757 | pins |= BPP_PP_nStrobe; | |
758 | rc = wait_for(BPP_GP_Busy, 0, TIME_PResponse, minor); | |
759 | if (rc == -1) return -EIO; | |
760 | ||
761 | set_pins(pins, minor); | |
762 | } | |
763 | ||
764 | return cnt - remaining; | |
765 | } | |
766 | ||
767 | /* | |
768 | * Write to the peripheral. Be sensitive of the current mode. If I'm | |
769 | * in a mode that can be turned around (ECP) then just do | |
770 | * that. Otherwise, terminate and do my writing in compat mode. This | |
771 | * is the safest course as any device can handle it. | |
772 | */ | |
773 | static ssize_t bpp_write(struct file *f, const char __user *c, size_t cnt, loff_t * ppos) | |
774 | { | |
775 | long errno = 0; | |
7fa95f72 | 776 | unsigned minor = iminor(f->f_path.dentry->d_inode); |
1da177e4 LT |
777 | if (minor >= BPP_NO) return -ENODEV; |
778 | if (!instances[minor].present) return -ENODEV; | |
779 | ||
780 | switch (instances[minor].mode) { | |
781 | ||
782 | case ECP: | |
783 | case ECP_RLE: | |
784 | errno = write_ecp(minor, c, cnt); | |
785 | break; | |
786 | case COMPATIBILITY: | |
787 | errno = write_compat(minor, c, cnt); | |
788 | break; | |
789 | default: | |
790 | terminate(minor); | |
791 | errno = write_compat(minor, c, cnt); | |
792 | } | |
793 | ||
794 | return errno; | |
795 | } | |
796 | ||
797 | static int bpp_ioctl(struct inode *inode, struct file *f, unsigned int cmd, | |
798 | unsigned long arg) | |
799 | { | |
800 | int errno = 0; | |
801 | ||
802 | unsigned minor = iminor(inode); | |
803 | if (minor >= BPP_NO) return -ENODEV; | |
804 | if (!instances[minor].present) return -ENODEV; | |
805 | ||
806 | ||
807 | switch (cmd) { | |
808 | ||
809 | case BPP_PUT_PINS: | |
810 | set_pins(arg, minor); | |
811 | break; | |
812 | ||
813 | case BPP_GET_PINS: | |
814 | errno = get_pins(minor); | |
815 | break; | |
816 | ||
817 | case BPP_PUT_DATA: | |
818 | bpp_outb_p(arg, base_addrs[minor]); | |
819 | break; | |
820 | ||
821 | case BPP_GET_DATA: | |
822 | errno = bpp_inb_p(base_addrs[minor]); | |
823 | break; | |
824 | ||
825 | case BPP_SET_INPUT: | |
826 | if (arg) | |
827 | if (instances[minor].enhanced) { | |
828 | unsigned short bits = get_pins(minor); | |
829 | instances[minor].direction = 0x20; | |
830 | set_pins(bits, minor); | |
831 | } else { | |
832 | errno = -ENOTTY; | |
833 | } | |
834 | else { | |
835 | unsigned short bits = get_pins(minor); | |
836 | instances[minor].direction = 0x00; | |
837 | set_pins(bits, minor); | |
838 | } | |
839 | break; | |
840 | ||
841 | default: | |
842 | errno = -EINVAL; | |
843 | } | |
844 | ||
845 | return errno; | |
846 | } | |
847 | ||
00977a59 | 848 | static const struct file_operations bpp_fops = { |
1da177e4 LT |
849 | .owner = THIS_MODULE, |
850 | .read = bpp_read, | |
851 | .write = bpp_write, | |
852 | .ioctl = bpp_ioctl, | |
853 | .open = bpp_open, | |
854 | .release = bpp_release, | |
855 | }; | |
856 | ||
857 | #if defined(__i386__) | |
858 | ||
859 | #define collectLptPorts() {} | |
860 | ||
861 | static void probeLptPort(unsigned idx) | |
862 | { | |
863 | unsigned int testvalue; | |
864 | const unsigned short lpAddr = base_addrs[idx]; | |
865 | ||
866 | instances[idx].present = 0; | |
867 | instances[idx].enhanced = 0; | |
868 | instances[idx].direction = 0; | |
869 | instances[idx].mode = COMPATIBILITY; | |
1da177e4 LT |
870 | instances[idx].run_length = 0; |
871 | instances[idx].run_flag = 0; | |
1da177e4 LT |
872 | if (!request_region(lpAddr,3, dev_name)) return; |
873 | ||
874 | /* | |
875 | * First, make sure the instance exists. Do this by writing to | |
876 | * the data latch and reading the value back. If the port *is* | |
877 | * present, test to see if it supports extended-mode | |
878 | * operation. This will be required for IEEE1284 reverse | |
879 | * transfers. | |
880 | */ | |
881 | ||
882 | outb_p(BPP_PROBE_CODE, lpAddr); | |
883 | for (testvalue=0; testvalue<BPP_DELAY; testvalue++) | |
884 | ; | |
885 | testvalue = inb_p(lpAddr); | |
886 | if (testvalue == BPP_PROBE_CODE) { | |
887 | unsigned save; | |
888 | instances[idx].present = 1; | |
889 | ||
890 | save = inb_p(lpAddr+2); | |
891 | for (testvalue=0; testvalue<BPP_DELAY; testvalue++) | |
892 | ; | |
893 | outb_p(save|0x20, lpAddr+2); | |
894 | for (testvalue=0; testvalue<BPP_DELAY; testvalue++) | |
895 | ; | |
896 | outb_p(~BPP_PROBE_CODE, lpAddr); | |
897 | for (testvalue=0; testvalue<BPP_DELAY; testvalue++) | |
898 | ; | |
899 | testvalue = inb_p(lpAddr); | |
900 | if ((testvalue&0xff) == (0xff&~BPP_PROBE_CODE)) | |
901 | instances[idx].enhanced = 0; | |
902 | else | |
903 | instances[idx].enhanced = 1; | |
904 | outb_p(save, lpAddr+2); | |
905 | } | |
906 | else { | |
907 | release_region(lpAddr,3); | |
908 | } | |
909 | /* | |
910 | * Leave the port in compat idle mode. | |
911 | */ | |
912 | set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, idx); | |
913 | ||
914 | printk("bpp%d: Port at 0x%03x: Enhanced mode %s\n", idx, base_addrs[idx], | |
915 | instances[idx].enhanced? "SUPPORTED" : "UNAVAILABLE"); | |
916 | } | |
917 | ||
918 | static inline void freeLptPort(int idx) | |
919 | { | |
920 | release_region(base_addrs[idx], 3); | |
921 | } | |
922 | ||
923 | #endif | |
924 | ||
925 | #if defined(__sparc__) | |
926 | ||
927 | static void __iomem *map_bpp(struct sbus_dev *dev, int idx) | |
928 | { | |
929 | return sbus_ioremap(&dev->resource[0], 0, BPP_SIZE, "bpp"); | |
930 | } | |
931 | ||
932 | static int collectLptPorts(void) | |
933 | { | |
934 | struct sbus_bus *bus; | |
935 | struct sbus_dev *dev; | |
936 | int count; | |
937 | ||
938 | count = 0; | |
939 | for_all_sbusdev(dev, bus) { | |
940 | if (strcmp(dev->prom_name, "SUNW,bpp") == 0) { | |
941 | if (count >= BPP_NO) { | |
942 | printk(KERN_NOTICE | |
943 | "bpp: More than %d bpp ports," | |
944 | " rest is ignored\n", BPP_NO); | |
945 | return count; | |
946 | } | |
947 | base_addrs[count] = map_bpp(dev, count); | |
948 | count++; | |
949 | } | |
950 | } | |
951 | return count; | |
952 | } | |
953 | ||
954 | static void probeLptPort(unsigned idx) | |
955 | { | |
956 | void __iomem *rp = base_addrs[idx]; | |
957 | __u32 csr; | |
958 | char *brand; | |
959 | ||
960 | instances[idx].present = 0; | |
961 | instances[idx].enhanced = 0; | |
962 | instances[idx].direction = 0; | |
963 | instances[idx].mode = COMPATIBILITY; | |
1da177e4 LT |
964 | instances[idx].run_length = 0; |
965 | instances[idx].run_flag = 0; | |
1da177e4 LT |
966 | |
967 | if (!rp) return; | |
968 | ||
969 | instances[idx].present = 1; | |
970 | instances[idx].enhanced = 1; /* Sure */ | |
971 | ||
972 | csr = sbus_readl(rp + BPP_CSR); | |
973 | if ((csr & P_DRAINING) != 0 && (csr & P_ERR_PEND) == 0) { | |
974 | udelay(20); | |
975 | csr = sbus_readl(rp + BPP_CSR); | |
976 | if ((csr & P_DRAINING) != 0 && (csr & P_ERR_PEND) == 0) { | |
977 | printk("bpp%d: DRAINING still active (0x%08x)\n", idx, csr); | |
978 | } | |
979 | } | |
980 | printk("bpp%d: reset with 0x%08x ..", idx, csr); | |
981 | sbus_writel((csr | P_RESET) & ~P_INT_EN, rp + BPP_CSR); | |
982 | udelay(500); | |
983 | sbus_writel(sbus_readl(rp + BPP_CSR) & ~P_RESET, rp + BPP_CSR); | |
984 | csr = sbus_readl(rp + BPP_CSR); | |
985 | printk(" done with csr=0x%08x ocr=0x%04x\n", | |
986 | csr, sbus_readw(rp + BPP_OCR)); | |
987 | ||
988 | switch (csr & P_DEV_ID_MASK) { | |
989 | case P_DEV_ID_ZEBRA: | |
990 | brand = "Zebra"; | |
991 | break; | |
992 | case P_DEV_ID_L64854: | |
993 | brand = "DMA2"; | |
994 | break; | |
995 | default: | |
996 | brand = "Unknown"; | |
997 | } | |
998 | printk("bpp%d: %s at %p\n", idx, brand, rp); | |
999 | ||
1000 | /* | |
1001 | * Leave the port in compat idle mode. | |
1002 | */ | |
1003 | set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, idx); | |
1004 | ||
1005 | return; | |
1006 | } | |
1007 | ||
1008 | static inline void freeLptPort(int idx) | |
1009 | { | |
1010 | sbus_iounmap(base_addrs[idx], BPP_SIZE); | |
1011 | } | |
1012 | ||
1013 | #endif | |
1014 | ||
1015 | static int __init bpp_init(void) | |
1016 | { | |
1017 | int rc; | |
1018 | unsigned idx; | |
1019 | ||
1020 | rc = collectLptPorts(); | |
1021 | if (rc == 0) | |
1022 | return -ENODEV; | |
1023 | ||
1024 | rc = register_chrdev(BPP_MAJOR, dev_name, &bpp_fops); | |
1025 | if (rc < 0) | |
1026 | return rc; | |
1027 | ||
1028 | for (idx = 0; idx < BPP_NO; idx++) { | |
1029 | instances[idx].opened = 0; | |
1030 | probeLptPort(idx); | |
1031 | } | |
1da177e4 LT |
1032 | |
1033 | return 0; | |
1034 | } | |
1035 | ||
1036 | static void __exit bpp_cleanup(void) | |
1037 | { | |
1038 | unsigned idx; | |
1039 | ||
1da177e4 LT |
1040 | unregister_chrdev(BPP_MAJOR, dev_name); |
1041 | ||
1042 | for (idx = 0; idx < BPP_NO; idx++) { | |
1043 | if (instances[idx].present) | |
1044 | freeLptPort(idx); | |
1045 | } | |
1046 | } | |
1047 | ||
1048 | module_init(bpp_init); | |
1049 | module_exit(bpp_cleanup); | |
1050 | ||
1051 | MODULE_LICENSE("GPL"); | |
1052 |