OSDN Git Service

[PATCH] ip-pnp-dhcp: wait lazily when doing dhcp for diskless systems
[linux-kernel-docs/linux-2.4.36.git] / drivers / parport / parport_ip22.c
1 /*
2  * Low-level parallel port routines for the SGI Indy/Indigo2 builtin port
3  *
4  * Copyright (c) 2002 Vincent StehlĂ© <vincent.stehle@free.fr>
5  * (shamelessly based on other parport_xxx.c)
6  * See the "COPYING" license file at the top-level.
7  *
8  * PI1 registers have the same bits as the PC parallel port registers, but
9  * all PI1 bits are "direct"; i.e. no invertion: A 1 is TTL "high" (5 V),
10  * a 0 is TTL "low" (0 V). There are also some bits on the PI1, which have
11  * no equivalents on the PC. They are for non-SPP modes.
12  *
13  * Here follows a little summary of the signals and their meanings:
14  *
15  * A "/" in front of a signal means that the _bit_ is inverted: i.e. a "1"
16  * bit value means a TTL "low" (0 V) signal.
17  *
18  * A "-" in front of a signal means that it is low active: i.e. a TTL "low"
19  * (0 V) value means that the signal is active.
20  *
21  * Internal only signals are between ()'s.
22  *
23  * Control
24  * -------
25  *                   PC                     SGI
26  *
27  * 7 6 5 4 3 2 1 0
28  *  \ \ \ \ \ \ \ `- /-STROBE               -STROBE
29  *   \ \ \ \ \ \ `-- /-AUTO FEED            -AFD
30  *    \ \ \ \ \ `---  -INIT                 -INIT
31  *     \ \ \ \ `---- /-SELECT               -SLIN
32  *      \ \ \ `----- (IRQ 1=enabled)
33  *       \ \ `------ (DIRECTION 0=forward)
34  *        \ `-------                        (SEL ?)
35  *         `--------
36  *
37  * Status
38  * ------
39  *                   PC                     SGI
40  *
41  * 7 6 5 4 3 2 1 0
42  *  \ \ \ \ \ \ \ `-                         DEVID
43  *   \ \ \ \ \ \ `--                          " "
44  *    \ \ \ \ \ `---                         NOINK
45  *     \ \ \ \ `----  -ERROR                -ERROR
46  *      \ \ \ `-----   SELECT IN             ONLINE
47  *       \ \ `------   PAPER END             PE
48  *        \ `-------  -ACK                  -ACK
49  *         `-------- / BUSY                  BUSY
50  *
51  * Note that some of those information have been "guessed" with a multimeter
52  * and some spare nights :)
53  *
54  * Reminder: all functions await PC-style values, i.e. one should convert
55  *           status and control.
56  */
57
58 #include <linux/kernel.h>
59 #include <linux/module.h>
60 #include <linux/init.h>
61 #include <linux/parport.h>
62 #include <asm/sgi/ioc.h>
63 #include <asm/sgi/pi1.h>
64
65 #undef DEBUG
66
67 #ifdef DEBUG
68 #define DPRINTK printk
69 #else
70 #define DPRINTK(x...)   do { } while (0)
71 #endif
72
73 const unsigned char control_invert = PARPORT_CONTROL_STROBE
74         | PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_SELECT;
75 const unsigned char status_invert = PARPORT_STATUS_BUSY;
76
77 static struct parport *this_port = NULL;
78
79 static inline void debug_dump_registers(void)
80 {
81 #ifdef DEBUG
82         printk(KERN_DEBUG
83                 "PI1 registers:\n"
84                 "             data= %02x\n"
85                 "          control= %02x\n"
86                 "           status= %02x\n"
87                 "      dma control= %02x\n"
88                 " interrupt status= %02x\n"
89                 "   interrupt mask= %02x\n"
90                 "          timer 1= %02x\n"
91                 "          timer 2= %02x\n"
92                 "          timer 3= %02x\n"
93                 "          timer 4= %02x\n"
94                 ,
95                 sgioc->pport.data,
96                 sgioc->pport.ctrl,
97                 sgioc->pport.status,
98                 sgioc->pport.dmactrl,
99                 sgioc->pport.intstat,
100                 sgioc->pport.intmask,
101                 sgioc->pport.timer1,
102                 sgioc->pport.timer2,
103                 sgioc->pport.timer3,
104                 sgioc->pport.timer4
105         );
106 #endif
107 }
108
109 static unsigned char pi1_read_data(struct parport *p)
110 {
111         unsigned char data = sgioc->pport.data;
112         DPRINTK("pi1_read_data: %#x\n", data);
113         return data;
114 }
115
116 static void pi1_write_data(struct parport *p, unsigned char data)
117 {
118         DPRINTK("pi1_write_data: %#x\n", data);
119         sgioc->pport.data = data;
120 }
121
122 static unsigned char pi1_read_control(struct parport *p)
123 {
124         const unsigned char mask = PARPORT_CONTROL_STROBE
125                 | PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_INIT
126                 | PARPORT_CONTROL_SELECT;
127         unsigned char pctrl = sgioc->pport.ctrl,
128                 control = ((pctrl & mask) ^ control_invert);
129         DPRINTK("pi1_read_control: %#x, %#x\n", pctrl, control);
130         return control;
131 }
132
133 static void pi1_write_control(struct parport *p, unsigned char control)
134 {
135         const unsigned char mask = PARPORT_CONTROL_STROBE
136                 | PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_INIT
137                 | PARPORT_CONTROL_SELECT,
138         /* we enforce some necessary bits */
139                 force = 0x30;
140         unsigned char pctrl = ((control & mask) ^ control_invert) | force;
141         DPRINTK("pi1_write_control: %#x, %#x\n", control, pctrl);
142         sgioc->pport.ctrl = pctrl;
143 }
144
145 static unsigned char pi1_frob_control(struct parport *p,
146         unsigned char mask, unsigned char val)
147 {
148         unsigned char old;
149         DPRINTK(KERN_DEBUG "pi1_frob_control mask %02x, value %02x\n",mask,val);
150         old = pi1_read_control(p);
151         pi1_write_control(p, (old & ~mask) ^ val);
152         return old;
153 }
154
155 static unsigned char pi1_read_status(struct parport *p)
156 {
157         const unsigned mask = PARPORT_STATUS_ERROR | PARPORT_STATUS_SELECT
158                 | PARPORT_STATUS_PAPEROUT | PARPORT_STATUS_ACK
159                 | PARPORT_STATUS_BUSY;
160         unsigned char pstat = sgioc->pport.status,
161                 status = ((pstat & mask) ^ status_invert);
162         DPRINTK("pi1_read_status: %#x, %#x\n", pstat, status);
163         return status;
164 }
165
166 static void pi1_init_state(struct pardevice *d, struct parport_state *s)
167 {
168         DPRINTK("pi1_init_state\n");
169 }
170
171 static void pi1_save_state(struct parport *p, struct parport_state *s)
172 {
173         DPRINTK("pi1_save_state\n");
174 }
175
176 static void pi1_restore_state(struct parport *p, struct parport_state *s)
177 {
178         DPRINTK("pi1_restore_state\n");
179 }
180
181 static void pi1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
182 {
183         DPRINTK("pi1_interrupt\n");
184         parport_generic_irq(irq, (struct parport *) dev_id, regs);
185 }
186
187 static void pi1_enable_irq(struct parport *p)
188 {
189         DPRINTK("pi1_enable_irq\n");
190 }
191
192 static void pi1_disable_irq(struct parport *p)
193 {
194         DPRINTK("pi1_disable_irq\n");
195 }
196
197 static void pi1_data_forward(struct parport *p)
198 {
199         DPRINTK("pi1_data_forward\n");
200         sgioc->pport.ctrl &= ~PI1_CTRL_DIR;
201 }
202
203 static void pi1_data_reverse(struct parport *p)
204 {
205         DPRINTK("pi1_data_reverse\n");
206         sgioc->pport.ctrl |= PI1_CTRL_DIR;
207 }
208
209 static void pi1_inc_use_count(void)
210 {
211         DPRINTK("pi1_inc_use_count\n");
212         MOD_INC_USE_COUNT;
213 }
214
215 static void pi1_dec_use_count(void)
216 {
217         DPRINTK("pi1_dec_use_count\n");
218         MOD_DEC_USE_COUNT;
219 }
220
221 static struct parport_operations pi1_ops = {
222         pi1_write_data,
223         pi1_read_data,
224         pi1_write_control,
225         pi1_read_control,
226         pi1_frob_control,
227         pi1_read_status,
228         pi1_enable_irq,
229         pi1_disable_irq,
230         pi1_data_forward,
231         pi1_data_reverse,
232         pi1_init_state,
233         pi1_save_state,
234         pi1_restore_state,
235         pi1_inc_use_count,
236         pi1_dec_use_count,
237         parport_ieee1284_epp_write_data,
238         parport_ieee1284_epp_read_data,
239         parport_ieee1284_epp_write_addr,
240         parport_ieee1284_epp_read_addr,
241         parport_ieee1284_ecp_write_data,
242         parport_ieee1284_ecp_read_data,
243         parport_ieee1284_ecp_write_addr,
244         parport_ieee1284_write_compat,
245         parport_ieee1284_read_nibble,
246         parport_ieee1284_read_byte
247 };
248
249 static void init_hardware(void)
250 {
251         sgioc->pport.intmask = 0xfc;
252         sgioc->pport.dmactrl = 1;
253         sgioc->pport.ctrl = 0x3f;
254         sgioc->pport.timer1 = 0;
255         sgioc->pport.timer2 = 0;
256         sgioc->pport.timer3 = 0;
257         sgioc->pport.timer4 = 0;
258         sgioc->pport.data = 0;
259 }
260
261 static int __init pi1_init(void)
262 {
263         struct parport *p;
264
265         DPRINTK("pi1_init\n");
266         p = parport_register_port((unsigned long) &sgioc->pport.data,
267                                   PARPORT_IRQ_NONE, PARPORT_DMA_NONE,
268                                   &pi1_ops);
269         if (!p)
270                 return -EBUSY;
271
272 /* TODO
273         err = request_irq(IRQ_AMIGA_CIAA_FLG, amiga_interrupt, 0, p->name, p);
274         if (err)
275                 goto out_irq;
276 */
277         
278         /* tell what we are capable of */
279         p->modes = PARPORT_MODE_PCSPP;
280
281 /* TODO
282          | PARPORT_MODE_TRISTATE;*/
283
284         /* remember for exit */
285         this_port = p;
286
287         /* put hardware into known initial state */
288         init_hardware();
289
290         printk(KERN_INFO "%s: SGI PI1\n", p->name);
291         parport_proc_register(p);
292         parport_announce_port(p);
293
294         return 0;
295 }
296
297 static void __exit pi1_exit(void)
298 {
299         DPRINTK("pi1_exit\n");
300         if (this_port->irq != PARPORT_IRQ_NONE)
301                 free_irq(this_port->irq, this_port);
302
303         parport_proc_unregister(this_port);
304         parport_unregister_port(this_port);
305 }
306
307 MODULE_AUTHOR("Vincent Stehle <vincent.stehle@free.fr>");
308 MODULE_DESCRIPTION("Driver for SGI Indy/Indigo2 parallel port");
309 MODULE_SUPPORTED_DEVICE("SGI PI1 parallel port");
310 MODULE_LICENSE("GPL");
311
312 module_init(pi1_init);
313 module_exit(pi1_exit);