summaryrefslogtreecommitdiffstats
path: root/arch/m68k/include/asm/sun3xflop.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68k/include/asm/sun3xflop.h')
-rw-r--r--arch/m68k/include/asm/sun3xflop.h263
1 files changed, 263 insertions, 0 deletions
diff --git a/arch/m68k/include/asm/sun3xflop.h b/arch/m68k/include/asm/sun3xflop.h
new file mode 100644
index 000000000..bce8aabb5
--- /dev/null
+++ b/arch/m68k/include/asm/sun3xflop.h
@@ -0,0 +1,263 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* sun3xflop.h: Sun3/80 specific parts of the floppy driver.
+ *
+ * Derived partially from asm-sparc/floppy.h, which is:
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * Sun3x version 2/4/2000 Sam Creasey (sammy@sammy.net)
+ */
+
+#ifndef __ASM_SUN3X_FLOPPY_H
+#define __ASM_SUN3X_FLOPPY_H
+
+#include <linux/pgtable.h>
+#include <asm/page.h>
+#include <asm/irq.h>
+#include <asm/sun3x.h>
+
+/* default interrupt vector */
+#define SUN3X_FDC_IRQ 0x40
+
+/* some constants */
+#define FCR_TC 0x1
+#define FCR_EJECT 0x2
+#define FCR_MTRON 0x4
+#define FCR_DSEL1 0x8
+#define FCR_DSEL0 0x10
+
+/* We don't need no stinkin' I/O port allocation crap. */
+#undef release_region
+#undef request_region
+#define release_region(X, Y) do { } while(0)
+#define request_region(X, Y, Z) (1)
+
+struct sun3xflop_private {
+ volatile unsigned char *status_r;
+ volatile unsigned char *data_r;
+ volatile unsigned char *fcr_r;
+ volatile unsigned char *fvr_r;
+ unsigned char fcr;
+} sun3x_fdc;
+
+/* Super paranoid... */
+#undef HAVE_DISABLE_HLT
+
+/* Routines unique to each controller type on a Sun. */
+static unsigned char sun3x_82072_fd_inb(int port)
+{
+ static int once = 0;
+// udelay(5);
+ switch(port & 7) {
+ default:
+ pr_crit("floppy: Asked to read unknown port %d\n", port);
+ panic("floppy: Port bolixed.");
+ case 4: /* FD_STATUS */
+ return (*sun3x_fdc.status_r) & ~STATUS_DMA;
+ case 5: /* FD_DATA */
+ return (*sun3x_fdc.data_r);
+ case 7: /* FD_DIR */
+ /* ugly hack, I can't find a way to actually detect the disk */
+ if(!once) {
+ once = 1;
+ return 0x80;
+ }
+ return 0;
+ };
+ panic("sun_82072_fd_inb: How did I get here?");
+}
+
+static void sun3x_82072_fd_outb(unsigned char value, int port)
+{
+// udelay(5);
+ switch(port & 7) {
+ default:
+ pr_crit("floppy: Asked to write to unknown port %d\n", port);
+ panic("floppy: Port bolixed.");
+ case 2: /* FD_DOR */
+ /* Oh geese, 82072 on the Sun has no DOR register,
+ * so we make do with taunting the FCR.
+ *
+ * ASSUMPTIONS: There will only ever be one floppy
+ * drive attached to a Sun controller
+ * and it will be at drive zero.
+ */
+
+ {
+ unsigned char fcr = sun3x_fdc.fcr;
+
+ if(value & 0x10) {
+ fcr |= (FCR_DSEL0 | FCR_MTRON);
+ } else
+ fcr &= ~(FCR_DSEL0 | FCR_MTRON);
+
+
+ if(fcr != sun3x_fdc.fcr) {
+ *(sun3x_fdc.fcr_r) = fcr;
+ sun3x_fdc.fcr = fcr;
+ }
+ }
+ break;
+ case 5: /* FD_DATA */
+ *(sun3x_fdc.data_r) = value;
+ break;
+ case 7: /* FD_DCR */
+ *(sun3x_fdc.status_r) = value;
+ break;
+ case 4: /* FD_STATUS */
+ *(sun3x_fdc.status_r) = value;
+ break;
+ }
+ return;
+}
+
+
+asmlinkage irqreturn_t sun3xflop_hardint(int irq, void *dev_id)
+{
+ register unsigned char st;
+
+#undef TRACE_FLPY_INT
+#define NO_FLOPPY_ASSEMBLER
+
+#ifdef TRACE_FLPY_INT
+ static int calls=0;
+ static int bytes=0;
+ static int dma_wait=0;
+#endif
+ if(!doing_pdma) {
+ floppy_interrupt(irq, dev_id);
+ return IRQ_HANDLED;
+ }
+
+// pr_info("doing pdma\n");// st %x\n", sun_fdc->status_82072);
+
+#ifdef TRACE_FLPY_INT
+ if(!calls)
+ bytes = virtual_dma_count;
+#endif
+
+ {
+ register int lcount;
+ register char *lptr;
+
+ for(lcount=virtual_dma_count, lptr=virtual_dma_addr;
+ lcount; lcount--, lptr++) {
+/* st=fd_inb(virtual_dma_port+4) & 0x80 ; */
+ st = *(sun3x_fdc.status_r);
+/* if(st != 0xa0) */
+/* break; */
+
+ if((st & 0x80) == 0) {
+ virtual_dma_count = lcount;
+ virtual_dma_addr = lptr;
+ return IRQ_HANDLED;
+ }
+
+ if((st & 0x20) == 0)
+ break;
+
+ if(virtual_dma_mode)
+/* fd_outb(*lptr, virtual_dma_port+5); */
+ *(sun3x_fdc.data_r) = *lptr;
+ else
+/* *lptr = fd_inb(virtual_dma_port+5); */
+ *lptr = *(sun3x_fdc.data_r);
+ }
+
+ virtual_dma_count = lcount;
+ virtual_dma_addr = lptr;
+/* st = fd_inb(virtual_dma_port+4); */
+ st = *(sun3x_fdc.status_r);
+ }
+
+#ifdef TRACE_FLPY_INT
+ calls++;
+#endif
+// pr_info("st=%02x\n", st);
+ if(st == 0x20)
+ return IRQ_HANDLED;
+ if(!(st & 0x20)) {
+ virtual_dma_residue += virtual_dma_count;
+ virtual_dma_count=0;
+ doing_pdma = 0;
+
+#ifdef TRACE_FLPY_INT
+ pr_info("count=%x, residue=%x calls=%d bytes=%x dma_wait=%d\n",
+ virtual_dma_count, virtual_dma_residue, calls, bytes,
+ dma_wait);
+ calls = 0;
+ dma_wait=0;
+#endif
+
+ floppy_interrupt(irq, dev_id);
+ return IRQ_HANDLED;
+ }
+
+
+#ifdef TRACE_FLPY_INT
+ if(!virtual_dma_count)
+ dma_wait++;
+#endif
+ return IRQ_HANDLED;
+}
+
+static int sun3xflop_request_irq(void)
+{
+ static int once = 0;
+ int error;
+
+ if(!once) {
+ once = 1;
+ error = request_irq(FLOPPY_IRQ, sun3xflop_hardint,
+ 0, "floppy", NULL);
+ return ((error == 0) ? 0 : -1);
+ } else return 0;
+}
+
+static void __init floppy_set_flags(int *ints,int param, int param2);
+
+static int sun3xflop_init(void)
+{
+ if(FLOPPY_IRQ < 0x40)
+ FLOPPY_IRQ = SUN3X_FDC_IRQ;
+
+ sun3x_fdc.status_r = (volatile unsigned char *)SUN3X_FDC;
+ sun3x_fdc.data_r = (volatile unsigned char *)(SUN3X_FDC+1);
+ sun3x_fdc.fcr_r = (volatile unsigned char *)SUN3X_FDC_FCR;
+ sun3x_fdc.fvr_r = (volatile unsigned char *)SUN3X_FDC_FVR;
+ sun3x_fdc.fcr = 0;
+
+ /* Last minute sanity check... */
+ if(*sun3x_fdc.status_r == 0xff) {
+ return -1;
+ }
+
+ *sun3x_fdc.fvr_r = FLOPPY_IRQ;
+
+ *sun3x_fdc.fcr_r = FCR_TC;
+ udelay(10);
+ *sun3x_fdc.fcr_r = 0;
+
+ /* Success... */
+ floppy_set_flags(NULL, 1, FD_BROKEN_DCL); // I don't know how to detect this.
+ allowed_drive_mask = 0x01;
+ return (int) SUN3X_FDC;
+}
+
+/* I'm not precisely sure this eject routine works */
+static int sun3x_eject(void)
+{
+ if(MACH_IS_SUN3X) {
+
+ sun3x_fdc.fcr |= (FCR_DSEL0 | FCR_EJECT);
+ *(sun3x_fdc.fcr_r) = sun3x_fdc.fcr;
+ udelay(10);
+ sun3x_fdc.fcr &= ~(FCR_DSEL0 | FCR_EJECT);
+ *(sun3x_fdc.fcr_r) = sun3x_fdc.fcr;
+ }
+
+ return 0;
+}
+
+#define fd_eject(drive) sun3x_eject()
+
+#endif /* !(__ASM_SUN3X_FLOPPY_H) */