1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Architecture specific parts of the Floppy driver
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * This file is subject to the terms and conditions of the GNU General Public
5*4882a593Smuzhiyun * License. See the file "COPYING" in the main directory of this archive
6*4882a593Smuzhiyun * for more details.
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * Copyright (C) 1995
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun #ifndef __ASM_POWERPC_FLOPPY_H
11*4882a593Smuzhiyun #define __ASM_POWERPC_FLOPPY_H
12*4882a593Smuzhiyun #ifdef __KERNEL__
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #include <asm/machdep.h>
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #define fd_inb(base, reg) inb_p((base) + (reg))
17*4882a593Smuzhiyun #define fd_outb(value, base, reg) outb_p(value, (base) + (reg))
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #define fd_enable_dma() enable_dma(FLOPPY_DMA)
20*4882a593Smuzhiyun #define fd_disable_dma() fd_ops->_disable_dma(FLOPPY_DMA)
21*4882a593Smuzhiyun #define fd_free_dma() fd_ops->_free_dma(FLOPPY_DMA)
22*4882a593Smuzhiyun #define fd_clear_dma_ff() clear_dma_ff(FLOPPY_DMA)
23*4882a593Smuzhiyun #define fd_set_dma_mode(mode) set_dma_mode(FLOPPY_DMA, mode)
24*4882a593Smuzhiyun #define fd_set_dma_count(count) set_dma_count(FLOPPY_DMA, count)
25*4882a593Smuzhiyun #define fd_get_dma_residue() fd_ops->_get_dma_residue(FLOPPY_DMA)
26*4882a593Smuzhiyun #define fd_enable_irq() enable_irq(FLOPPY_IRQ)
27*4882a593Smuzhiyun #define fd_disable_irq() disable_irq(FLOPPY_IRQ)
28*4882a593Smuzhiyun #define fd_free_irq() free_irq(FLOPPY_IRQ, NULL);
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun #include <linux/pci.h>
31*4882a593Smuzhiyun #include <asm/ppc-pci.h> /* for isa_bridge_pcidev */
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #define fd_dma_setup(addr,size,mode,io) fd_ops->_dma_setup(addr,size,mode,io)
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun static int fd_request_dma(void);
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun struct fd_dma_ops {
38*4882a593Smuzhiyun void (*_disable_dma)(unsigned int dmanr);
39*4882a593Smuzhiyun void (*_free_dma)(unsigned int dmanr);
40*4882a593Smuzhiyun int (*_get_dma_residue)(unsigned int dummy);
41*4882a593Smuzhiyun int (*_dma_setup)(char *addr, unsigned long size, int mode, int io);
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun static int virtual_dma_count;
45*4882a593Smuzhiyun static int virtual_dma_residue;
46*4882a593Smuzhiyun static char *virtual_dma_addr;
47*4882a593Smuzhiyun static int virtual_dma_mode;
48*4882a593Smuzhiyun static int doing_vdma;
49*4882a593Smuzhiyun static struct fd_dma_ops *fd_ops;
50*4882a593Smuzhiyun
floppy_hardint(int irq,void * dev_id)51*4882a593Smuzhiyun static irqreturn_t floppy_hardint(int irq, void *dev_id)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun unsigned char st;
54*4882a593Smuzhiyun int lcount;
55*4882a593Smuzhiyun char *lptr;
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun if (!doing_vdma)
58*4882a593Smuzhiyun return floppy_interrupt(irq, dev_id);
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun st = 1;
62*4882a593Smuzhiyun for (lcount=virtual_dma_count, lptr=virtual_dma_addr;
63*4882a593Smuzhiyun lcount; lcount--, lptr++) {
64*4882a593Smuzhiyun st = inb(virtual_dma_port + FD_STATUS);
65*4882a593Smuzhiyun st &= STATUS_DMA | STATUS_READY;
66*4882a593Smuzhiyun if (st != (STATUS_DMA | STATUS_READY))
67*4882a593Smuzhiyun break;
68*4882a593Smuzhiyun if (virtual_dma_mode)
69*4882a593Smuzhiyun outb_p(*lptr, virtual_dma_port + FD_DATA);
70*4882a593Smuzhiyun else
71*4882a593Smuzhiyun *lptr = inb_p(virtual_dma_port + FD_DATA);
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun virtual_dma_count = lcount;
74*4882a593Smuzhiyun virtual_dma_addr = lptr;
75*4882a593Smuzhiyun st = inb(virtual_dma_port + FD_STATUS);
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun if (st == STATUS_DMA)
78*4882a593Smuzhiyun return IRQ_HANDLED;
79*4882a593Smuzhiyun if (!(st & STATUS_DMA)) {
80*4882a593Smuzhiyun virtual_dma_residue += virtual_dma_count;
81*4882a593Smuzhiyun virtual_dma_count=0;
82*4882a593Smuzhiyun doing_vdma = 0;
83*4882a593Smuzhiyun floppy_interrupt(irq, dev_id);
84*4882a593Smuzhiyun return IRQ_HANDLED;
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun return IRQ_HANDLED;
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
vdma_disable_dma(unsigned int dummy)89*4882a593Smuzhiyun static void vdma_disable_dma(unsigned int dummy)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun doing_vdma = 0;
92*4882a593Smuzhiyun virtual_dma_residue += virtual_dma_count;
93*4882a593Smuzhiyun virtual_dma_count=0;
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun
vdma_nop(unsigned int dummy)96*4882a593Smuzhiyun static void vdma_nop(unsigned int dummy)
97*4882a593Smuzhiyun {
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun
vdma_get_dma_residue(unsigned int dummy)101*4882a593Smuzhiyun static int vdma_get_dma_residue(unsigned int dummy)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun return virtual_dma_count + virtual_dma_residue;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun
fd_request_irq(void)107*4882a593Smuzhiyun static int fd_request_irq(void)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun if (can_use_virtual_dma)
110*4882a593Smuzhiyun return request_irq(FLOPPY_IRQ, floppy_hardint,
111*4882a593Smuzhiyun 0, "floppy", NULL);
112*4882a593Smuzhiyun else
113*4882a593Smuzhiyun return request_irq(FLOPPY_IRQ, floppy_interrupt,
114*4882a593Smuzhiyun 0, "floppy", NULL);
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun
vdma_dma_setup(char * addr,unsigned long size,int mode,int io)117*4882a593Smuzhiyun static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun doing_vdma = 1;
120*4882a593Smuzhiyun virtual_dma_port = io;
121*4882a593Smuzhiyun virtual_dma_mode = (mode == DMA_MODE_WRITE);
122*4882a593Smuzhiyun virtual_dma_addr = addr;
123*4882a593Smuzhiyun virtual_dma_count = size;
124*4882a593Smuzhiyun virtual_dma_residue = 0;
125*4882a593Smuzhiyun return 0;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun
hard_dma_setup(char * addr,unsigned long size,int mode,int io)128*4882a593Smuzhiyun static int hard_dma_setup(char *addr, unsigned long size, int mode, int io)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun static unsigned long prev_size;
131*4882a593Smuzhiyun static dma_addr_t bus_addr = 0;
132*4882a593Smuzhiyun static char *prev_addr;
133*4882a593Smuzhiyun static int prev_dir;
134*4882a593Smuzhiyun int dir;
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun doing_vdma = 0;
137*4882a593Smuzhiyun dir = (mode == DMA_MODE_READ) ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun if (bus_addr
140*4882a593Smuzhiyun && (addr != prev_addr || size != prev_size || dir != prev_dir)) {
141*4882a593Smuzhiyun /* different from last time -- unmap prev */
142*4882a593Smuzhiyun pci_unmap_single(isa_bridge_pcidev, bus_addr, prev_size, prev_dir);
143*4882a593Smuzhiyun bus_addr = 0;
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun if (!bus_addr) /* need to map it */
147*4882a593Smuzhiyun bus_addr = pci_map_single(isa_bridge_pcidev, addr, size, dir);
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun /* remember this one as prev */
150*4882a593Smuzhiyun prev_addr = addr;
151*4882a593Smuzhiyun prev_size = size;
152*4882a593Smuzhiyun prev_dir = dir;
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun fd_clear_dma_ff();
155*4882a593Smuzhiyun fd_set_dma_mode(mode);
156*4882a593Smuzhiyun set_dma_addr(FLOPPY_DMA, bus_addr);
157*4882a593Smuzhiyun fd_set_dma_count(size);
158*4882a593Smuzhiyun virtual_dma_port = io;
159*4882a593Smuzhiyun fd_enable_dma();
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun return 0;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun static struct fd_dma_ops real_dma_ops =
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun ._disable_dma = disable_dma,
167*4882a593Smuzhiyun ._free_dma = free_dma,
168*4882a593Smuzhiyun ._get_dma_residue = get_dma_residue,
169*4882a593Smuzhiyun ._dma_setup = hard_dma_setup
170*4882a593Smuzhiyun };
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun static struct fd_dma_ops virt_dma_ops =
173*4882a593Smuzhiyun {
174*4882a593Smuzhiyun ._disable_dma = vdma_disable_dma,
175*4882a593Smuzhiyun ._free_dma = vdma_nop,
176*4882a593Smuzhiyun ._get_dma_residue = vdma_get_dma_residue,
177*4882a593Smuzhiyun ._dma_setup = vdma_dma_setup
178*4882a593Smuzhiyun };
179*4882a593Smuzhiyun
fd_request_dma(void)180*4882a593Smuzhiyun static int fd_request_dma(void)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun if (can_use_virtual_dma & 1) {
183*4882a593Smuzhiyun fd_ops = &virt_dma_ops;
184*4882a593Smuzhiyun return 0;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun else {
187*4882a593Smuzhiyun fd_ops = &real_dma_ops;
188*4882a593Smuzhiyun return request_dma(FLOPPY_DMA, "floppy");
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun static int FDC1 = 0x3f0;
193*4882a593Smuzhiyun static int FDC2 = -1;
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun /*
196*4882a593Smuzhiyun * Again, the CMOS information not available
197*4882a593Smuzhiyun */
198*4882a593Smuzhiyun #define FLOPPY0_TYPE 6
199*4882a593Smuzhiyun #define FLOPPY1_TYPE 0
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun #define N_FDC 2 /* Don't change this! */
202*4882a593Smuzhiyun #define N_DRIVE 8
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun /*
205*4882a593Smuzhiyun * The PowerPC has no problems with floppy DMA crossing 64k borders.
206*4882a593Smuzhiyun */
207*4882a593Smuzhiyun #define CROSS_64KB(a,s) (0)
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun #define EXTRA_FLOPPY_PARAMS
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun #endif /* __KERNEL__ */
212*4882a593Smuzhiyun #endif /* __ASM_POWERPC_FLOPPY_H */
213