patch-2.1.54 linux/include/asm-sparc64/floppy.h

Next file: linux/include/asm-sparc64/namei.h
Previous file: linux/include/asm-sparc64/ebus.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.53/linux/include/asm-sparc64/floppy.h linux/include/asm-sparc64/floppy.h
@@ -1,13 +1,17 @@
-/* $Id: floppy.h,v 1.3 1997/07/11 03:03:22 davem Exp $
+/* $Id: floppy.h,v 1.4 1997/09/05 23:00:15 ecd Exp $
  * asm-sparc64/floppy.h: Sparc specific parts of the Floppy driver.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ *
+ * Ultra/PCI support added: Sep 1997  Eddie C. Dost  (ecd@skynet.be)
  */
 
 #ifndef __ASM_SPARC64_FLOPPY_H
 #define __ASM_SPARC64_FLOPPY_H
 
+#include <linux/config.h>
+
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -23,19 +27,12 @@
  * 3) Intel 82077 controller manual
  */
 struct sun_flpy_controller {
-	volatile unsigned char status_82072;  /* Main Status reg. */
-#define dcr_82072              status_82072   /* Digital Control reg. */
-#define status1_82077          status_82072   /* Auxiliary Status reg. 1 */
-
-	volatile unsigned char data_82072;    /* Data fifo. */
-#define status2_82077          data_82072     /* Auxiliary Status reg. 2 */
-
+	volatile unsigned char status1_82077; /* Auxiliary Status reg. 1 */
+	volatile unsigned char status2_82077; /* Auxiliary Status reg. 2 */
 	volatile unsigned char dor_82077;     /* Digital Output reg. */
 	volatile unsigned char tapectl_82077; /* What the? Tape control reg? */
-
 	volatile unsigned char status_82077;  /* Main Status Register. */
 #define drs_82077              status_82077   /* Digital Rate Select reg. */
-
 	volatile unsigned char data_82077;    /* Data fifo. */
 	volatile unsigned char ___unused;
 	volatile unsigned char dir_82077;     /* Digital Input reg. */
@@ -47,40 +44,42 @@
 volatile unsigned char *fdc_status;
 
 struct sun_floppy_ops {
-	unsigned char (*fd_inb)(int port);
-	void (*fd_outb)(unsigned char value, int port);
+	unsigned char	(*fd_inb) (unsigned long port);
+	void		(*fd_outb) (unsigned char value, unsigned long port);
+	void		(*fd_enable_dma) (void);
+	void		(*fd_disable_dma) (void);
+	void		(*fd_set_dma_mode) (int);
+	void		(*fd_set_dma_addr) (char *);
+	void		(*fd_set_dma_count) (int);
+	unsigned int	(*get_dma_residue) (void);
+	void		(*fd_enable_irq) (void);
+	void		(*fd_disable_irq) (void);
+	int		(*fd_request_irq) (void);
+	void		(*fd_free_irq) (void);
+	int		(*fd_eject) (int);
 };
 
 static struct sun_floppy_ops sun_fdops;
 
 #define fd_inb(port)              sun_fdops.fd_inb(port)
 #define fd_outb(value,port)       sun_fdops.fd_outb(value,port)
-#define fd_enable_dma()           sun_fd_enable_dma()
-#define fd_disable_dma()          sun_fd_disable_dma()
+#define fd_enable_dma()           sun_fdops.fd_enable_dma()
+#define fd_disable_dma()          sun_fdops.fd_disable_dma()
 #define fd_request_dma()          (0) /* nothing... */
 #define fd_free_dma()             /* nothing... */
 #define fd_clear_dma_ff()         /* nothing... */
-#define fd_set_dma_mode(mode)     sun_fd_set_dma_mode(mode)
-#define fd_set_dma_addr(addr)     sun_fd_set_dma_addr(addr)
-#define fd_set_dma_count(count)   sun_fd_set_dma_count(count)
-#define fd_enable_irq()           /* nothing... */
-#define fd_disable_irq()          /* nothing... */
+#define fd_set_dma_mode(mode)     sun_fdops.fd_set_dma_mode(mode)
+#define fd_set_dma_addr(addr)     sun_fdops.fd_set_dma_addr(addr)
+#define fd_set_dma_count(count)   sun_fdops.fd_set_dma_count(count)
+#define get_dma_residue(x)        sun_fdops.get_dma_residue()
+#define fd_enable_irq()           sun_fdops.fd_enable_irq()
+#define fd_disable_irq()          sun_fdops.fd_disable_irq()
 #define fd_cacheflush(addr, size) /* nothing... */
-#define fd_request_irq()          sun_fd_request_irq()
-#define fd_free_irq()             /* nothing... */
-#if 0  /* P3: added by Alain, these cause a MMU corruption. 19960524 XXX */
-#define fd_dma_mem_alloc(size)    ((unsigned long) vmalloc(size))
-#define fd_dma_mem_free(addr,size) (vfree((void *)(addr)))
-#endif
-
-#define FLOPPY_MOTOR_MASK         0x10
-
-/* It's all the same... */
-#define virt_to_bus(x)            (x)
-#define bus_to_virt(x)            (x)
+#define fd_request_irq()          sun_fdops.fd_request_irq()
+#define fd_free_irq()             sun_fdops.fd_free_irq()
+#define fd_eject(drive)           sun_fdops.fd_eject(drive)
 
-/* XXX This isn't really correct. XXX */
-#define get_dma_residue(x)        (0)
+static int FLOPPY_MOTOR_MASK = 0x10;
 
 #define FLOPPY0_TYPE  4
 #define FLOPPY1_TYPE  0
@@ -94,7 +93,7 @@
  */
 #define FDC1                      sun_floppy_init()
 
-static int FDC2=-1;
+static int FDC2 = -1;
 
 #define N_FDC    1
 #define N_DRIVE  8
@@ -102,63 +101,11 @@
 /* No 64k boundary crossing problems on the Sparc. */
 #define CROSS_64KB(a,s) (0)
 
-/* Routines unique to each controller type on a Sun. */
-static unsigned char sun_82072_fd_inb(int port)
+static unsigned char sun_82077_fd_inb(unsigned long port)
 {
 	switch(port & 7) {
 	default:
-		printk("floppy: Asked to read unknown port %d\n", port);
-		panic("floppy: Port bolixed.");
-	case 4: /* FD_STATUS */
-		return sun_fdc->status_82072 & ~STATUS_DMA;
-	case 5: /* FD_DATA */
-		return sun_fdc->data_82072;
-	case 7: /* FD_DIR */
-		return (*AUXREG & AUXIO_FLPY_DCHG)? 0x80: 0;
-	};
-	panic("sun_82072_fd_inb: How did I get here?");
-}
-
-static void sun_82072_fd_outb(unsigned char value, int port)
-{
-	switch(port & 7) {
-	default:
-		printk("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,
-		 * the functionality is implemented via the AUXIO
-		 * I/O register.  So we must emulate the behavior.
-		 *
-		 * ASSUMPTIONS:  There will only ever be one floppy
-		 *               drive attached to a Sun controller
-		 *               and it will be at drive zero.
-		 */
-		{
-			unsigned bits = 0;
-			if (value & 0x10) bits |= AUXIO_FLPY_DSEL;
-			if ((value & 0x80) == 0) bits |= AUXIO_FLPY_EJCT;
-			set_auxio(bits, (~bits) & (AUXIO_FLPY_DSEL|AUXIO_FLPY_EJCT));
-		}
-		break;
-	case 5: /* FD_DATA */
-		sun_fdc->data_82072 = value;
-		break;
-	case 7: /* FD_DCR */
-		sun_fdc->dcr_82072 = value;
-		break;
-	case 4: /* FD_STATUS */
-		sun_fdc->status_82072 = value;
-		break;
-	};
-	return;
-}
-
-static unsigned char sun_82077_fd_inb(int port)
-{
-	switch(port & 7) {
-	default:
-		printk("floppy: Asked to read unknown port %d\n", port);
+		printk("floppy: Asked to read unknown port %lx\n", port);
 		panic("floppy: Port bolixed.");
 	case 4: /* FD_STATUS */
 		return sun_fdc->status_82077 & ~STATUS_DMA;
@@ -171,11 +118,11 @@
 	panic("sun_82072_fd_inb: How did I get here?");
 }
 
-static void sun_82077_fd_outb(unsigned char value, int port)
+static void sun_82077_fd_outb(unsigned char value, unsigned long port)
 {
 	switch(port & 7) {
 	default:
-		printk("floppy: Asked to write to unknown port %d\n", port);
+		printk("floppy: Asked to write to unknown port %lx\n", port);
 		panic("floppy: Port bolixed.");
 	case 2: /* FD_DOR */
 		/* Happily, the 82077 has a real DOR register. */
@@ -218,7 +165,7 @@
 	/* nothing... */
 }
 
-static __inline__ void sun_fd_disable_dma(void)
+static void sun_fd_disable_dma(void)
 {
 	doing_pdma = 0;
 	if (pdma_base) {
@@ -227,7 +174,7 @@
 	}
 }
 
-static __inline__ void sun_fd_set_dma_mode(int mode)
+static void sun_fd_set_dma_mode(int mode)
 {
 	switch(mode) {
 	case DMA_MODE_READ:
@@ -242,17 +189,17 @@
 	}
 }
 
-static __inline__ void sun_fd_set_dma_addr(char *buffer)
+static void sun_fd_set_dma_addr(char *buffer)
 {
 	pdma_vaddr = buffer;
 }
 
-static __inline__ void sun_fd_set_dma_count(int length)
+static void sun_fd_set_dma_count(int length)
 {
 	pdma_size = length;
 }
 
-static __inline__ void sun_fd_enable_dma(void)
+static void sun_fd_enable_dma(void)
 {
 	pdma_vaddr = mmu_lockarea(pdma_vaddr, pdma_size);
 	pdma_base = pdma_vaddr;
@@ -274,23 +221,207 @@
 	} else return 0;
 }
 
+static void sun_fd_enable_irq(void)
+{
+}
+
+static void sun_fd_disable_irq(void)
+{
+}
+
+static void sun_fd_free_irq(void)
+{
+}
+
+static unsigned int sun_get_dma_residue(void)
+{
+	/* XXX This isn't really correct. XXX */
+	return 0;
+}
+
+static int sun_fd_eject(int drive)
+{
+	set_dor(0x00, 0xff, 0x90);
+	udelay(500);
+	set_dor(0x00, 0x6f, 0x00);
+	udelay(500);
+	return 0;
+}
+
+#ifdef CONFIG_PCI
+#include <asm/ebus.h>
+
+static struct linux_ebus_dma *sun_fd_ebus_dma;
+
+extern void floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+
+static unsigned char sun_pci_fd_inb(unsigned long port)
+{
+	return inb(port);
+}
+
+static void sun_pci_fd_outb(unsigned char val, unsigned long port)
+{
+	outb(val, port);
+}
+
+static void sun_pci_fd_enable_dma(void)
+{
+	unsigned int dcsr;
+
+	dcsr = readl((unsigned long)&sun_fd_ebus_dma->dcsr);
+	dcsr |= (EBUS_DCSR_EN_DMA | EBUS_DCSR_EN_CNT);
+	writel(dcsr, (unsigned long)&sun_fd_ebus_dma->dcsr);
+}
+
+static void sun_pci_fd_disable_dma(void)
+{
+	unsigned int dcsr;
+
+	dcsr = readl((unsigned long)&sun_fd_ebus_dma->dcsr);
+	dcsr &= ~(EBUS_DCSR_EN_DMA | EBUS_DCSR_EN_CNT);
+	writel(dcsr, (unsigned long)&sun_fd_ebus_dma->dcsr);
+}
+
+static void sun_pci_fd_set_dma_mode(int mode)
+{
+	unsigned int dcsr;
+
+	dcsr = readl((unsigned long)&sun_fd_ebus_dma->dcsr);
+	/*
+	 * For EBus WRITE means to system memory, which is
+	 * READ for us.
+	 */
+	if (mode == DMA_MODE_WRITE)
+		dcsr &= ~(EBUS_DCSR_WRITE);
+	else
+		dcsr |= EBUS_DCSR_WRITE;
+	writel(dcsr, (unsigned long)&sun_fd_ebus_dma->dcsr);
+}
+
+static void sun_pci_fd_set_dma_count(int length)
+{
+	writel(length, (unsigned long)&sun_fd_ebus_dma->dbcr);
+}
+
+static void sun_pci_fd_set_dma_addr(char *buffer)
+{
+	unsigned int addr;
+
+	addr = virt_to_bus(buffer);
+	writel(addr, (unsigned long)&sun_fd_ebus_dma->dacr);
+}
+
+static void sun_pci_fd_enable_irq(void)
+{
+	unsigned int dcsr;
+
+	dcsr = readl((unsigned long)&sun_fd_ebus_dma->dcsr);
+	dcsr |= EBUS_DCSR_INT_EN;
+	writel(dcsr, (unsigned long)&sun_fd_ebus_dma->dcsr);
+}
+
+static void sun_pci_fd_disable_irq(void)
+{
+	unsigned int dcsr;
+
+	dcsr = readl((unsigned long)&sun_fd_ebus_dma->dcsr);
+	dcsr &= ~(EBUS_DCSR_INT_EN);
+	writel(dcsr, (unsigned long)&sun_fd_ebus_dma->dcsr);
+}
+
+static int sun_pci_fd_request_irq(void)
+{
+	int error;
+
+	error = request_irq(FLOPPY_IRQ, floppy_interrupt, SA_SHIRQ, "floppy", sun_fdc);
+	return ((error == 0) ? 0 : -1);
+}
+
+static void sun_pci_fd_free_irq(void)
+{
+	free_irq(FLOPPY_IRQ, sun_fdc);
+}
+
+static unsigned int sun_pci_get_dma_residue(void)
+{
+	unsigned int res;
+
+	res = readl((unsigned long)&sun_fd_ebus_dma->dbcr);
+	return res;
+}
+
+static int sun_pci_fd_eject(int drive)
+{
+	return -EINVAL;
+}
+#endif
+
 static struct linux_prom_registers fd_regs[2];
 
-static int sun_floppy_init(void)
+static unsigned long sun_floppy_init(void)
 {
 	char state[128];
 	int fd_node, num_regs;
 	struct linux_sbus *bus;
 	struct linux_sbus_device *sdev;
 
-	use_virtual_dma = 1;
-	
 	FLOPPY_IRQ = 11;
 	for_all_sbusdev (sdev, bus) {
 		if (!strcmp(sdev->prom_name, "SUNW,fdtwo")) 
 			break;
 	}
-	if (!bus) return -1;
+	if (!bus) {
+#ifdef CONFIG_PCI
+		struct linux_ebus *ebus;
+		struct linux_ebus_device *edev;
+
+		for_all_ebusdev(edev, ebus) {
+			if (!strcmp(edev->prom_name, "fdthree"))
+				break;
+		}
+		if (!edev)
+			return -1;
+
+		if (check_region(edev->base_address[1], sizeof(struct linux_ebus_dma))) {
+			printk("sun_floppy_init: can't get region %016lx (%d)\n",
+			       edev->base_address[1], (int)sizeof(struct linux_ebus_dma));
+			return -1;
+		}
+		request_region(edev->base_address[1], sizeof(struct linux_ebus_dma), "floppy DMA");
+
+		sun_fdc = (struct sun_flpy_controller *)edev->base_address[0];
+		FLOPPY_IRQ = edev->irqs[0];
+
+		sun_fd_ebus_dma = (struct linux_ebus_dma *)edev->base_address[1];
+		writel(EBUS_DCSR_BURST_SZ_16, (unsigned long)&sun_fd_ebus_dma->dcsr);
+
+		sun_fdops.fd_inb = sun_pci_fd_inb;
+		sun_fdops.fd_outb = sun_pci_fd_outb;
+
+		use_virtual_dma = 0;
+		sun_fdops.fd_enable_dma = sun_pci_fd_enable_dma;
+		sun_fdops.fd_disable_dma = sun_pci_fd_disable_dma;
+		sun_fdops.fd_set_dma_mode = sun_pci_fd_set_dma_mode;
+		sun_fdops.fd_set_dma_addr = sun_pci_fd_set_dma_addr;
+		sun_fdops.fd_set_dma_count = sun_pci_fd_set_dma_count;
+		sun_fdops.get_dma_residue = sun_pci_get_dma_residue;
+
+		sun_fdops.fd_enable_irq = sun_pci_fd_enable_irq;
+		sun_fdops.fd_disable_irq = sun_pci_fd_disable_irq;
+		sun_fdops.fd_request_irq = sun_pci_fd_request_irq;
+		sun_fdops.fd_free_irq = sun_pci_fd_free_irq;
+
+		sun_fdops.fd_eject = sun_pci_fd_eject;
+
+        	fdc_status = &sun_fdc->status_82077;
+		FLOPPY_MOTOR_MASK = 0xf0;
+
+		return (unsigned long)sun_fdc;
+#else
+		return -1;
+#endif
+	}
 	fd_node = sdev->prom_node;
 	prom_getproperty(fd_node, "status", state, sizeof(state));
 	if(!strcmp(state, "disabled")) return -1;
@@ -304,29 +435,34 @@
 								fd_regs[0].which_io,
 								0x0);
 	/* Last minute sanity check... */
-	if(sun_fdc->status_82072 == 0xff) {
+	if(sun_fdc->status1_82077 == 0xff) {
 		sun_fdc = NULL;
 		return -1;
 	}
 
         sun_fdops.fd_inb = sun_82077_fd_inb;
         sun_fdops.fd_outb = sun_82077_fd_outb;
+
+	use_virtual_dma = 1;
+	sun_fdops.fd_enable_dma = sun_fd_enable_dma;
+	sun_fdops.fd_disable_dma = sun_fd_disable_dma;
+	sun_fdops.fd_set_dma_mode = sun_fd_set_dma_mode;
+	sun_fdops.fd_set_dma_addr = sun_fd_set_dma_addr;
+	sun_fdops.fd_set_dma_count = sun_fd_set_dma_count;
+	sun_fdops.get_dma_residue = sun_get_dma_residue;
+
+	sun_fdops.fd_enable_irq = sun_fd_enable_irq;
+	sun_fdops.fd_disable_irq = sun_fd_disable_irq;
+	sun_fdops.fd_request_irq = sun_fd_request_irq;
+	sun_fdops.fd_free_irq = sun_fd_free_irq;
+
+	sun_fdops.fd_eject = sun_fd_eject;
+
         fdc_status = &sun_fdc->status_82077;
         /* printk("DOR @0x%p\n", &sun_fdc->dor_82077); */ /* P3 */
 
 	/* Success... */
-	return (int) ((unsigned long)sun_fdc);
+	return (unsigned long)sun_fdc;
 }
-
-static int sparc_eject(void)
-{
-	set_dor(0x00, 0xff, 0x90);
-	udelay(500);
-	set_dor(0x00, 0x6f, 0x00);
-	udelay(500);
-	return 0;
-}
-
-#define fd_eject(drive) sparc_eject()
 
 #endif /* !(__ASM_SPARC64_FLOPPY_H) */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov