File: /usr/src/linux/include/asm-sparc64/parport.h

1     /* $Id: parport.h,v 1.11 2001/05/11 07:54:24 davem Exp $
2      * parport.h: sparc64 specific parport initialization and dma.
3      *
4      * Copyright (C) 1999  Eddie C. Dost  (ecd@skynet.be)
5      */
6     
7     #ifndef _ASM_SPARC64_PARPORT_H
8     #define _ASM_SPARC64_PARPORT_H 1
9     
10     #include <asm/ebus.h>
11     #include <asm/isa.h>
12     #include <asm/ns87303.h>
13     
14     #define PARPORT_PC_MAX_PORTS	PARPORT_MAX
15     
16     static struct linux_ebus_dma *sparc_ebus_dmas[PARPORT_PC_MAX_PORTS];
17     
18     static __inline__ void
19     reset_dma(unsigned int dmanr)
20     {
21     	unsigned int dcsr;
22     
23     	writel(EBUS_DCSR_RESET, &sparc_ebus_dmas[dmanr]->dcsr);
24     	udelay(1);
25     	dcsr = EBUS_DCSR_BURST_SZ_16 | EBUS_DCSR_TCI_DIS |
26     	       EBUS_DCSR_EN_CNT | EBUS_DCSR_INT_EN;
27     	writel(dcsr, &sparc_ebus_dmas[dmanr]->dcsr);
28     }
29     
30     static __inline__ void
31     enable_dma(unsigned int dmanr)
32     {
33     	unsigned int dcsr;
34     
35     	dcsr = readl(&sparc_ebus_dmas[dmanr]->dcsr);
36     	dcsr |= EBUS_DCSR_EN_DMA;
37     	writel(dcsr, &sparc_ebus_dmas[dmanr]->dcsr);
38     }
39     
40     static __inline__ void
41     disable_dma(unsigned int dmanr)
42     {
43     	unsigned int dcsr;
44     
45     	dcsr = readl(&sparc_ebus_dmas[dmanr]->dcsr);
46     	if (dcsr & EBUS_DCSR_EN_DMA) {
47     		while (dcsr & EBUS_DCSR_DRAIN) {
48     			udelay(1);
49     			dcsr = readl(&sparc_ebus_dmas[dmanr]->dcsr);
50     		}
51     		dcsr &= ~(EBUS_DCSR_EN_DMA);
52     		writel(dcsr, &sparc_ebus_dmas[dmanr]->dcsr);
53     
54     		dcsr = readl(&sparc_ebus_dmas[dmanr]->dcsr);
55     		if (dcsr & EBUS_DCSR_ERR_PEND)
56     			reset_dma(dmanr);
57     	}
58     }
59     
60     static __inline__ void
61     clear_dma_ff(unsigned int dmanr)
62     {
63     	/* nothing */
64     }
65     
66     static __inline__ void
67     set_dma_mode(unsigned int dmanr, char mode)
68     {
69     	unsigned int dcsr;
70     
71     	dcsr = readl(&sparc_ebus_dmas[dmanr]->dcsr);
72     	dcsr |= EBUS_DCSR_EN_CNT | EBUS_DCSR_TC;
73     	if (mode == DMA_MODE_WRITE)
74     		dcsr &= ~(EBUS_DCSR_WRITE);
75     	else
76     		dcsr |= EBUS_DCSR_WRITE;
77     	writel(dcsr, &sparc_ebus_dmas[dmanr]->dcsr);
78     }
79     
80     static __inline__ void
81     set_dma_addr(unsigned int dmanr, unsigned int addr)
82     {
83     	writel(addr, &sparc_ebus_dmas[dmanr]->dacr);
84     }
85     
86     static __inline__ void
87     set_dma_count(unsigned int dmanr, unsigned int count)
88     {
89     	writel(count, &sparc_ebus_dmas[dmanr]->dbcr);
90     }
91     
92     static __inline__ int
93     get_dma_residue(unsigned int dmanr)
94     {
95     	int res;
96     
97     	res = readl(&sparc_ebus_dmas[dmanr]->dbcr);
98     	if (res != 0)
99     		reset_dma(dmanr);
100     	return res;
101     }
102     
103     static int ebus_ecpp_p(struct linux_ebus_device *edev)
104     {
105     	if (!strcmp(edev->prom_name, "ecpp"))
106     		return 1;
107     	if (!strcmp(edev->prom_name, "parallel")) {
108     		char compat[19];
109     		prom_getstring(edev->prom_node,
110     			       "compatible",
111     			       compat, sizeof(compat));
112     		compat[18] = '\0';
113     		if (!strcmp(compat, "ecpp"))
114     			return 1;
115     		if (!strcmp(compat, "ns87317-ecpp") &&
116     		    !strcmp(compat + 13, "ecpp"))
117     			return 1;
118     	}
119     	return 0;
120     }
121     
122     static int parport_isa_probe(int count)
123     {
124     	struct isa_bridge *isa_br;
125     	struct isa_device *isa_dev;
126     
127     	for_each_isa(isa_br) {
128     		for_each_isadev(isa_dev, isa_br) {
129     			struct isa_device *child;
130     			unsigned long base;
131     
132     			if (strcmp(isa_dev->prom_name, "dma"))
133     				continue;
134     
135     			child = isa_dev->child;
136     			while (child) {
137     				if (!strcmp(child->prom_name, "parallel"))
138     					break;
139     				child = child->next;
140     			}
141     			if (!child)
142     				continue;
143     
144     			base = child->resource.start;
145     
146     			/* No DMA, see commentary in
147     			 * asm-sparc64/floppy.h:isa_floppy_init()
148     			 */
149     			if (parport_pc_probe_port(base, base + 0x400,
150     						  child->irq, PARPORT_DMA_NOFIFO,
151     						  child->bus->self))
152     				count++;
153     		}
154     	}
155     
156     	return count;
157     }
158     
159     static int parport_pc_find_nonpci_ports (int autoirq, int autodma)
160     {
161     	struct linux_ebus *ebus;
162     	struct linux_ebus_device *edev;
163     	int count = 0;
164     
165     	if (!pci_present())
166     		return 0;
167     
168     	for_each_ebus(ebus) {
169     		for_each_ebusdev(edev, ebus) {
170     			if (ebus_ecpp_p(edev)) {
171     				unsigned long base = edev->resource[0].start;
172     				unsigned long config = edev->resource[1].start;
173     
174     				sparc_ebus_dmas[count] =
175     						(struct linux_ebus_dma *)
176     							edev->resource[2].start;
177     				reset_dma(count);
178     
179     				/* Configure IRQ to Push Pull, Level Low */
180     				/* Enable ECP, set bit 2 of the CTR first */
181     				outb(0x04, base + 0x02);
182     				ns87303_modify(config, PCR,
183     					       PCR_EPP_ENABLE |
184     					       PCR_IRQ_ODRAIN,
185     					       PCR_ECP_ENABLE |
186     					       PCR_ECP_CLK_ENA |
187     					       PCR_IRQ_POLAR);
188     
189     				/* CTR bit 5 controls direction of port */
190     				ns87303_modify(config, PTR,
191     					       0, PTR_LPT_REG_DIR);
192     
193     				if (parport_pc_probe_port(base, base + 0x400,
194     							  edev->irqs[0],
195     							  count, ebus->self))
196     					count++;
197     			}
198     		}
199     	}
200     
201     	count = parport_isa_probe(count);
202     
203     	return count;
204     }
205     
206     #endif /* !(_ASM_SPARC64_PARPORT_H */
207