File: /usr/src/linux/drivers/parport/parport_sunbpp.c

1     /* $Id: parport_sunbpp.c,v 1.12 2001/05/26 03:01:42 davem Exp $
2      * Parallel-port routines for Sun architecture
3      * 
4      * Author: Derrick J. Brashear <shadow@dementia.org>
5      *
6      * based on work by:
7      *          Phil Blundell <Philip.Blundell@pobox.com>
8      *          Tim Waugh <tim@cyberelk.demon.co.uk>
9      *	    Jose Renau <renau@acm.org>
10      *          David Campbell <campbell@tirian.che.curtin.edu.au>
11      *          Grant Guenther <grant@torque.net>
12      *          Eddie C. Dost <ecd@skynet.be>
13      *          Stephen Williams (steve@icarus.com)
14      *          Gus Baldauf (gbaldauf@ix.netcom.com)
15      *          Peter Zaitcev
16      *          Tom Dyas
17      */
18     
19     #include <linux/string.h>
20     #include <linux/module.h>
21     #include <linux/delay.h>
22     #include <linux/errno.h>
23     #include <linux/ioport.h>
24     #include <linux/kernel.h>
25     #include <linux/slab.h>
26     #include <linux/init.h>
27     
28     #include <linux/parport.h>
29     
30     #include <asm/ptrace.h>
31     #include <linux/interrupt.h>
32     
33     #include <asm/io.h>
34     #include <asm/oplib.h>           /* OpenProm Library */
35     #include <asm/sbus.h>
36     #include <asm/dma.h>             /* BPP uses LSI 64854 for DMA */
37     #include <asm/irq.h>
38     #include <asm/sunbpp.h>
39     
40     #undef __SUNBPP_DEBUG
41     #ifdef __SUNBPP_DEBUG
42     #define dprintk(x) printk x
43     #else
44     #define dprintk(x)
45     #endif
46     
47     static void parport_sunbpp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
48     {
49     	parport_generic_irq(irq, (struct parport *) dev_id, regs);
50     }
51     
52     static void parport_sunbpp_disable_irq(struct parport *p)
53     {
54     	struct bpp_regs *regs = (struct bpp_regs *)p->base;
55     	u32 tmp;
56     
57     	tmp = sbus_readl(&regs->p_csr);
58     	tmp &= ~DMA_INT_ENAB;
59     	sbus_writel(tmp, &regs->p_csr);
60     }
61     
62     static void parport_sunbpp_enable_irq(struct parport *p)
63     {
64     	struct bpp_regs *regs = (struct bpp_regs *)p->base;
65     	u32 tmp;
66     
67     	tmp = sbus_readl(&regs->p_csr);
68     	tmp |= DMA_INT_ENAB;
69     	sbus_writel(tmp, &regs->p_csr);
70     }
71     
72     static void parport_sunbpp_write_data(struct parport *p, unsigned char d)
73     {
74     	struct bpp_regs *regs = (struct bpp_regs *)p->base;
75     
76     	sbus_writeb(d, &regs->p_dr);
77     	dprintk((KERN_DEBUG "wrote 0x%x\n", d));
78     }
79     
80     static unsigned char parport_sunbpp_read_data(struct parport *p)
81     {
82     	struct bpp_regs *regs = (struct bpp_regs *)p->base;
83     
84     	return sbus_readb(&regs->p_dr);
85     }
86     
87     #if 0
88     static void control_pc_to_sunbpp(struct parport *p, unsigned char status)
89     {
90     	struct bpp_regs *regs = (struct bpp_regs *)p->base;
91     	unsigned char value_tcr = sbus_readb(&regs->p_tcr);
92     	unsigned char value_or = sbus_readb(&regs->p_or);
93     
94     	if (status & PARPORT_CONTROL_STROBE) 
95     		value_tcr |= P_TCR_DS;
96     	if (status & PARPORT_CONTROL_AUTOFD) 
97     		value_or |= P_OR_AFXN;
98     	if (status & PARPORT_CONTROL_INIT) 
99     		value_or |= P_OR_INIT;
100     	if (status & PARPORT_CONTROL_SELECT) 
101     		value_or |= P_OR_SLCT_IN;
102     
103     	sbus_writeb(value_or, &regs->p_or);
104     	sbus_writeb(value_tcr, &regs->p_tcr);
105     }
106     #endif
107     
108     static unsigned char status_sunbpp_to_pc(struct parport *p)
109     {
110     	struct bpp_regs *regs = (struct bpp_regs *)p->base;
111     	unsigned char bits = 0;
112     	unsigned char value_tcr = sbus_readb(&regs->p_tcr);
113     	unsigned char value_ir = sbus_readb(&regs->p_ir);
114     
115     	if (!(value_ir & P_IR_ERR))
116     		bits |= PARPORT_STATUS_ERROR;
117     	if (!(value_ir & P_IR_SLCT))
118     		bits |= PARPORT_STATUS_SELECT;
119     	if (!(value_ir & P_IR_PE))
120     		bits |= PARPORT_STATUS_PAPEROUT;
121     	if (value_tcr & P_TCR_ACK)
122     		bits |= PARPORT_STATUS_ACK;
123     	if (!(value_tcr & P_TCR_BUSY))
124     		bits |= PARPORT_STATUS_BUSY;
125     
126     	dprintk((KERN_DEBUG "tcr 0x%x ir 0x%x\n", regs->p_tcr, regs->p_ir));
127     	dprintk((KERN_DEBUG "read status 0x%x\n", bits));
128     	return bits;
129     }
130     
131     static unsigned char control_sunbpp_to_pc(struct parport *p)
132     {
133     	struct bpp_regs *regs = (struct bpp_regs *)p->base;
134     	unsigned char bits = 0;
135     	unsigned char value_tcr = sbus_readb(&regs->p_tcr);
136     	unsigned char value_or = sbus_readb(&regs->p_or);
137     
138     	if (!(value_tcr & P_TCR_DS))
139     		bits |= PARPORT_CONTROL_STROBE;
140     	if (!(value_or & P_OR_AFXN))
141     		bits |= PARPORT_CONTROL_AUTOFD;
142     	if (!(value_or & P_OR_INIT))
143     		bits |= PARPORT_CONTROL_INIT;
144     	if (value_or & P_OR_SLCT_IN)
145     		bits |= PARPORT_CONTROL_SELECT;
146     
147     	dprintk((KERN_DEBUG "tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or));
148     	dprintk((KERN_DEBUG "read control 0x%x\n", bits));
149     	return bits;
150     }
151     
152     static unsigned char parport_sunbpp_read_control(struct parport *p)
153     {
154     	return control_sunbpp_to_pc(p);
155     }
156     
157     static unsigned char parport_sunbpp_frob_control(struct parport *p,
158     						 unsigned char mask,
159     						 unsigned char val)
160     {
161     	struct bpp_regs *regs = (struct bpp_regs *)p->base;
162     	unsigned char value_tcr = sbus_readb(&regs->p_tcr);
163     	unsigned char value_or = sbus_readb(&regs->p_or);
164     
165     	dprintk((KERN_DEBUG "frob1: tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or));
166     	if (mask & PARPORT_CONTROL_STROBE) {
167     		if (val & PARPORT_CONTROL_STROBE) {
168     			value_tcr &= ~P_TCR_DS;
169     		} else {
170     			value_tcr |= P_TCR_DS;
171     		}
172     	}
173     	if (mask & PARPORT_CONTROL_AUTOFD) {
174     		if (val & PARPORT_CONTROL_AUTOFD) {
175     			value_or &= ~P_OR_AFXN;
176     		} else {
177     			value_or |= P_OR_AFXN;
178     		}
179     	}
180     	if (mask & PARPORT_CONTROL_INIT) {
181     		if (val & PARPORT_CONTROL_INIT) {
182     			value_or &= ~P_OR_INIT;
183     		} else {
184     			value_or |= P_OR_INIT;
185     		}
186     	}
187     	if (mask & PARPORT_CONTROL_SELECT) {
188     		if (val & PARPORT_CONTROL_SELECT) {
189     			value_or |= P_OR_SLCT_IN;
190     		} else {
191     			value_or &= ~P_OR_SLCT_IN;
192     		}
193     	}
194     
195     	sbus_writeb(value_or, &regs->p_or);
196     	sbus_writeb(value_tcr, &regs->p_tcr);
197     	dprintk((KERN_DEBUG "frob2: tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or));
198     	return parport_sunbpp_read_control(p);
199     }
200     
201     static void parport_sunbpp_write_control(struct parport *p, unsigned char d)
202     {
203     	const unsigned char wm = (PARPORT_CONTROL_STROBE |
204     				  PARPORT_CONTROL_AUTOFD |
205     				  PARPORT_CONTROL_INIT |
206     				  PARPORT_CONTROL_SELECT);
207     
208     	parport_sunbpp_frob_control (p, wm, d & wm);
209     }
210     
211     static unsigned char parport_sunbpp_read_status(struct parport *p)
212     {
213     	return status_sunbpp_to_pc(p);
214     }
215     
216     static void parport_sunbpp_data_forward (struct parport *p)
217     {
218     	struct bpp_regs *regs = (struct bpp_regs *)p->base;
219     	unsigned char value_tcr = sbus_readb(&regs->p_tcr);
220     
221     	dprintk((KERN_DEBUG "forward\n"));
222     	value_tcr &= ~P_TCR_DIR;
223     	sbus_writeb(value_tcr, &regs->p_tcr);
224     }
225     
226     static void parport_sunbpp_data_reverse (struct parport *p)
227     {
228     	struct bpp_regs *regs = (struct bpp_regs *)p->base;
229     	u8 val = sbus_readb(&regs->p_tcr);
230     
231     	dprintk((KERN_DEBUG "reverse\n"));
232     	val |= P_TCR_DIR;
233     	sbus_writeb(val, &regs->p_tcr);
234     }
235     
236     static void parport_sunbpp_init_state(struct pardevice *dev, struct parport_state *s)
237     {
238     	s->u.pc.ctr = 0xc;
239     	s->u.pc.ecr = 0x0;
240     }
241     
242     static void parport_sunbpp_save_state(struct parport *p, struct parport_state *s)
243     {
244     	s->u.pc.ctr = parport_sunbpp_read_control(p);
245     }
246     
247     static void parport_sunbpp_restore_state(struct parport *p, struct parport_state *s)
248     {
249     	parport_sunbpp_write_control(p, s->u.pc.ctr);
250     }
251     
252     static void parport_sunbpp_inc_use_count(void)
253     {
254     #ifdef MODULE
255     	MOD_INC_USE_COUNT;
256     #endif
257     }
258     
259     static void parport_sunbpp_dec_use_count(void)
260     {
261     #ifdef MODULE
262     	MOD_DEC_USE_COUNT;
263     #endif
264     }
265     
266     static struct parport_operations parport_sunbpp_ops = 
267     {
268     	parport_sunbpp_write_data,
269     	parport_sunbpp_read_data,
270     
271     	parport_sunbpp_write_control,
272     	parport_sunbpp_read_control,
273     	parport_sunbpp_frob_control,
274     
275     	parport_sunbpp_read_status,
276     
277     	parport_sunbpp_enable_irq,
278             parport_sunbpp_disable_irq,
279     
280             parport_sunbpp_data_forward,
281             parport_sunbpp_data_reverse,
282     
283             parport_sunbpp_init_state,
284             parport_sunbpp_save_state,
285             parport_sunbpp_restore_state,
286     
287             parport_sunbpp_inc_use_count,
288             parport_sunbpp_dec_use_count,
289     
290             parport_ieee1284_epp_write_data,
291             parport_ieee1284_epp_read_data,
292             parport_ieee1284_epp_write_addr,
293             parport_ieee1284_epp_read_addr,
294     
295             parport_ieee1284_ecp_write_data,
296             parport_ieee1284_ecp_read_data,
297             parport_ieee1284_ecp_write_addr,
298     
299             parport_ieee1284_write_compat,
300             parport_ieee1284_read_nibble,
301             parport_ieee1284_read_byte,
302     };
303     
304     static int __init init_one_port(struct sbus_dev *sdev)
305     {
306     	struct parport *p;
307     	/* at least in theory there may be a "we don't dma" case */
308     	struct parport_operations *ops;
309     	unsigned long base;
310     	int irq, dma, err, size;
311     	struct bpp_regs *regs;
312     	unsigned char value_tcr;
313     
314     	dprintk((KERN_DEBUG "init_one_port(%p): ranges, alloc_io, ", sdev));
315     	irq = sdev->irqs[0];
316     	base = sbus_ioremap(&sdev->resource[0], 0,
317     			    sdev->reg_addrs[0].reg_size, 
318     			    "sunbpp");
319     	size = sdev->reg_addrs[0].reg_size;
320     	dma = PARPORT_DMA_NONE;
321     
322     	dprintk(("alloc(ppops), "));
323     	ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL);
324             if (!ops) {
325     		sbus_iounmap(base, size);
326     		return 0;
327             }
328     
329             memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations));
330     
331     	dprintk(("register_port\n"));
332     	if (!(p = parport_register_port(base, irq, dma, ops))) {
333     		kfree(ops);
334     		sbus_iounmap(base, size);
335     		return 0;
336     	}
337     
338     	p->size = size;
339     
340     	dprintk((KERN_DEBUG "init_one_port: request_irq(%08x:%p:%x:%s:%p) ",
341     		p->irq, parport_sunbpp_interrupt, SA_SHIRQ, p->name, p));
342     	if ((err = request_irq(p->irq, parport_sunbpp_interrupt,
343     			       SA_SHIRQ, p->name, p)) != 0) {
344     		dprintk(("ERROR %d\n", err));
345     		parport_unregister_port(p);
346     		kfree(ops);
347     		sbus_iounmap(base, size);
348     		return err;
349     	} else {
350     		dprintk(("OK\n"));
351     		parport_sunbpp_enable_irq(p);
352     	}
353     
354     	regs = (struct bpp_regs *)p->base;
355     	dprintk((KERN_DEBUG "forward\n"));
356     	value_tcr = sbus_readb(&regs->p_tcr);
357     	value_tcr &= ~P_TCR_DIR;
358     	sbus_writeb(value_tcr, &regs->p_tcr);
359     
360     	printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base);
361     	parport_proc_register(p);
362     	parport_announce_port (p);
363     
364     	return 1;
365     }
366     
367     EXPORT_NO_SYMBOLS;
368     
369     #ifdef MODULE
370     int init_module(void)
371     #else
372     int __init parport_sunbpp_init(void)
373     #endif
374     {
375             struct sbus_bus *sbus;
376             struct sbus_dev *sdev;
377     	int count = 0;
378     
379     	for_each_sbus(sbus) {
380     		for_each_sbusdev(sdev, sbus) {
381     			if (!strcmp(sdev->prom_name, "SUNW,bpp"))
382     				count += init_one_port(sdev);
383     		}
384     	}
385     	return count ? 0 : -ENODEV;
386     }
387     
388     #ifdef MODULE
389     MODULE_AUTHOR("Derrick J Brashear");
390     MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port");
391     MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port");
392     
393     void
394     cleanup_module(void)
395     {
396     	struct parport *p = parport_enumerate();
397     
398     	while (p) {
399     		struct parport *next = p->next;
400     
401     		if (1/*p->modes & PARPORT_MODE_PCSPP*/) { 
402     			struct parport_operations *ops = p->ops;
403     
404     			if (p->irq != PARPORT_IRQ_NONE) {
405     				parport_sunbpp_disable_irq(p);
406     				free_irq(p->irq, p);
407     			}
408     			sbus_iounmap(p->base, p->size);
409     			parport_proc_unregister(p);
410     			parport_unregister_port(p);
411     			kfree (ops);
412     		}
413     		p = next;
414     	}
415     }
416     #endif
417