aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-sparc64/floppy.h
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /include/asm-sparc64/floppy.h
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'include/asm-sparc64/floppy.h')
-rw-r--r--include/asm-sparc64/floppy.h811
1 files changed, 811 insertions, 0 deletions
diff --git a/include/asm-sparc64/floppy.h b/include/asm-sparc64/floppy.h
new file mode 100644
index 000000000000..e071b4b4edfd
--- /dev/null
+++ b/include/asm-sparc64/floppy.h
@@ -0,0 +1,811 @@
1/* $Id: floppy.h,v 1.32 2001/10/26 17:59:36 davem Exp $
2 * asm-sparc64/floppy.h: Sparc specific parts of the Floppy driver.
3 *
4 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
5 * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
6 *
7 * Ultra/PCI support added: Sep 1997 Eddie C. Dost (ecd@skynet.be)
8 */
9
10#ifndef __ASM_SPARC64_FLOPPY_H
11#define __ASM_SPARC64_FLOPPY_H
12
13#include <linux/config.h>
14#include <linux/init.h>
15
16#include <asm/page.h>
17#include <asm/pgtable.h>
18#include <asm/system.h>
19#include <asm/idprom.h>
20#include <asm/oplib.h>
21#include <asm/auxio.h>
22#include <asm/sbus.h>
23#include <asm/irq.h>
24
25
26/*
27 * Define this to enable exchanging drive 0 and 1 if only drive 1 is
28 * probed on PCI machines.
29 */
30#undef PCI_FDC_SWAP_DRIVES
31
32
33/* References:
34 * 1) Netbsd Sun floppy driver.
35 * 2) NCR 82077 controller manual
36 * 3) Intel 82077 controller manual
37 */
38struct sun_flpy_controller {
39 volatile unsigned char status1_82077; /* Auxiliary Status reg. 1 */
40 volatile unsigned char status2_82077; /* Auxiliary Status reg. 2 */
41 volatile unsigned char dor_82077; /* Digital Output reg. */
42 volatile unsigned char tapectl_82077; /* Tape Control reg */
43 volatile unsigned char status_82077; /* Main Status Register. */
44#define drs_82077 status_82077 /* Digital Rate Select reg. */
45 volatile unsigned char data_82077; /* Data fifo. */
46 volatile unsigned char ___unused;
47 volatile unsigned char dir_82077; /* Digital Input reg. */
48#define dcr_82077 dir_82077 /* Config Control reg. */
49};
50
51/* You'll only ever find one controller on an Ultra anyways. */
52static struct sun_flpy_controller *sun_fdc = (struct sun_flpy_controller *)-1;
53unsigned long fdc_status;
54static struct sbus_dev *floppy_sdev = NULL;
55
56struct sun_floppy_ops {
57 unsigned char (*fd_inb) (unsigned long port);
58 void (*fd_outb) (unsigned char value, unsigned long port);
59 void (*fd_enable_dma) (void);
60 void (*fd_disable_dma) (void);
61 void (*fd_set_dma_mode) (int);
62 void (*fd_set_dma_addr) (char *);
63 void (*fd_set_dma_count) (int);
64 unsigned int (*get_dma_residue) (void);
65 int (*fd_request_irq) (void);
66 void (*fd_free_irq) (void);
67 int (*fd_eject) (int);
68};
69
70static struct sun_floppy_ops sun_fdops;
71
72#define fd_inb(port) sun_fdops.fd_inb(port)
73#define fd_outb(value,port) sun_fdops.fd_outb(value,port)
74#define fd_enable_dma() sun_fdops.fd_enable_dma()
75#define fd_disable_dma() sun_fdops.fd_disable_dma()
76#define fd_request_dma() (0) /* nothing... */
77#define fd_free_dma() /* nothing... */
78#define fd_clear_dma_ff() /* nothing... */
79#define fd_set_dma_mode(mode) sun_fdops.fd_set_dma_mode(mode)
80#define fd_set_dma_addr(addr) sun_fdops.fd_set_dma_addr(addr)
81#define fd_set_dma_count(count) sun_fdops.fd_set_dma_count(count)
82#define get_dma_residue(x) sun_fdops.get_dma_residue()
83#define fd_cacheflush(addr, size) /* nothing... */
84#define fd_request_irq() sun_fdops.fd_request_irq()
85#define fd_free_irq() sun_fdops.fd_free_irq()
86#define fd_eject(drive) sun_fdops.fd_eject(drive)
87
88static int FLOPPY_MOTOR_MASK = 0x10;
89
90/* Super paranoid... */
91#undef HAVE_DISABLE_HLT
92
93static int sun_floppy_types[2] = { 0, 0 };
94
95/* Here is where we catch the floppy driver trying to initialize,
96 * therefore this is where we call the PROM device tree probing
97 * routine etc. on the Sparc.
98 */
99#define FLOPPY0_TYPE sun_floppy_init()
100#define FLOPPY1_TYPE sun_floppy_types[1]
101
102#define FDC1 ((unsigned long)sun_fdc)
103
104#define N_FDC 1
105#define N_DRIVE 8
106
107/* No 64k boundary crossing problems on the Sparc. */
108#define CROSS_64KB(a,s) (0)
109
110static unsigned char sun_82077_fd_inb(unsigned long port)
111{
112 udelay(5);
113 switch(port & 7) {
114 default:
115 printk("floppy: Asked to read unknown port %lx\n", port);
116 panic("floppy: Port bolixed.");
117 case 4: /* FD_STATUS */
118 return sbus_readb(&sun_fdc->status_82077) & ~STATUS_DMA;
119 case 5: /* FD_DATA */
120 return sbus_readb(&sun_fdc->data_82077);
121 case 7: /* FD_DIR */
122 /* XXX: Is DCL on 0x80 in sun4m? */
123 return sbus_readb(&sun_fdc->dir_82077);
124 };
125 panic("sun_82072_fd_inb: How did I get here?");
126}
127
128static void sun_82077_fd_outb(unsigned char value, unsigned long port)
129{
130 udelay(5);
131 switch(port & 7) {
132 default:
133 printk("floppy: Asked to write to unknown port %lx\n", port);
134 panic("floppy: Port bolixed.");
135 case 2: /* FD_DOR */
136 /* Happily, the 82077 has a real DOR register. */
137 sbus_writeb(value, &sun_fdc->dor_82077);
138 break;
139 case 5: /* FD_DATA */
140 sbus_writeb(value, &sun_fdc->data_82077);
141 break;
142 case 7: /* FD_DCR */
143 sbus_writeb(value, &sun_fdc->dcr_82077);
144 break;
145 case 4: /* FD_STATUS */
146 sbus_writeb(value, &sun_fdc->status_82077);
147 break;
148 };
149 return;
150}
151
152/* For pseudo-dma (Sun floppy drives have no real DMA available to
153 * them so we must eat the data fifo bytes directly ourselves) we have
154 * three state variables. doing_pdma tells our inline low-level
155 * assembly floppy interrupt entry point whether it should sit and eat
156 * bytes from the fifo or just transfer control up to the higher level
157 * floppy interrupt c-code. I tried very hard but I could not get the
158 * pseudo-dma to work in c-code without getting many overruns and
159 * underruns. If non-zero, doing_pdma encodes the direction of
160 * the transfer for debugging. 1=read 2=write
161 */
162char *pdma_vaddr;
163unsigned long pdma_size;
164volatile int doing_pdma = 0;
165
166/* This is software state */
167char *pdma_base = NULL;
168unsigned long pdma_areasize;
169
170/* Common routines to all controller types on the Sparc. */
171static void sun_fd_disable_dma(void)
172{
173 doing_pdma = 0;
174 if (pdma_base) {
175 mmu_unlockarea(pdma_base, pdma_areasize);
176 pdma_base = NULL;
177 }
178}
179
180static void sun_fd_set_dma_mode(int mode)
181{
182 switch(mode) {
183 case DMA_MODE_READ:
184 doing_pdma = 1;
185 break;
186 case DMA_MODE_WRITE:
187 doing_pdma = 2;
188 break;
189 default:
190 printk("Unknown dma mode %d\n", mode);
191 panic("floppy: Giving up...");
192 }
193}
194
195static void sun_fd_set_dma_addr(char *buffer)
196{
197 pdma_vaddr = buffer;
198}
199
200static void sun_fd_set_dma_count(int length)
201{
202 pdma_size = length;
203}
204
205static void sun_fd_enable_dma(void)
206{
207 pdma_vaddr = mmu_lockarea(pdma_vaddr, pdma_size);
208 pdma_base = pdma_vaddr;
209 pdma_areasize = pdma_size;
210}
211
212/* Our low-level entry point in arch/sparc/kernel/entry.S */
213extern irqreturn_t floppy_hardint(int irq, void *unused, struct pt_regs *regs);
214
215static int sun_fd_request_irq(void)
216{
217 static int once = 0;
218 int error;
219
220 if(!once) {
221 once = 1;
222
223 error = request_fast_irq(FLOPPY_IRQ, floppy_hardint,
224 SA_INTERRUPT, "floppy", NULL);
225
226 return ((error == 0) ? 0 : -1);
227 }
228 return 0;
229}
230
231static void sun_fd_free_irq(void)
232{
233}
234
235static unsigned int sun_get_dma_residue(void)
236{
237 /* XXX This isn't really correct. XXX */
238 return 0;
239}
240
241static int sun_fd_eject(int drive)
242{
243 set_dor(0x00, 0xff, 0x90);
244 udelay(500);
245 set_dor(0x00, 0x6f, 0x00);
246 udelay(500);
247 return 0;
248}
249
250#ifdef CONFIG_PCI
251#include <asm/ebus.h>
252#include <asm/isa.h>
253#include <asm/ns87303.h>
254
255static struct ebus_dma_info sun_pci_fd_ebus_dma;
256static struct pci_dev *sun_pci_ebus_dev;
257static int sun_pci_broken_drive = -1;
258
259struct sun_pci_dma_op {
260 unsigned int addr;
261 int len;
262 int direction;
263 char *buf;
264};
265static struct sun_pci_dma_op sun_pci_dma_current = { -1U, 0, 0, NULL};
266static struct sun_pci_dma_op sun_pci_dma_pending = { -1U, 0, 0, NULL};
267
268extern irqreturn_t floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
269
270static unsigned char sun_pci_fd_inb(unsigned long port)
271{
272 udelay(5);
273 return inb(port);
274}
275
276static void sun_pci_fd_outb(unsigned char val, unsigned long port)
277{
278 udelay(5);
279 outb(val, port);
280}
281
282static void sun_pci_fd_broken_outb(unsigned char val, unsigned long port)
283{
284 udelay(5);
285 /*
286 * XXX: Due to SUN's broken floppy connector on AX and AXi
287 * we need to turn on MOTOR_0 also, if the floppy is
288 * jumpered to DS1 (like most PC floppies are). I hope
289 * this does not hurt correct hardware like the AXmp.
290 * (Eddie, Sep 12 1998).
291 */
292 if (port == ((unsigned long)sun_fdc) + 2) {
293 if (((val & 0x03) == sun_pci_broken_drive) && (val & 0x20)) {
294 val |= 0x10;
295 }
296 }
297 outb(val, port);
298}
299
300#ifdef PCI_FDC_SWAP_DRIVES
301static void sun_pci_fd_lde_broken_outb(unsigned char val, unsigned long port)
302{
303 udelay(5);
304 /*
305 * XXX: Due to SUN's broken floppy connector on AX and AXi
306 * we need to turn on MOTOR_0 also, if the floppy is
307 * jumpered to DS1 (like most PC floppies are). I hope
308 * this does not hurt correct hardware like the AXmp.
309 * (Eddie, Sep 12 1998).
310 */
311 if (port == ((unsigned long)sun_fdc) + 2) {
312 if (((val & 0x03) == sun_pci_broken_drive) && (val & 0x10)) {
313 val &= ~(0x03);
314 val |= 0x21;
315 }
316 }
317 outb(val, port);
318}
319#endif /* PCI_FDC_SWAP_DRIVES */
320
321static void sun_pci_fd_enable_dma(void)
322{
323 BUG_ON((NULL == sun_pci_dma_pending.buf) ||
324 (0 == sun_pci_dma_pending.len) ||
325 (0 == sun_pci_dma_pending.direction));
326
327 sun_pci_dma_current.buf = sun_pci_dma_pending.buf;
328 sun_pci_dma_current.len = sun_pci_dma_pending.len;
329 sun_pci_dma_current.direction = sun_pci_dma_pending.direction;
330
331 sun_pci_dma_pending.buf = NULL;
332 sun_pci_dma_pending.len = 0;
333 sun_pci_dma_pending.direction = 0;
334 sun_pci_dma_pending.addr = -1U;
335
336 sun_pci_dma_current.addr =
337 pci_map_single(sun_pci_ebus_dev,
338 sun_pci_dma_current.buf,
339 sun_pci_dma_current.len,
340 sun_pci_dma_current.direction);
341
342 ebus_dma_enable(&sun_pci_fd_ebus_dma, 1);
343
344 if (ebus_dma_request(&sun_pci_fd_ebus_dma,
345 sun_pci_dma_current.addr,
346 sun_pci_dma_current.len))
347 BUG();
348}
349
350static void sun_pci_fd_disable_dma(void)
351{
352 ebus_dma_enable(&sun_pci_fd_ebus_dma, 0);
353 if (sun_pci_dma_current.addr != -1U)
354 pci_unmap_single(sun_pci_ebus_dev,
355 sun_pci_dma_current.addr,
356 sun_pci_dma_current.len,
357 sun_pci_dma_current.direction);
358 sun_pci_dma_current.addr = -1U;
359}
360
361static void sun_pci_fd_set_dma_mode(int mode)
362{
363 if (mode == DMA_MODE_WRITE)
364 sun_pci_dma_pending.direction = PCI_DMA_TODEVICE;
365 else
366 sun_pci_dma_pending.direction = PCI_DMA_FROMDEVICE;
367
368 ebus_dma_prepare(&sun_pci_fd_ebus_dma, mode != DMA_MODE_WRITE);
369}
370
371static void sun_pci_fd_set_dma_count(int length)
372{
373 sun_pci_dma_pending.len = length;
374}
375
376static void sun_pci_fd_set_dma_addr(char *buffer)
377{
378 sun_pci_dma_pending.buf = buffer;
379}
380
381static unsigned int sun_pci_get_dma_residue(void)
382{
383 return ebus_dma_residue(&sun_pci_fd_ebus_dma);
384}
385
386static int sun_pci_fd_request_irq(void)
387{
388 return ebus_dma_irq_enable(&sun_pci_fd_ebus_dma, 1);
389}
390
391static void sun_pci_fd_free_irq(void)
392{
393 ebus_dma_irq_enable(&sun_pci_fd_ebus_dma, 0);
394}
395
396static int sun_pci_fd_eject(int drive)
397{
398 return -EINVAL;
399}
400
401void sun_pci_fd_dma_callback(struct ebus_dma_info *p, int event, void *cookie)
402{
403 floppy_interrupt(0, NULL, NULL);
404}
405
406/*
407 * Floppy probing, we'd like to use /dev/fd0 for a single Floppy on PCI,
408 * even if this is configured using DS1, thus looks like /dev/fd1 with
409 * the cabling used in Ultras.
410 */
411#define DOR (port + 2)
412#define MSR (port + 4)
413#define FIFO (port + 5)
414
415static void sun_pci_fd_out_byte(unsigned long port, unsigned char val,
416 unsigned long reg)
417{
418 unsigned char status;
419 int timeout = 1000;
420
421 while (!((status = inb(MSR)) & 0x80) && --timeout)
422 udelay(100);
423 outb(val, reg);
424}
425
426static unsigned char sun_pci_fd_sensei(unsigned long port)
427{
428 unsigned char result[2] = { 0x70, 0x00 };
429 unsigned char status;
430 int i = 0;
431
432 sun_pci_fd_out_byte(port, 0x08, FIFO);
433 do {
434 int timeout = 1000;
435
436 while (!((status = inb(MSR)) & 0x80) && --timeout)
437 udelay(100);
438
439 if (!timeout)
440 break;
441
442 if ((status & 0xf0) == 0xd0)
443 result[i++] = inb(FIFO);
444 else
445 break;
446 } while (i < 2);
447
448 return result[0];
449}
450
451static void sun_pci_fd_reset(unsigned long port)
452{
453 unsigned char mask = 0x00;
454 unsigned char status;
455 int timeout = 10000;
456
457 outb(0x80, MSR);
458 do {
459 status = sun_pci_fd_sensei(port);
460 if ((status & 0xc0) == 0xc0)
461 mask |= 1 << (status & 0x03);
462 else
463 udelay(100);
464 } while ((mask != 0x0f) && --timeout);
465}
466
467static int sun_pci_fd_test_drive(unsigned long port, int drive)
468{
469 unsigned char status, data;
470 int timeout = 1000;
471 int ready;
472
473 sun_pci_fd_reset(port);
474
475 data = (0x10 << drive) | 0x0c | drive;
476 sun_pci_fd_out_byte(port, data, DOR);
477
478 sun_pci_fd_out_byte(port, 0x07, FIFO);
479 sun_pci_fd_out_byte(port, drive & 0x03, FIFO);
480
481 do {
482 udelay(100);
483 status = sun_pci_fd_sensei(port);
484 } while (((status & 0xc0) == 0x80) && --timeout);
485
486 if (!timeout)
487 ready = 0;
488 else
489 ready = (status & 0x10) ? 0 : 1;
490
491 sun_pci_fd_reset(port);
492 return ready;
493}
494#undef FIFO
495#undef MSR
496#undef DOR
497
498#endif /* CONFIG_PCI */
499
500#ifdef CONFIG_PCI
501static int __init ebus_fdthree_p(struct linux_ebus_device *edev)
502{
503 if (!strcmp(edev->prom_name, "fdthree"))
504 return 1;
505 if (!strcmp(edev->prom_name, "floppy")) {
506 char compat[16];
507 prom_getstring(edev->prom_node,
508 "compatible",
509 compat, sizeof(compat));
510 compat[15] = '\0';
511 if (!strcmp(compat, "fdthree"))
512 return 1;
513 }
514 return 0;
515}
516#endif
517
518#ifdef CONFIG_PCI
519#undef ISA_FLOPPY_WORKS
520
521#ifdef ISA_FLOPPY_WORKS
522static unsigned long __init isa_floppy_init(void)
523{
524 struct sparc_isa_bridge *isa_br;
525 struct sparc_isa_device *isa_dev = NULL;
526
527 for_each_isa(isa_br) {
528 for_each_isadev(isa_dev, isa_br) {
529 if (!strcmp(isa_dev->prom_name, "dma")) {
530 struct sparc_isa_device *child =
531 isa_dev->child;
532
533 while (child) {
534 if (!strcmp(child->prom_name,
535 "floppy")) {
536 isa_dev = child;
537 goto isa_done;
538 }
539 child = child->next;
540 }
541 }
542 }
543 }
544isa_done:
545 if (!isa_dev)
546 return 0;
547
548 /* We could use DMA on devices behind the ISA bridge, but...
549 *
550 * There is a slight problem. Normally on x86 kit the x86 processor
551 * delays I/O port instructions when the ISA bus "dma in progress"
552 * signal is active. Well, sparc64 systems do not monitor this
553 * signal thus we would need to block all I/O port accesses in software
554 * when a dma transfer is active for some device.
555 */
556
557 sun_fdc = (struct sun_flpy_controller *)isa_dev->resource.start;
558 FLOPPY_IRQ = isa_dev->irq;
559
560 sun_fdops.fd_inb = sun_pci_fd_inb;
561 sun_fdops.fd_outb = sun_pci_fd_outb;
562
563 can_use_virtual_dma = use_virtual_dma = 1;
564 sun_fdops.fd_enable_dma = sun_fd_enable_dma;
565 sun_fdops.fd_disable_dma = sun_fd_disable_dma;
566 sun_fdops.fd_set_dma_mode = sun_fd_set_dma_mode;
567 sun_fdops.fd_set_dma_addr = sun_fd_set_dma_addr;
568 sun_fdops.fd_set_dma_count = sun_fd_set_dma_count;
569 sun_fdops.get_dma_residue = sun_get_dma_residue;
570
571 sun_fdops.fd_request_irq = sun_fd_request_irq;
572 sun_fdops.fd_free_irq = sun_fd_free_irq;
573
574 /* Floppy eject is manual. Actually, could determine this
575 * via presence of 'manual' property in OBP node.
576 */
577 sun_fdops.fd_eject = sun_pci_fd_eject;
578
579 fdc_status = (unsigned long) &sun_fdc->status_82077;
580 FLOPPY_MOTOR_MASK = 0xf0;
581
582 allowed_drive_mask = 0;
583 sun_floppy_types[0] = 0;
584 sun_floppy_types[1] = 4;
585
586 sun_pci_broken_drive = 1;
587 sun_fdops.fd_outb = sun_pci_fd_broken_outb;
588
589 return sun_floppy_types[0];
590}
591#endif /* ISA_FLOPPY_WORKS */
592
593#endif
594
595static unsigned long __init sun_floppy_init(void)
596{
597 char state[128];
598 struct sbus_bus *bus;
599 struct sbus_dev *sdev = NULL;
600 static int initialized = 0;
601
602 if (initialized)
603 return sun_floppy_types[0];
604 initialized = 1;
605
606 for_all_sbusdev (sdev, bus) {
607 if (!strcmp(sdev->prom_name, "SUNW,fdtwo"))
608 break;
609 }
610 if(sdev) {
611 floppy_sdev = sdev;
612 FLOPPY_IRQ = sdev->irqs[0];
613 } else {
614#ifdef CONFIG_PCI
615 struct linux_ebus *ebus;
616 struct linux_ebus_device *edev = NULL;
617 unsigned long config = 0;
618 unsigned long auxio_reg;
619
620 for_each_ebus(ebus) {
621 for_each_ebusdev(edev, ebus) {
622 if (ebus_fdthree_p(edev))
623 goto ebus_done;
624 }
625 }
626 ebus_done:
627 if (!edev) {
628#ifdef ISA_FLOPPY_WORKS
629 return isa_floppy_init();
630#else
631 return 0;
632#endif
633 }
634
635 prom_getproperty(edev->prom_node, "status",
636 state, sizeof(state));
637 if (!strncmp(state, "disabled", 8))
638 return 0;
639
640 FLOPPY_IRQ = edev->irqs[0];
641
642 /* Make sure the high density bit is set, some systems
643 * (most notably Ultra5/Ultra10) come up with it clear.
644 */
645 auxio_reg = edev->resource[2].start;
646 writel(readl(auxio_reg)|0x2, auxio_reg);
647
648 sun_pci_ebus_dev = ebus->self;
649
650 spin_lock_init(&sun_pci_fd_ebus_dma.lock);
651
652 /* XXX ioremap */
653 sun_pci_fd_ebus_dma.regs = edev->resource[1].start;
654 if (!sun_pci_fd_ebus_dma.regs)
655 return 0;
656
657 sun_pci_fd_ebus_dma.flags = (EBUS_DMA_FLAG_USE_EBDMA_HANDLER |
658 EBUS_DMA_FLAG_TCI_DISABLE);
659 sun_pci_fd_ebus_dma.callback = sun_pci_fd_dma_callback;
660 sun_pci_fd_ebus_dma.client_cookie = NULL;
661 sun_pci_fd_ebus_dma.irq = FLOPPY_IRQ;
662 strcpy(sun_pci_fd_ebus_dma.name, "floppy");
663 if (ebus_dma_register(&sun_pci_fd_ebus_dma))
664 return 0;
665
666 /* XXX ioremap */
667 sun_fdc = (struct sun_flpy_controller *)edev->resource[0].start;
668
669 sun_fdops.fd_inb = sun_pci_fd_inb;
670 sun_fdops.fd_outb = sun_pci_fd_outb;
671
672 can_use_virtual_dma = use_virtual_dma = 0;
673 sun_fdops.fd_enable_dma = sun_pci_fd_enable_dma;
674 sun_fdops.fd_disable_dma = sun_pci_fd_disable_dma;
675 sun_fdops.fd_set_dma_mode = sun_pci_fd_set_dma_mode;
676 sun_fdops.fd_set_dma_addr = sun_pci_fd_set_dma_addr;
677 sun_fdops.fd_set_dma_count = sun_pci_fd_set_dma_count;
678 sun_fdops.get_dma_residue = sun_pci_get_dma_residue;
679
680 sun_fdops.fd_request_irq = sun_pci_fd_request_irq;
681 sun_fdops.fd_free_irq = sun_pci_fd_free_irq;
682
683 sun_fdops.fd_eject = sun_pci_fd_eject;
684
685 fdc_status = (unsigned long) &sun_fdc->status_82077;
686 FLOPPY_MOTOR_MASK = 0xf0;
687
688 /*
689 * XXX: Find out on which machines this is really needed.
690 */
691 if (1) {
692 sun_pci_broken_drive = 1;
693 sun_fdops.fd_outb = sun_pci_fd_broken_outb;
694 }
695
696 allowed_drive_mask = 0;
697 if (sun_pci_fd_test_drive((unsigned long)sun_fdc, 0))
698 sun_floppy_types[0] = 4;
699 if (sun_pci_fd_test_drive((unsigned long)sun_fdc, 1))
700 sun_floppy_types[1] = 4;
701
702 /*
703 * Find NS87303 SuperIO config registers (through ecpp).
704 */
705 for_each_ebus(ebus) {
706 for_each_ebusdev(edev, ebus) {
707 if (!strcmp(edev->prom_name, "ecpp")) {
708 config = edev->resource[1].start;
709 goto config_done;
710 }
711 }
712 }
713 config_done:
714
715 /*
716 * Sanity check, is this really the NS87303?
717 */
718 switch (config & 0x3ff) {
719 case 0x02e:
720 case 0x15c:
721 case 0x26e:
722 case 0x398:
723 break;
724 default:
725 config = 0;
726 }
727
728 if (!config)
729 return sun_floppy_types[0];
730
731 /* Enable PC-AT mode. */
732 ns87303_modify(config, ASC, 0, 0xc0);
733
734#ifdef PCI_FDC_SWAP_DRIVES
735 /*
736 * If only Floppy 1 is present, swap drives.
737 */
738 if (!sun_floppy_types[0] && sun_floppy_types[1]) {
739 /*
740 * Set the drive exchange bit in FCR on NS87303,
741 * make shure other bits are sane before doing so.
742 */
743 ns87303_modify(config, FER, FER_EDM, 0);
744 ns87303_modify(config, ASC, ASC_DRV2_SEL, 0);
745 ns87303_modify(config, FCR, 0, FCR_LDE);
746
747 config = sun_floppy_types[0];
748 sun_floppy_types[0] = sun_floppy_types[1];
749 sun_floppy_types[1] = config;
750
751 if (sun_pci_broken_drive != -1) {
752 sun_pci_broken_drive = 1 - sun_pci_broken_drive;
753 sun_fdops.fd_outb = sun_pci_fd_lde_broken_outb;
754 }
755 }
756#endif /* PCI_FDC_SWAP_DRIVES */
757
758 return sun_floppy_types[0];
759#else
760 return 0;
761#endif
762 }
763 prom_getproperty(sdev->prom_node, "status", state, sizeof(state));
764 if(!strncmp(state, "disabled", 8))
765 return 0;
766
767 /*
768 * We cannot do sbus_ioremap here: it does request_region,
769 * which the generic floppy driver tries to do once again.
770 * But we must use the sdev resource values as they have
771 * had parent ranges applied.
772 */
773 sun_fdc = (struct sun_flpy_controller *)
774 (sdev->resource[0].start +
775 ((sdev->resource[0].flags & 0x1ffUL) << 32UL));
776
777 /* Last minute sanity check... */
778 if(sbus_readb(&sun_fdc->status1_82077) == 0xff) {
779 sun_fdc = (struct sun_flpy_controller *)-1;
780 return 0;
781 }
782
783 sun_fdops.fd_inb = sun_82077_fd_inb;
784 sun_fdops.fd_outb = sun_82077_fd_outb;
785
786 can_use_virtual_dma = use_virtual_dma = 1;
787 sun_fdops.fd_enable_dma = sun_fd_enable_dma;
788 sun_fdops.fd_disable_dma = sun_fd_disable_dma;
789 sun_fdops.fd_set_dma_mode = sun_fd_set_dma_mode;
790 sun_fdops.fd_set_dma_addr = sun_fd_set_dma_addr;
791 sun_fdops.fd_set_dma_count = sun_fd_set_dma_count;
792 sun_fdops.get_dma_residue = sun_get_dma_residue;
793
794 sun_fdops.fd_request_irq = sun_fd_request_irq;
795 sun_fdops.fd_free_irq = sun_fd_free_irq;
796
797 sun_fdops.fd_eject = sun_fd_eject;
798
799 fdc_status = (unsigned long) &sun_fdc->status_82077;
800
801 /* Success... */
802 allowed_drive_mask = 0x01;
803 sun_floppy_types[0] = 4;
804 sun_floppy_types[1] = 0;
805
806 return sun_floppy_types[0];
807}
808
809#define EXTRA_FLOPPY_PARAMS
810
811#endif /* !(__ASM_SPARC64_FLOPPY_H) */