📄 floppy.h
字号:
/* $Id: floppy.h,v 1.28 2000/02/18 13:50:54 davem 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 <linux/init.h>#include <asm/page.h>#include <asm/pgtable.h>#include <asm/system.h>#include <asm/idprom.h>#include <asm/oplib.h>#include <asm/auxio.h>#include <asm/sbus.h>#include <asm/irq.h>/* * Define this to enable exchanging drive 0 and 1 if only drive 1 is * probed on PCI machines. */#undef PCI_FDC_SWAP_DRIVES/* References: * 1) Netbsd Sun floppy driver. * 2) NCR 82077 controller manual * 3) Intel 82077 controller manual */struct sun_flpy_controller { 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; /* 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. */#define dcr_82077 dir_82077 /* Config Control reg. */};/* You'll only ever find one controller on an Ultra anyways. */static struct sun_flpy_controller *sun_fdc = (struct sun_flpy_controller *)-1;unsigned long fdc_status;static struct sbus_dev *floppy_sdev = NULL;struct sun_floppy_ops { 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_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_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_fdops.fd_request_irq()#define fd_free_irq() sun_fdops.fd_free_irq()#define fd_eject(drive) sun_fdops.fd_eject(drive)static int FLOPPY_MOTOR_MASK = 0x10;/* Super paranoid... */#undef HAVE_DISABLE_HLTstatic int sun_floppy_types[2] = { 0, 0 };/* Here is where we catch the floppy driver trying to initialize, * therefore this is where we call the PROM device tree probing * routine etc. on the Sparc. */#define FLOPPY0_TYPE sun_floppy_init()#define FLOPPY1_TYPE sun_floppy_types[1]#define FDC1 ((unsigned long)sun_fdc)static int FDC2 = -1;#define N_FDC 1#define N_DRIVE 8/* No 64k boundary crossing problems on the Sparc. */#define CROSS_64KB(a,s) (0)static unsigned char sun_82077_fd_inb(unsigned long port){ udelay(5); switch(port & 7) { default: printk("floppy: Asked to read unknown port %lx\n", port); panic("floppy: Port bolixed."); case 4: /* FD_STATUS */ return sbus_readb(&sun_fdc->status_82077) & ~STATUS_DMA; case 5: /* FD_DATA */ return sbus_readb(&sun_fdc->data_82077); case 7: /* FD_DIR */ /* XXX: Is DCL on 0x80 in sun4m? */ return sbus_readb(&sun_fdc->dir_82077); }; panic("sun_82072_fd_inb: How did I get here?");}static void sun_82077_fd_outb(unsigned char value, unsigned long port){ udelay(5); switch(port & 7) { default: 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. */ sbus_writeb(value, &sun_fdc->dor_82077); break; case 5: /* FD_DATA */ sbus_writeb(value, &sun_fdc->data_82077); break; case 7: /* FD_DCR */ sbus_writeb(value, &sun_fdc->dcr_82077); break; case 4: /* FD_STATUS */ sbus_writeb(value, &sun_fdc->status_82077); break; }; return;}/* For pseudo-dma (Sun floppy drives have no real DMA available to * them so we must eat the data fifo bytes directly ourselves) we have * three state variables. doing_pdma tells our inline low-level * assembly floppy interrupt entry point whether it should sit and eat * bytes from the fifo or just transfer control up to the higher level * floppy interrupt c-code. I tried very hard but I could not get the * pseudo-dma to work in c-code without getting many overruns and * underruns. If non-zero, doing_pdma encodes the direction of * the transfer for debugging. 1=read 2=write */char *pdma_vaddr;unsigned long pdma_size;volatile int doing_pdma = 0;/* This is software state */char *pdma_base = 0;unsigned long pdma_areasize;/* Common routines to all controller types on the Sparc. */static __inline__ void virtual_dma_init(void){ /* nothing... */}static void sun_fd_disable_dma(void){ doing_pdma = 0; if (pdma_base) { mmu_unlockarea(pdma_base, pdma_areasize); pdma_base = 0; }}static void sun_fd_set_dma_mode(int mode){ switch(mode) { case DMA_MODE_READ: doing_pdma = 1; break; case DMA_MODE_WRITE: doing_pdma = 2; break; default: printk("Unknown dma mode %d\n", mode); panic("floppy: Giving up..."); }}static void sun_fd_set_dma_addr(char *buffer){ pdma_vaddr = buffer;}static void sun_fd_set_dma_count(int length){ pdma_size = length;}static void sun_fd_enable_dma(void){ pdma_vaddr = mmu_lockarea(pdma_vaddr, pdma_size); pdma_base = pdma_vaddr; pdma_areasize = pdma_size;}/* Our low-level entry point in arch/sparc/kernel/entry.S */extern void floppy_hardint(int irq, void *unused, struct pt_regs *regs);static int sun_fd_request_irq(void){ static int once = 0; int error; if(!once) { once = 1; error = request_fast_irq(FLOPPY_IRQ, floppy_hardint, SA_INTERRUPT, "floppy", NULL); return ((error == 0) ? 0 : -1); } 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>#include <asm/ns87303.h>static struct linux_ebus_dma *sun_pci_fd_ebus_dma;static struct pci_dev *sun_pci_ebus_dev;static int sun_pci_broken_drive = -1;static unsigned int sun_pci_dma_addr = -1U;static int sun_pci_dma_len, sun_pci_dma_direction;extern void floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs);static unsigned char sun_pci_fd_inb(unsigned long port){ udelay(5); return inb(port);}static void sun_pci_fd_outb(unsigned char val, unsigned long port){ udelay(5); outb(val, port);}static void sun_pci_fd_broken_outb(unsigned char val, unsigned long port){ udelay(5); /* * XXX: Due to SUN's broken floppy connector on AX and AXi * we need to turn on MOTOR_0 also, if the floppy is * jumpered to DS1 (like most PC floppies are). I hope * this does not hurt correct hardware like the AXmp. * (Eddie, Sep 12 1998). */ if (port == ((unsigned long)sun_fdc) + 2) { if (((val & 0x03) == sun_pci_broken_drive) && (val & 0x20)) { val |= 0x10; } } outb(val, port);}#ifdef PCI_FDC_SWAP_DRIVESstatic void sun_pci_fd_lde_broken_outb(unsigned char val, unsigned long port){ udelay(5); /* * XXX: Due to SUN's broken floppy connector on AX and AXi * we need to turn on MOTOR_0 also, if the floppy is * jumpered to DS1 (like most PC floppies are). I hope * this does not hurt correct hardware like the AXmp. * (Eddie, Sep 12 1998). */ if (port == ((unsigned long)sun_fdc) + 2) { if (((val & 0x03) == sun_pci_broken_drive) && (val & 0x10)) { val &= ~(0x03); val |= 0x21; } } outb(val, port);}#endif /* PCI_FDC_SWAP_DRIVES */static void sun_pci_fd_reset_dma(void){ unsigned int dcsr; writel(EBUS_DCSR_RESET, &sun_pci_fd_ebus_dma->dcsr); udelay(1); dcsr = EBUS_DCSR_BURST_SZ_16 | EBUS_DCSR_TCI_DIS | EBUS_DCSR_EN_CNT; writel(dcsr, (unsigned long)&sun_pci_fd_ebus_dma->dcsr);}static void sun_pci_fd_enable_dma(void){ unsigned int dcsr; dcsr = readl(&sun_pci_fd_ebus_dma->dcsr); dcsr |= EBUS_DCSR_EN_DMA; writel(dcsr, &sun_pci_fd_ebus_dma->dcsr);}static void sun_pci_fd_disable_dma(void){ unsigned int dcsr; dcsr = readl(&sun_pci_fd_ebus_dma->dcsr); if (dcsr & EBUS_DCSR_EN_DMA) { while (dcsr & EBUS_DCSR_DRAIN) { udelay(1); dcsr = readl(&sun_pci_fd_ebus_dma->dcsr); } dcsr &= ~(EBUS_DCSR_EN_DMA); writel(dcsr, &sun_pci_fd_ebus_dma->dcsr); if (dcsr & EBUS_DCSR_ERR_PEND) { sun_pci_fd_reset_dma(); dcsr &= ~(EBUS_DCSR_ERR_PEND); writel(dcsr, &sun_pci_fd_ebus_dma->dcsr); } } if (sun_pci_dma_addr != -1U) pci_unmap_single(sun_pci_ebus_dev, sun_pci_dma_addr, sun_pci_dma_len, sun_pci_dma_direction); sun_pci_dma_addr = -1U;}static void sun_pci_fd_set_dma_mode(int mode){ unsigned int dcsr; dcsr = readl(&sun_pci_fd_ebus_dma->dcsr); if (readl(&sun_pci_fd_ebus_dma->dbcr)) { sun_pci_fd_reset_dma(); writel(dcsr, &sun_pci_fd_ebus_dma->dcsr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -