1f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg/* floppy.h: Sparc specific parts of the Floppy driver.
2f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg *
310a104f9c591c3b1175bbb03ecb0bc8f2a4a16eeDavid S. Miller * Copyright (C) 1996, 2007, 2008 David S. Miller (davem@davemloft.net)
4f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
5f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg *
6f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * Ultra/PCI support added: Sep 1997  Eddie C. Dost  (ecd@skynet.be)
7f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg */
8f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
9f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#ifndef __ASM_SPARC64_FLOPPY_H
10f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define __ASM_SPARC64_FLOPPY_H
11f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
1210a104f9c591c3b1175bbb03ecb0bc8f2a4a16eeDavid S. Miller#include <linux/of.h>
1310a104f9c591c3b1175bbb03ecb0bc8f2a4a16eeDavid S. Miller#include <linux/of_device.h>
143ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller#include <linux/dma-mapping.h>
15f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
16f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#include <asm/auxio.h>
17f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
18f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg/*
19f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * Define this to enable exchanging drive 0 and 1 if only drive 1 is
20f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * probed on PCI machines.
21f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg */
22f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#undef PCI_FDC_SWAP_DRIVES
23f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
24f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
25f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg/* References:
26f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * 1) Netbsd Sun floppy driver.
27f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * 2) NCR 82077 controller manual
28f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * 3) Intel 82077 controller manual
29f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg */
30f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstruct sun_flpy_controller {
31f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	volatile unsigned char status1_82077; /* Auxiliary Status reg. 1 */
32f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	volatile unsigned char status2_82077; /* Auxiliary Status reg. 2 */
33f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	volatile unsigned char dor_82077;     /* Digital Output reg. */
34f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	volatile unsigned char tapectl_82077; /* Tape Control reg */
35f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	volatile unsigned char status_82077;  /* Main Status Register. */
36f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define drs_82077              status_82077   /* Digital Rate Select reg. */
37f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	volatile unsigned char data_82077;    /* Data fifo. */
38f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	volatile unsigned char ___unused;
39f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	volatile unsigned char dir_82077;     /* Digital Input reg. */
40f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define dcr_82077              dir_82077      /* Config Control reg. */
41f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg};
42f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
43f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg/* You'll only ever find one controller on an Ultra anyways. */
44f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic struct sun_flpy_controller *sun_fdc = (struct sun_flpy_controller *)-1;
45f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgunsigned long fdc_status;
4694a0cb1fc61ab7a0d47d268a7764374efeb2160bGrant Likelystatic struct platform_device *floppy_op = NULL;
47f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
48f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstruct sun_floppy_ops {
49f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	unsigned char	(*fd_inb) (unsigned long port);
50f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	void		(*fd_outb) (unsigned char value, unsigned long port);
51f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	void		(*fd_enable_dma) (void);
52f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	void		(*fd_disable_dma) (void);
53f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	void		(*fd_set_dma_mode) (int);
54f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	void		(*fd_set_dma_addr) (char *);
55f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	void		(*fd_set_dma_count) (int);
56f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	unsigned int	(*get_dma_residue) (void);
57f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	int		(*fd_request_irq) (void);
58f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	void		(*fd_free_irq) (void);
59f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	int		(*fd_eject) (int);
60f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg};
61f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
62f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic struct sun_floppy_ops sun_fdops;
63f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
64f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define fd_inb(port)              sun_fdops.fd_inb(port)
65f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define fd_outb(value,port)       sun_fdops.fd_outb(value,port)
66f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define fd_enable_dma()           sun_fdops.fd_enable_dma()
67f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define fd_disable_dma()          sun_fdops.fd_disable_dma()
68f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define fd_request_dma()          (0) /* nothing... */
69f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define fd_free_dma()             /* nothing... */
70f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define fd_clear_dma_ff()         /* nothing... */
71f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define fd_set_dma_mode(mode)     sun_fdops.fd_set_dma_mode(mode)
72f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define fd_set_dma_addr(addr)     sun_fdops.fd_set_dma_addr(addr)
73f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define fd_set_dma_count(count)   sun_fdops.fd_set_dma_count(count)
74f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define get_dma_residue(x)        sun_fdops.get_dma_residue()
75f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define fd_cacheflush(addr, size) /* nothing... */
76f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define fd_request_irq()          sun_fdops.fd_request_irq()
77f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define fd_free_irq()             sun_fdops.fd_free_irq()
78f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define fd_eject(drive)           sun_fdops.fd_eject(drive)
79f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
80f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg/* Super paranoid... */
81f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#undef HAVE_DISABLE_HLT
82f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
83f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic int sun_floppy_types[2] = { 0, 0 };
84f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
85f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg/* Here is where we catch the floppy driver trying to initialize,
86f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * therefore this is where we call the PROM device tree probing
87f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * routine etc. on the Sparc.
88f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg */
89f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define FLOPPY0_TYPE		sun_floppy_init()
90f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define FLOPPY1_TYPE		sun_floppy_types[1]
91f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
92f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define FDC1			((unsigned long)sun_fdc)
93f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
94f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define N_FDC    1
95f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define N_DRIVE  8
96f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
97f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg/* No 64k boundary crossing problems on the Sparc. */
98f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define CROSS_64KB(a,s) (0)
99f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
100f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic unsigned char sun_82077_fd_inb(unsigned long port)
101f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
102f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	udelay(5);
103f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	switch(port & 7) {
104f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	default:
105f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		printk("floppy: Asked to read unknown port %lx\n", port);
106f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		panic("floppy: Port bolixed.");
107f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	case 4: /* FD_STATUS */
108f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		return sbus_readb(&sun_fdc->status_82077) & ~STATUS_DMA;
109f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	case 5: /* FD_DATA */
110f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		return sbus_readb(&sun_fdc->data_82077);
111f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	case 7: /* FD_DIR */
112f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		/* XXX: Is DCL on 0x80 in sun4m? */
113f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		return sbus_readb(&sun_fdc->dir_82077);
1146cb79b3f3ba2b14590cac02ee13ab7410b6225edJoe Perches	}
115f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	panic("sun_82072_fd_inb: How did I get here?");
116f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
117f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
118f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic void sun_82077_fd_outb(unsigned char value, unsigned long port)
119f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
120f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	udelay(5);
121f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	switch(port & 7) {
122f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	default:
123f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		printk("floppy: Asked to write to unknown port %lx\n", port);
124f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		panic("floppy: Port bolixed.");
125f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	case 2: /* FD_DOR */
126f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		/* Happily, the 82077 has a real DOR register. */
127f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		sbus_writeb(value, &sun_fdc->dor_82077);
128f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		break;
129f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	case 5: /* FD_DATA */
130f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		sbus_writeb(value, &sun_fdc->data_82077);
131f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		break;
132f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	case 7: /* FD_DCR */
133f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		sbus_writeb(value, &sun_fdc->dcr_82077);
134f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		break;
135f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	case 4: /* FD_STATUS */
136f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		sbus_writeb(value, &sun_fdc->status_82077);
137f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		break;
1386cb79b3f3ba2b14590cac02ee13ab7410b6225edJoe Perches	}
139f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	return;
140f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
141f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
142f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg/* For pseudo-dma (Sun floppy drives have no real DMA available to
143f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * them so we must eat the data fifo bytes directly ourselves) we have
144f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * three state variables.  doing_pdma tells our inline low-level
145f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * assembly floppy interrupt entry point whether it should sit and eat
146f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * bytes from the fifo or just transfer control up to the higher level
147f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * floppy interrupt c-code.  I tried very hard but I could not get the
148f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * pseudo-dma to work in c-code without getting many overruns and
149f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * underruns.  If non-zero, doing_pdma encodes the direction of
150f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * the transfer for debugging.  1=read 2=write
151f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg */
152f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgunsigned char *pdma_vaddr;
153f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgunsigned long pdma_size;
154f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgvolatile int doing_pdma = 0;
155f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
156f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg/* This is software state */
157f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgchar *pdma_base = NULL;
158f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgunsigned long pdma_areasize;
159f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
160f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg/* Common routines to all controller types on the Sparc. */
161f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic void sun_fd_disable_dma(void)
162f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
163f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	doing_pdma = 0;
164679bea5e438df70b5d4348fd2da4501aaeacebe0David S. Miller	pdma_base = NULL;
165f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
166f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
167f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic void sun_fd_set_dma_mode(int mode)
168f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
169f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	switch(mode) {
170f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	case DMA_MODE_READ:
171f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		doing_pdma = 1;
172f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		break;
173f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	case DMA_MODE_WRITE:
174f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		doing_pdma = 2;
175f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		break;
176f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	default:
177f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		printk("Unknown dma mode %d\n", mode);
178f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		panic("floppy: Giving up...");
179f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	}
180f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
181f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
182f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic void sun_fd_set_dma_addr(char *buffer)
183f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
184f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	pdma_vaddr = buffer;
185f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
186f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
187f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic void sun_fd_set_dma_count(int length)
188f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
189f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	pdma_size = length;
190f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
191f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
192f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic void sun_fd_enable_dma(void)
193f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
194f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	pdma_base = pdma_vaddr;
195f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	pdma_areasize = pdma_size;
196f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
197f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
198f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgirqreturn_t sparc_floppy_irq(int irq, void *dev_cookie)
199f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
200f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	if (likely(doing_pdma)) {
201f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		void __iomem *stat = (void __iomem *) fdc_status;
202f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		unsigned char *vaddr = pdma_vaddr;
203f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		unsigned long size = pdma_size;
204f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		u8 val;
205f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
206f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		while (size) {
207f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			val = readb(stat);
208f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			if (unlikely(!(val & 0x80))) {
209f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg				pdma_vaddr = vaddr;
210f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg				pdma_size = size;
211f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg				return IRQ_HANDLED;
212f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			}
213f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			if (unlikely(!(val & 0x20))) {
214f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg				pdma_vaddr = vaddr;
215f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg				pdma_size = size;
216f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg				doing_pdma = 0;
217f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg				goto main_interrupt;
218f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			}
219f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			if (val & 0x40) {
220f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg				/* read */
221f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg				*vaddr++ = readb(stat + 1);
222f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			} else {
223f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg				unsigned char data = *vaddr++;
224f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
225f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg				/* write */
226f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg				writeb(data, stat + 1);
227f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			}
228f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			size--;
229f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		}
230f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
231f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		pdma_vaddr = vaddr;
232f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		pdma_size = size;
233f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
234f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		/* Send Terminal Count pulse to floppy controller. */
235f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		val = readb(auxio_register);
236f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		val |= AUXIO_AUX1_FTCNT;
237f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		writeb(val, auxio_register);
238f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		val &= ~AUXIO_AUX1_FTCNT;
239f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		writeb(val, auxio_register);
240f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
241f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		doing_pdma = 0;
242f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	}
243f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
244f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgmain_interrupt:
245f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	return floppy_interrupt(irq, dev_cookie);
246f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
247f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
248f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic int sun_fd_request_irq(void)
249f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
250f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	static int once = 0;
251f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	int error;
252f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
253f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	if(!once) {
254f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		once = 1;
255f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
256f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		error = request_irq(FLOPPY_IRQ, sparc_floppy_irq,
257d2f09b1c17158fa870fb4f78babf1b307cd2685bMichael Opdenacker				    0, "floppy", NULL);
258f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
259f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		return ((error == 0) ? 0 : -1);
260f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	}
261f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	return 0;
262f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
263f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
264f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic void sun_fd_free_irq(void)
265f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
266f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
267f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
268f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic unsigned int sun_get_dma_residue(void)
269f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
270f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	/* XXX This isn't really correct. XXX */
271f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	return 0;
272f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
273f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
274f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic int sun_fd_eject(int drive)
275f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
276f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	set_dor(0x00, 0xff, 0x90);
277f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	udelay(500);
278f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	set_dor(0x00, 0x6f, 0x00);
279f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	udelay(500);
280f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	return 0;
281f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
282f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
283aae7fb87ec4d2df6cb551670b1765cf4e5795a3bDavid S. Miller#include <asm/ebus_dma.h>
284f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#include <asm/ns87303.h>
285f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
286f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic struct ebus_dma_info sun_pci_fd_ebus_dma;
2873ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Millerstatic struct device *sun_floppy_dev;
288f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic int sun_pci_broken_drive = -1;
289f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
290f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstruct sun_pci_dma_op {
291f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	unsigned int 	addr;
292f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	int		len;
293f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	int		direction;
294f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	char		*buf;
295f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg};
296f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic struct sun_pci_dma_op sun_pci_dma_current = { -1U, 0, 0, NULL};
297f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic struct sun_pci_dma_op sun_pci_dma_pending = { -1U, 0, 0, NULL};
298f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
299f05a68653e56ca2f23bccf7e50be69486886f052Sam Ravnborgirqreturn_t floppy_interrupt(int irq, void *dev_id);
300f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
301f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic unsigned char sun_pci_fd_inb(unsigned long port)
302f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
303f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	udelay(5);
304f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	return inb(port);
305f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
306f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
307f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic void sun_pci_fd_outb(unsigned char val, unsigned long port)
308f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
309f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	udelay(5);
310f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	outb(val, port);
311f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
312f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
313f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic void sun_pci_fd_broken_outb(unsigned char val, unsigned long port)
314f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
315f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	udelay(5);
316f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	/*
317f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	 * XXX: Due to SUN's broken floppy connector on AX and AXi
318f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	 *      we need to turn on MOTOR_0 also, if the floppy is
319f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	 *      jumpered to DS1 (like most PC floppies are). I hope
320f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	 *      this does not hurt correct hardware like the AXmp.
321f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	 *      (Eddie, Sep 12 1998).
322f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	 */
323f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	if (port == ((unsigned long)sun_fdc) + 2) {
324f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		if (((val & 0x03) == sun_pci_broken_drive) && (val & 0x20)) {
325f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			val |= 0x10;
326f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		}
327f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	}
328f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	outb(val, port);
329f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
330f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
331f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#ifdef PCI_FDC_SWAP_DRIVES
332f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic void sun_pci_fd_lde_broken_outb(unsigned char val, unsigned long port)
333f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
334f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	udelay(5);
335f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	/*
336f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	 * XXX: Due to SUN's broken floppy connector on AX and AXi
337f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	 *      we need to turn on MOTOR_0 also, if the floppy is
338f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	 *      jumpered to DS1 (like most PC floppies are). I hope
339f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	 *      this does not hurt correct hardware like the AXmp.
340f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	 *      (Eddie, Sep 12 1998).
341f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	 */
342f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	if (port == ((unsigned long)sun_fdc) + 2) {
343f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		if (((val & 0x03) == sun_pci_broken_drive) && (val & 0x10)) {
344f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			val &= ~(0x03);
345f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			val |= 0x21;
346f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		}
347f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	}
348f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	outb(val, port);
349f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
350f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#endif /* PCI_FDC_SWAP_DRIVES */
351f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
352f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic void sun_pci_fd_enable_dma(void)
353f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
354f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	BUG_ON((NULL == sun_pci_dma_pending.buf) 	||
355f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	    (0	  == sun_pci_dma_pending.len) 	||
356f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	    (0	  == sun_pci_dma_pending.direction));
357f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
358f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_pci_dma_current.buf = sun_pci_dma_pending.buf;
359f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_pci_dma_current.len = sun_pci_dma_pending.len;
360f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_pci_dma_current.direction = sun_pci_dma_pending.direction;
361f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
362f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_pci_dma_pending.buf  = NULL;
363f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_pci_dma_pending.len  = 0;
364f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_pci_dma_pending.direction = 0;
365f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_pci_dma_pending.addr = -1U;
366f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
367f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_pci_dma_current.addr =
3683ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller		dma_map_single(sun_floppy_dev,
369f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			       sun_pci_dma_current.buf,
370f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			       sun_pci_dma_current.len,
371f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			       sun_pci_dma_current.direction);
372f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
373f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	ebus_dma_enable(&sun_pci_fd_ebus_dma, 1);
374f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
375f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	if (ebus_dma_request(&sun_pci_fd_ebus_dma,
376f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			     sun_pci_dma_current.addr,
377f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			     sun_pci_dma_current.len))
378f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		BUG();
379f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
380f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
381f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic void sun_pci_fd_disable_dma(void)
382f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
383f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	ebus_dma_enable(&sun_pci_fd_ebus_dma, 0);
384f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	if (sun_pci_dma_current.addr != -1U)
3853ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller		dma_unmap_single(sun_floppy_dev,
386f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg				 sun_pci_dma_current.addr,
387f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg				 sun_pci_dma_current.len,
388f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg				 sun_pci_dma_current.direction);
389f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_pci_dma_current.addr = -1U;
390f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
391f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
392f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic void sun_pci_fd_set_dma_mode(int mode)
393f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
394f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	if (mode == DMA_MODE_WRITE)
3953ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller		sun_pci_dma_pending.direction = DMA_TO_DEVICE;
396f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	else
3973ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller		sun_pci_dma_pending.direction = DMA_FROM_DEVICE;
398f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
399f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	ebus_dma_prepare(&sun_pci_fd_ebus_dma, mode != DMA_MODE_WRITE);
400f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
401f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
402f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic void sun_pci_fd_set_dma_count(int length)
403f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
404f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_pci_dma_pending.len = length;
405f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
406f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
407f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic void sun_pci_fd_set_dma_addr(char *buffer)
408f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
409f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_pci_dma_pending.buf = buffer;
410f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
411f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
412f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic unsigned int sun_pci_get_dma_residue(void)
413f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
414f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	return ebus_dma_residue(&sun_pci_fd_ebus_dma);
415f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
416f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
417f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic int sun_pci_fd_request_irq(void)
418f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
419f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	return ebus_dma_irq_enable(&sun_pci_fd_ebus_dma, 1);
420f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
421f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
422f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic void sun_pci_fd_free_irq(void)
423f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
424f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	ebus_dma_irq_enable(&sun_pci_fd_ebus_dma, 0);
425f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
426f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
427f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic int sun_pci_fd_eject(int drive)
428f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
429f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	return -EINVAL;
430f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
431f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
432f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgvoid sun_pci_fd_dma_callback(struct ebus_dma_info *p, int event, void *cookie)
433f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
434f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	floppy_interrupt(0, NULL);
435f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
436f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
437f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg/*
438f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * Floppy probing, we'd like to use /dev/fd0 for a single Floppy on PCI,
439f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * even if this is configured using DS1, thus looks like /dev/fd1 with
440f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * the cabling used in Ultras.
441f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg */
442f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define DOR	(port + 2)
443f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define MSR	(port + 4)
444f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define FIFO	(port + 5)
445f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
446f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic void sun_pci_fd_out_byte(unsigned long port, unsigned char val,
447f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			        unsigned long reg)
448f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
449f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	unsigned char status;
450f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	int timeout = 1000;
451f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
452f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	while (!((status = inb(MSR)) & 0x80) && --timeout)
453f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		udelay(100);
454f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	outb(val, reg);
455f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
456f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
457f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic unsigned char sun_pci_fd_sensei(unsigned long port)
458f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
459f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	unsigned char result[2] = { 0x70, 0x00 };
460f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	unsigned char status;
461f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	int i = 0;
462f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
463f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_pci_fd_out_byte(port, 0x08, FIFO);
464f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	do {
465f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		int timeout = 1000;
466f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
467f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		while (!((status = inb(MSR)) & 0x80) && --timeout)
468f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			udelay(100);
469f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
470f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		if (!timeout)
471f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			break;
472f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
473f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		if ((status & 0xf0) == 0xd0)
474f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			result[i++] = inb(FIFO);
475f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		else
476f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			break;
477f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	} while (i < 2);
478f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
479f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	return result[0];
480f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
481f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
482f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic void sun_pci_fd_reset(unsigned long port)
483f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
484f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	unsigned char mask = 0x00;
485f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	unsigned char status;
486f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	int timeout = 10000;
487f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
488f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	outb(0x80, MSR);
489f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	do {
490f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		status = sun_pci_fd_sensei(port);
491f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		if ((status & 0xc0) == 0xc0)
492f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			mask |= 1 << (status & 0x03);
493f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		else
494f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			udelay(100);
495f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	} while ((mask != 0x0f) && --timeout);
496f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
497f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
498f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic int sun_pci_fd_test_drive(unsigned long port, int drive)
499f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
500f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	unsigned char status, data;
501f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	int timeout = 1000;
502f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	int ready;
503f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
504f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_pci_fd_reset(port);
505f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
506f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	data = (0x10 << drive) | 0x0c | drive;
507f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_pci_fd_out_byte(port, data, DOR);
508f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
509f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_pci_fd_out_byte(port, 0x07, FIFO);
510f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_pci_fd_out_byte(port, drive & 0x03, FIFO);
511f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
512f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	do {
513f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		udelay(100);
514f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		status = sun_pci_fd_sensei(port);
515f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	} while (((status & 0xc0) == 0x80) && --timeout);
516f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
517f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	if (!timeout)
518f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		ready = 0;
519f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	else
520f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		ready = (status & 0x10) ? 0 : 1;
521f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
522f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_pci_fd_reset(port);
523f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	return ready;
524f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
525f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#undef FIFO
526f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#undef MSR
527f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#undef DOR
528f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
5293ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Millerstatic int __init ebus_fdthree_p(struct device_node *dp)
530f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
5313ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller	if (!strcmp(dp->name, "fdthree"))
532f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		return 1;
5333ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller	if (!strcmp(dp->name, "floppy")) {
534f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		const char *compat;
535f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
5363ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller		compat = of_get_property(dp, "compatible", NULL);
537f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		if (compat && !strcmp(compat, "fdthree"))
538f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			return 1;
539f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	}
540f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	return 0;
541f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
542f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
543f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic unsigned long __init sun_floppy_init(void)
544f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{
545f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	static int initialized = 0;
54610a104f9c591c3b1175bbb03ecb0bc8f2a4a16eeDavid S. Miller	struct device_node *dp;
54794a0cb1fc61ab7a0d47d268a7764374efeb2160bGrant Likely	struct platform_device *op;
54810a104f9c591c3b1175bbb03ecb0bc8f2a4a16eeDavid S. Miller	const char *prop;
54910a104f9c591c3b1175bbb03ecb0bc8f2a4a16eeDavid S. Miller	char state[128];
550f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
551f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	if (initialized)
552f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		return sun_floppy_types[0];
553f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	initialized = 1;
554f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
55510a104f9c591c3b1175bbb03ecb0bc8f2a4a16eeDavid S. Miller	op = NULL;
55610a104f9c591c3b1175bbb03ecb0bc8f2a4a16eeDavid S. Miller
55710a104f9c591c3b1175bbb03ecb0bc8f2a4a16eeDavid S. Miller	for_each_node_by_name(dp, "SUNW,fdtwo") {
55810a104f9c591c3b1175bbb03ecb0bc8f2a4a16eeDavid S. Miller		if (strcmp(dp->parent->name, "sbus"))
55910a104f9c591c3b1175bbb03ecb0bc8f2a4a16eeDavid S. Miller			continue;
56010a104f9c591c3b1175bbb03ecb0bc8f2a4a16eeDavid S. Miller		op = of_find_device_by_node(dp);
56110a104f9c591c3b1175bbb03ecb0bc8f2a4a16eeDavid S. Miller		if (op)
562f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			break;
563f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	}
56410a104f9c591c3b1175bbb03ecb0bc8f2a4a16eeDavid S. Miller	if (op) {
56510a104f9c591c3b1175bbb03ecb0bc8f2a4a16eeDavid S. Miller		floppy_op = op;
5661636f8ac2b08410df4766449f7c86b912443cd99Grant Likely		FLOPPY_IRQ = op->archdata.irqs[0];
567f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	} else {
5683ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller		struct device_node *ebus_dp;
569f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		void __iomem *auxio_reg;
570f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		const char *state_prop;
5713ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller		unsigned long config;
572f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
5733ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller		dp = NULL;
5743ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller		for_each_node_by_name(ebus_dp, "ebus") {
5753ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller			for (dp = ebus_dp->child; dp; dp = dp->sibling) {
5763ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller				if (ebus_fdthree_p(dp))
5773ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller					goto found_fdthree;
578f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			}
579f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		}
5803ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller	found_fdthree:
5813ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller		if (!dp)
582f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			return 0;
583f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
5843ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller		op = of_find_device_by_node(dp);
5853ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller		if (!op)
5863ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller			return 0;
58710a104f9c591c3b1175bbb03ecb0bc8f2a4a16eeDavid S. Miller
58861c7a080a5a061c976988fd4b844dfb468dda255Grant Likely		state_prop = of_get_property(op->dev.of_node, "status", NULL);
589f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		if (state_prop && !strncmp(state_prop, "disabled", 8))
590f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			return 0;
591f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
5921636f8ac2b08410df4766449f7c86b912443cd99Grant Likely		FLOPPY_IRQ = op->archdata.irqs[0];
593f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
594f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		/* Make sure the high density bit is set, some systems
595f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		 * (most notably Ultra5/Ultra10) come up with it clear.
596f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		 */
5973ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller		auxio_reg = (void __iomem *) op->resource[2].start;
598f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		writel(readl(auxio_reg)|0x2, auxio_reg);
599f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
6003ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller		sun_floppy_dev = &op->dev;
601f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
602f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		spin_lock_init(&sun_pci_fd_ebus_dma.lock);
603f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
604f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		/* XXX ioremap */
605f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		sun_pci_fd_ebus_dma.regs = (void __iomem *)
6063ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller			op->resource[1].start;
607f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		if (!sun_pci_fd_ebus_dma.regs)
608f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			return 0;
609f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
610f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		sun_pci_fd_ebus_dma.flags = (EBUS_DMA_FLAG_USE_EBDMA_HANDLER |
611f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg					     EBUS_DMA_FLAG_TCI_DISABLE);
612f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		sun_pci_fd_ebus_dma.callback = sun_pci_fd_dma_callback;
613f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		sun_pci_fd_ebus_dma.client_cookie = NULL;
614f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		sun_pci_fd_ebus_dma.irq = FLOPPY_IRQ;
615f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		strcpy(sun_pci_fd_ebus_dma.name, "floppy");
616f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		if (ebus_dma_register(&sun_pci_fd_ebus_dma))
617f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			return 0;
618f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
619f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		/* XXX ioremap */
6203ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller		sun_fdc = (struct sun_flpy_controller *) op->resource[0].start;
621f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
622f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		sun_fdops.fd_inb = sun_pci_fd_inb;
623f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		sun_fdops.fd_outb = sun_pci_fd_outb;
624f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
625f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		can_use_virtual_dma = use_virtual_dma = 0;
626f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		sun_fdops.fd_enable_dma = sun_pci_fd_enable_dma;
627f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		sun_fdops.fd_disable_dma = sun_pci_fd_disable_dma;
628f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		sun_fdops.fd_set_dma_mode = sun_pci_fd_set_dma_mode;
629f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		sun_fdops.fd_set_dma_addr = sun_pci_fd_set_dma_addr;
630f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		sun_fdops.fd_set_dma_count = sun_pci_fd_set_dma_count;
631f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		sun_fdops.get_dma_residue = sun_pci_get_dma_residue;
632f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
633f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		sun_fdops.fd_request_irq = sun_pci_fd_request_irq;
634f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		sun_fdops.fd_free_irq = sun_pci_fd_free_irq;
635f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
636f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		sun_fdops.fd_eject = sun_pci_fd_eject;
637f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
638f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		fdc_status = (unsigned long) &sun_fdc->status_82077;
639f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
640f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		/*
641f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		 * XXX: Find out on which machines this is really needed.
642f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		 */
643f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		if (1) {
644f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			sun_pci_broken_drive = 1;
645f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			sun_fdops.fd_outb = sun_pci_fd_broken_outb;
646f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		}
647f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
648f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		allowed_drive_mask = 0;
649f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		if (sun_pci_fd_test_drive((unsigned long)sun_fdc, 0))
650f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			sun_floppy_types[0] = 4;
651f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		if (sun_pci_fd_test_drive((unsigned long)sun_fdc, 1))
652f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			sun_floppy_types[1] = 4;
653f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
654f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		/*
655f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		 * Find NS87303 SuperIO config registers (through ecpp).
656f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		 */
6573ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller		config = 0;
6583ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller		for (dp = ebus_dp->child; dp; dp = dp->sibling) {
6593ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller			if (!strcmp(dp->name, "ecpp")) {
66094a0cb1fc61ab7a0d47d268a7764374efeb2160bGrant Likely				struct platform_device *ecpp_op;
6613ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller
6623ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller				ecpp_op = of_find_device_by_node(dp);
6633ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller				if (ecpp_op)
6643ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller					config = ecpp_op->resource[1].start;
6653ae627a19ef0d7b5521a070e309ac7ebe57638d3David S. Miller				goto config_done;
666f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			}
667f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		}
668f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	config_done:
669f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
670f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		/*
671f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		 * Sanity check, is this really the NS87303?
672f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		 */
673f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		switch (config & 0x3ff) {
674f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		case 0x02e:
675f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		case 0x15c:
676f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		case 0x26e:
677f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		case 0x398:
678f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			break;
679f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		default:
680f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			config = 0;
681f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		}
682f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
683f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		if (!config)
684f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			return sun_floppy_types[0];
685f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
686f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		/* Enable PC-AT mode. */
687f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		ns87303_modify(config, ASC, 0, 0xc0);
688f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
689f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#ifdef PCI_FDC_SWAP_DRIVES
690f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		/*
691f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		 * If only Floppy 1 is present, swap drives.
692f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		 */
693f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		if (!sun_floppy_types[0] && sun_floppy_types[1]) {
694f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			/*
695f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			 * Set the drive exchange bit in FCR on NS87303,
696f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			 * make sure other bits are sane before doing so.
697f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			 */
698f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			ns87303_modify(config, FER, FER_EDM, 0);
699f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			ns87303_modify(config, ASC, ASC_DRV2_SEL, 0);
700f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			ns87303_modify(config, FCR, 0, FCR_LDE);
701f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
702f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			config = sun_floppy_types[0];
703f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			sun_floppy_types[0] = sun_floppy_types[1];
704f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			sun_floppy_types[1] = config;
705f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
706f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			if (sun_pci_broken_drive != -1) {
707f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg				sun_pci_broken_drive = 1 - sun_pci_broken_drive;
708f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg				sun_fdops.fd_outb = sun_pci_fd_lde_broken_outb;
709f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg			}
710f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		}
711f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#endif /* PCI_FDC_SWAP_DRIVES */
712f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
713f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		return sun_floppy_types[0];
714f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	}
71561c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	prop = of_get_property(op->dev.of_node, "status", NULL);
71610a104f9c591c3b1175bbb03ecb0bc8f2a4a16eeDavid S. Miller	if (prop && !strncmp(state, "disabled", 8))
717f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		return 0;
718f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
719f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	/*
72010a104f9c591c3b1175bbb03ecb0bc8f2a4a16eeDavid S. Miller	 * We cannot do of_ioremap here: it does request_region,
721f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	 * which the generic floppy driver tries to do once again.
722f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	 * But we must use the sdev resource values as they have
723f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	 * had parent ranges applied.
724f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	 */
725f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_fdc = (struct sun_flpy_controller *)
72610a104f9c591c3b1175bbb03ecb0bc8f2a4a16eeDavid S. Miller		(op->resource[0].start +
72710a104f9c591c3b1175bbb03ecb0bc8f2a4a16eeDavid S. Miller		 ((op->resource[0].flags & 0x1ffUL) << 32UL));
728f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
729f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	/* Last minute sanity check... */
73010a104f9c591c3b1175bbb03ecb0bc8f2a4a16eeDavid S. Miller	if (sbus_readb(&sun_fdc->status1_82077) == 0xff) {
731f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		sun_fdc = (struct sun_flpy_controller *)-1;
732f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg		return 0;
733f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	}
734f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
735f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg        sun_fdops.fd_inb = sun_82077_fd_inb;
736f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg        sun_fdops.fd_outb = sun_82077_fd_outb;
737f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
738f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	can_use_virtual_dma = use_virtual_dma = 1;
739f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_fdops.fd_enable_dma = sun_fd_enable_dma;
740f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_fdops.fd_disable_dma = sun_fd_disable_dma;
741f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_fdops.fd_set_dma_mode = sun_fd_set_dma_mode;
742f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_fdops.fd_set_dma_addr = sun_fd_set_dma_addr;
743f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_fdops.fd_set_dma_count = sun_fd_set_dma_count;
744f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_fdops.get_dma_residue = sun_get_dma_residue;
745f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
746f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_fdops.fd_request_irq = sun_fd_request_irq;
747f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_fdops.fd_free_irq = sun_fd_free_irq;
748f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
749f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_fdops.fd_eject = sun_fd_eject;
750f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
751f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg        fdc_status = (unsigned long) &sun_fdc->status_82077;
752f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
753f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	/* Success... */
754f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	allowed_drive_mask = 0x01;
755f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_floppy_types[0] = 4;
756f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	sun_floppy_types[1] = 0;
757f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
758f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	return sun_floppy_types[0];
759f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg}
760f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
761f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define EXTRA_FLOPPY_PARAMS
762f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
763f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic DEFINE_SPINLOCK(dma_spin_lock);
764f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
765f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define claim_dma_lock() \
766f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg({	unsigned long flags; \
767f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	spin_lock_irqsave(&dma_spin_lock, flags); \
768f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	flags; \
769f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg})
770f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
771f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define release_dma_lock(__flags) \
772f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg	spin_unlock_irqrestore(&dma_spin_lock, __flags);
773f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg
774f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#endif /* !(__ASM_SPARC64_FLOPPY_H) */
775