Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / include / asm-x86_64 / mach-xen / 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  * Modifications for Xen are Copyright (c) 2004, Keir Fraser.
11  */
12 #ifndef __ASM_XEN_X86_64_FLOPPY_H
13 #define __ASM_XEN_X86_64_FLOPPY_H
14
15 #include <linux/vmalloc.h>
16
17 /*
18  * The DMA channel used by the floppy controller cannot access data at
19  * addresses >= 16MB
20  *
21  * Went back to the 1MB limit, as some people had problems with the floppy
22  * driver otherwise. It doesn't matter much for performance anyway, as most
23  * floppy accesses go through the track buffer.
24  */
25 #define _CROSS_64KB(a,s,vdma) \
26 (!(vdma) && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64))
27
28 /* XEN: Hit DMA paths on the head. This trick from asm-m68k/floppy.h. */
29 #include <asm/dma.h>
30 #undef MAX_DMA_ADDRESS
31 #define MAX_DMA_ADDRESS 0
32 #define CROSS_64KB(a,s) (0)
33
34 #define fd_inb(port)                    inb_p(port)
35 #define fd_outb(value,port)             outb_p(value,port)
36
37 #define fd_request_dma()        (0)
38 #define fd_free_dma()           ((void)0)
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()    vdma_get_dma_residue(FLOPPY_DMA)
43 /*
44  * Do not use vmalloc/vfree: floppy_release_irq_and_dma() gets called from
45  * softirq context via motor_off_callback. A generic bug we happen to trigger.
46  */
47 #define fd_dma_mem_alloc(size)  __get_free_pages(GFP_KERNEL|__GFP_NORETRY, get_order(size))
48 #define fd_dma_mem_free(addr, size) free_pages(addr, get_order(size))
49 #define fd_dma_setup(addr, size, mode, io) vdma_dma_setup(addr, size, mode, io)
50
51 static int virtual_dma_count;
52 static int virtual_dma_residue;
53 static char *virtual_dma_addr;
54 static int virtual_dma_mode;
55 static int doing_pdma;
56
57 static irqreturn_t floppy_hardint(int irq, void *dev_id, struct pt_regs * regs)
58 {
59         register unsigned char st;
60
61 #undef TRACE_FLPY_INT
62
63 #ifdef TRACE_FLPY_INT
64         static int calls=0;
65         static int bytes=0;
66         static int dma_wait=0;
67 #endif
68         if (!doing_pdma)
69                 return floppy_interrupt(irq, dev_id, regs);
70
71 #ifdef TRACE_FLPY_INT
72         if(!calls)
73                 bytes = virtual_dma_count;
74 #endif
75
76         {
77                 register int lcount;
78                 register char *lptr;
79
80                 st = 1;
81                 for(lcount=virtual_dma_count, lptr=virtual_dma_addr; 
82                     lcount; lcount--, lptr++) {
83                         st=inb(virtual_dma_port+4) & 0xa0 ;
84                         if(st != 0xa0) 
85                                 break;
86                         if(virtual_dma_mode)
87                                 outb_p(*lptr, virtual_dma_port+5);
88                         else
89                                 *lptr = inb_p(virtual_dma_port+5);
90                 }
91                 virtual_dma_count = lcount;
92                 virtual_dma_addr = lptr;
93                 st = inb(virtual_dma_port+4);
94         }
95
96 #ifdef TRACE_FLPY_INT
97         calls++;
98 #endif
99         if(st == 0x20)
100                 return IRQ_HANDLED;
101         if(!(st & 0x20)) {
102                 virtual_dma_residue += virtual_dma_count;
103                 virtual_dma_count=0;
104 #ifdef TRACE_FLPY_INT
105                 printk("count=%x, residue=%x calls=%d bytes=%d dma_wait=%d\n", 
106                        virtual_dma_count, virtual_dma_residue, calls, bytes,
107                        dma_wait);
108                 calls = 0;
109                 dma_wait=0;
110 #endif
111                 doing_pdma = 0;
112                 floppy_interrupt(irq, dev_id, regs);
113                 return IRQ_HANDLED;
114         }
115 #ifdef TRACE_FLPY_INT
116         if(!virtual_dma_count)
117                 dma_wait++;
118 #endif
119         return IRQ_HANDLED;
120 }
121
122 static void fd_disable_dma(void)
123 {
124         doing_pdma = 0;
125         virtual_dma_residue += virtual_dma_count;
126         virtual_dma_count=0;
127 }
128
129 static int vdma_get_dma_residue(unsigned int dummy)
130 {
131         return virtual_dma_count + virtual_dma_residue;
132 }
133
134
135 static int fd_request_irq(void)
136 {
137         return request_irq(FLOPPY_IRQ, floppy_hardint,
138                            IRQF_DISABLED, "floppy", NULL);
139 }
140
141 #if 0
142 static unsigned long vdma_mem_alloc(unsigned long size)
143 {
144         return (unsigned long) vmalloc(size);
145
146 }
147
148 static void vdma_mem_free(unsigned long addr, unsigned long size)
149 {
150         vfree((void *)addr);
151 }
152 #endif
153
154 static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io)
155 {
156         doing_pdma = 1;
157         virtual_dma_port = io;
158         virtual_dma_mode = (mode  == DMA_MODE_WRITE);
159         virtual_dma_addr = addr;
160         virtual_dma_count = size;
161         virtual_dma_residue = 0;
162         return 0;
163 }
164
165 /* XEN: This trick to force 'virtual DMA' is from include/asm-m68k/floppy.h. */
166 #define FDC1 xen_floppy_init()
167 static int FDC2 = -1;
168
169 static int xen_floppy_init(void)
170 {
171         use_virtual_dma = 1;
172         can_use_virtual_dma = 1;
173         return 0x3f0;
174 }
175
176 /*
177  * Floppy types are stored in the rtc's CMOS RAM and so rtc_lock
178  * is needed to prevent corrupted CMOS RAM in case "insmod floppy"
179  * coincides with another rtc CMOS user.                Paul G.
180  */
181 #define FLOPPY0_TYPE    ({                              \
182         unsigned long flags;                            \
183         unsigned char val;                              \
184         spin_lock_irqsave(&rtc_lock, flags);            \
185         val = (CMOS_READ(0x10) >> 4) & 15;              \
186         spin_unlock_irqrestore(&rtc_lock, flags);       \
187         val;                                            \
188 })
189
190 #define FLOPPY1_TYPE    ({                              \
191         unsigned long flags;                            \
192         unsigned char val;                              \
193         spin_lock_irqsave(&rtc_lock, flags);            \
194         val = CMOS_READ(0x10) & 15;                     \
195         spin_unlock_irqrestore(&rtc_lock, flags);       \
196         val;                                            \
197 })
198
199 #define N_FDC 2
200 #define N_DRIVE 8
201
202 #define FLOPPY_MOTOR_MASK 0xf0
203
204 #define EXTRA_FLOPPY_PARAMS
205
206 #endif /* __ASM_XEN_X86_64_FLOPPY_H */