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