File: /usr/include/asm/floppy.h

1     /*
2      * Architecture specific parts of the Floppy driver
3      *
4      * This file is subject to the terms and conditions of the GNU General Public
5      * License.  See the file "COPYING" in the main directory of this archive
6      * for more details.
7      *
8      * Copyright (C) 1995
9      */
10     #ifndef __ASM_I386_FLOPPY_H
11     #define __ASM_I386_FLOPPY_H
12     
13     #include <linux/vmalloc.h>
14     
15     
16     /*
17      * The DMA channel used by the floppy controller cannot access data at
18      * addresses >= 16MB
19      *
20      * Went back to the 1MB limit, as some people had problems with the floppy
21      * driver otherwise. It doesn't matter much for performance anyway, as most
22      * floppy accesses go through the track buffer.
23      */
24     #define _CROSS_64KB(a,s,vdma) \
25     (!vdma && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64))
26     
27     #define CROSS_64KB(a,s) _CROSS_64KB(a,s,use_virtual_dma & 1)
28     
29     
30     #define SW fd_routine[use_virtual_dma&1]
31     #define CSW fd_routine[can_use_virtual_dma & 1]
32     
33     
34     #define fd_inb(port)			inb_p(port)
35     #define fd_outb(port,value)		outb_p(port,value)
36     
37     #define fd_request_dma()        CSW._request_dma(FLOPPY_DMA,"floppy")
38     #define fd_free_dma()           CSW._free_dma(FLOPPY_DMA)
39     #define fd_enable_irq()         enable_irq(FLOPPY_IRQ)
40     #define fd_disable_irq()        disable_irq(FLOPPY_IRQ)
41     #define fd_free_irq()		free_irq(FLOPPY_IRQ, NULL)
42     #define fd_get_dma_residue()    SW._get_dma_residue(FLOPPY_DMA)
43     #define fd_dma_mem_alloc(size)	SW._dma_mem_alloc(size)
44     #define fd_dma_setup(addr, size, mode, io) SW._dma_setup(addr, size, mode, io)
45     
46     #define FLOPPY_CAN_FALLBACK_ON_NODMA
47     
48     static int virtual_dma_count;
49     static int virtual_dma_residue;
50     static char *virtual_dma_addr;
51     static int virtual_dma_mode;
52     static int doing_pdma;
53     
54     static void floppy_hardint(int irq, void *dev_id, struct pt_regs * regs)
55     {
56     	register unsigned char st;
57     
58     #undef TRACE_FLPY_INT
59     #define NO_FLOPPY_ASSEMBLER
60     
61     #ifdef TRACE_FLPY_INT
62     	static int calls=0;
63     	static int bytes=0;
64     	static int dma_wait=0;
65     #endif
66     	if(!doing_pdma) {
67     		floppy_interrupt(irq, dev_id, regs);
68     		return;
69     	}
70     
71     #ifdef TRACE_FLPY_INT
72     	if(!calls)
73     		bytes = virtual_dma_count;
74     #endif
75     
76     #ifndef NO_FLOPPY_ASSEMBLER
77     	__asm__ (
78            "testl %1,%1
79     	je 3f
80     1:	inb %w4,%b0
81     	andb $160,%b0
82     	cmpb $160,%b0
83     	jne 2f
84     	incw %w4
85     	testl %3,%3
86     	jne 4f
87     	inb %w4,%b0
88     	movb %0,(%2)
89     	jmp 5f
90     4:     	movb (%2),%0
91     	outb %b0,%w4
92     5:	decw %w4
93     	outb %0,$0x80
94     	decl %1
95     	incl %2
96     	testl %1,%1
97     	jne 1b
98     3:	inb %w4,%b0
99     2:	"
100            : "=a" ((char) st), 
101            "=c" ((long) virtual_dma_count), 
102            "=S" ((long) virtual_dma_addr)
103            : "b" ((long) virtual_dma_mode),
104            "d" ((short) virtual_dma_port+4), 
105            "1" ((long) virtual_dma_count),
106            "2" ((long) virtual_dma_addr));
107     #else	
108     	{
109     		register int lcount;
110     		register char *lptr;
111     
112     		st = 1;
113     		for(lcount=virtual_dma_count, lptr=virtual_dma_addr; 
114     		    lcount; lcount--, lptr++) {
115     			st=inb(virtual_dma_port+4) & 0xa0 ;
116     			if(st != 0xa0) 
117     				break;
118     			if(virtual_dma_mode)
119     				outb_p(*lptr, virtual_dma_port+5);
120     			else
121     				*lptr = inb_p(virtual_dma_port+5);
122     		}
123     		virtual_dma_count = lcount;
124     		virtual_dma_addr = lptr;
125     		st = inb(virtual_dma_port+4);
126     	}
127     #endif
128     
129     #ifdef TRACE_FLPY_INT
130     	calls++;
131     #endif
132     	if(st == 0x20)
133     		return;
134     	if(!(st & 0x20)) {
135     		virtual_dma_residue += virtual_dma_count;
136     		virtual_dma_count=0;
137     #ifdef TRACE_FLPY_INT
138     		printk("count=%x, residue=%x calls=%d bytes=%d dma_wait=%d\n", 
139     		       virtual_dma_count, virtual_dma_residue, calls, bytes,
140     		       dma_wait);
141     		calls = 0;
142     		dma_wait=0;
143     #endif
144     		doing_pdma = 0;
145     		floppy_interrupt(irq, dev_id, regs);
146     		return;
147     	}
148     #ifdef TRACE_FLPY_INT
149     	if(!virtual_dma_count)
150     		dma_wait++;
151     #endif
152     }
153     
154     static void fd_disable_dma(void)
155     {
156     	if(! (can_use_virtual_dma & 1))
157     		disable_dma(FLOPPY_DMA);
158     	doing_pdma = 0;
159     	virtual_dma_residue += virtual_dma_count;
160     	virtual_dma_count=0;
161     }
162     
163     static int vdma_request_dma(unsigned int dmanr, const char * device_id)
164     {
165     	return 0;
166     }
167     
168     static void vdma_nop(unsigned int dummy)
169     {
170     }
171     
172     
173     static int vdma_get_dma_residue(unsigned int dummy)
174     {
175     	return virtual_dma_count + virtual_dma_residue;
176     }
177     
178     
179     static int fd_request_irq(void)
180     {
181     	if(can_use_virtual_dma)
182     		return request_irq(FLOPPY_IRQ, floppy_hardint,SA_INTERRUPT,
183     						   "floppy", NULL);
184     	else
185     		return request_irq(FLOPPY_IRQ, floppy_interrupt,
186     						   SA_INTERRUPT|SA_SAMPLE_RANDOM,
187     						   "floppy", NULL);	
188     
189     }
190     
191     static unsigned long dma_mem_alloc(unsigned long size)
192     {
193     	return __get_dma_pages(GFP_KERNEL,get_order(size));
194     }
195     
196     
197     static unsigned long vdma_mem_alloc(unsigned long size)
198     {
199     	return (unsigned long) vmalloc(size);
200     
201     }
202     
203     #define nodma_mem_alloc(size) vdma_mem_alloc(size)
204     
205     static void _fd_dma_mem_free(unsigned long addr, unsigned long size)
206     {
207     	if((unsigned int) addr >= (unsigned int) high_memory)
208     		return vfree((void *)addr);
209     	else
210     		free_pages(addr, get_order(size));		
211     }
212     
213     #define fd_dma_mem_free(addr, size)  _fd_dma_mem_free(addr, size) 
214     
215     static void _fd_chose_dma_mode(char *addr, unsigned long size)
216     {
217     	if(can_use_virtual_dma == 2) {
218     		if((unsigned int) addr >= (unsigned int) high_memory ||
219     		   virt_to_bus(addr) >= 0x1000000 ||
220     		   _CROSS_64KB(addr, size, 0))
221     			use_virtual_dma = 1;
222     		else
223     			use_virtual_dma = 0;
224     	} else {
225     		use_virtual_dma = can_use_virtual_dma & 1;
226     	}
227     }
228     
229     #define fd_chose_dma_mode(addr, size) _fd_chose_dma_mode(addr, size)
230     
231     
232     static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io)
233     {
234     	doing_pdma = 1;
235     	virtual_dma_port = io;
236     	virtual_dma_mode = (mode  == DMA_MODE_WRITE);
237     	virtual_dma_addr = addr;
238     	virtual_dma_count = size;
239     	virtual_dma_residue = 0;
240     	return 0;
241     }
242     
243     static int hard_dma_setup(char *addr, unsigned long size, int mode, int io)
244     {
245     #ifdef FLOPPY_SANITY_CHECK
246     	if (CROSS_64KB(addr, size)) {
247     		printk("DMA crossing 64-K boundary %p-%p\n", addr, addr+size);
248     		return -1;
249     	}
250     #endif
251     	/* actual, physical DMA */
252     	doing_pdma = 0;
253     	clear_dma_ff(FLOPPY_DMA);
254     	set_dma_mode(FLOPPY_DMA,mode);
255     	set_dma_addr(FLOPPY_DMA,virt_to_bus(addr));
256     	set_dma_count(FLOPPY_DMA,size);
257     	enable_dma(FLOPPY_DMA);
258     	return 0;
259     }
260     
261     struct fd_routine_l {
262     	int (*_request_dma)(unsigned int dmanr, const char * device_id);
263     	void (*_free_dma)(unsigned int dmanr);
264     	int (*_get_dma_residue)(unsigned int dummy);
265     	unsigned long (*_dma_mem_alloc) (unsigned long size);
266     	int (*_dma_setup)(char *addr, unsigned long size, int mode, int io);
267     } fd_routine[] = {
268     	{
269     		request_dma,
270     		free_dma,
271     		get_dma_residue,
272     		dma_mem_alloc,
273     		hard_dma_setup
274     	},
275     	{
276     		vdma_request_dma,
277     		vdma_nop,
278     		vdma_get_dma_residue,
279     		vdma_mem_alloc,
280     		vdma_dma_setup
281     	}
282     };
283     
284     
285     static int FDC1 = 0x3f0;
286     static int FDC2 = -1;
287     
288     /*
289      * Floppy types are stored in the rtc's CMOS RAM and so rtc_lock
290      * is needed to prevent corrupted CMOS RAM in case "insmod floppy"
291      * coincides with another rtc CMOS user.		Paul G.
292      */
293     #define FLOPPY0_TYPE	({				\
294     	unsigned long flags;				\
295     	unsigned char val;				\
296     	spin_lock_irqsave(&rtc_lock, flags);		\
297     	val = (CMOS_READ(0x10) >> 4) & 15;		\
298     	spin_unlock_irqrestore(&rtc_lock, flags);	\
299     	val;						\
300     })
301     
302     #define FLOPPY1_TYPE	({				\
303     	unsigned long flags;				\
304     	unsigned char val;				\
305     	spin_lock_irqsave(&rtc_lock, flags);		\
306     	val = CMOS_READ(0x10) & 15;			\
307     	spin_unlock_irqrestore(&rtc_lock, flags);	\
308     	val;						\
309     })
310     
311     #define N_FDC 2
312     #define N_DRIVE 8
313     
314     #define FLOPPY_MOTOR_MASK 0xf0
315     
316     #define AUTO_DMA
317     
318     
319     #endif /* __ASM_I386_FLOPPY_H */
320