Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /* asm/floppy.h: Sparc specific parts of the Floppy driver.
0003  *
0004  * Copyright (C) 1995 David S. Miller (davem@davemloft.net)
0005  */
0006 
0007 #ifndef __ASM_SPARC_FLOPPY_H
0008 #define __ASM_SPARC_FLOPPY_H
0009 
0010 #include <linux/of.h>
0011 #include <linux/of_device.h>
0012 #include <linux/pgtable.h>
0013 
0014 #include <asm/idprom.h>
0015 #include <asm/oplib.h>
0016 #include <asm/auxio.h>
0017 #include <asm/setup.h>
0018 #include <asm/page.h>
0019 #include <asm/irq.h>
0020 
0021 /* We don't need no stinkin' I/O port allocation crap. */
0022 #undef release_region
0023 #undef request_region
0024 #define release_region(X, Y)    do { } while(0)
0025 #define request_region(X, Y, Z) (1)
0026 
0027 /* References:
0028  * 1) Netbsd Sun floppy driver.
0029  * 2) NCR 82077 controller manual
0030  * 3) Intel 82077 controller manual
0031  */
0032 struct sun_flpy_controller {
0033     volatile unsigned char status_82072;  /* Main Status reg. */
0034 #define dcr_82072              status_82072   /* Digital Control reg. */
0035 #define status1_82077          status_82072   /* Auxiliary Status reg. 1 */
0036 
0037     volatile unsigned char data_82072;    /* Data fifo. */
0038 #define status2_82077          data_82072     /* Auxiliary Status reg. 2 */
0039 
0040     volatile unsigned char dor_82077;     /* Digital Output reg. */
0041     volatile unsigned char tapectl_82077; /* What the? Tape control reg? */
0042 
0043     volatile unsigned char status_82077;  /* Main Status Register. */
0044 #define drs_82077              status_82077   /* Digital Rate Select reg. */
0045 
0046     volatile unsigned char data_82077;    /* Data fifo. */
0047     volatile unsigned char ___unused;
0048     volatile unsigned char dir_82077;     /* Digital Input reg. */
0049 #define dcr_82077              dir_82077      /* Config Control reg. */
0050 };
0051 
0052 /* You'll only ever find one controller on a SparcStation anyways. */
0053 static struct sun_flpy_controller *sun_fdc = NULL;
0054 
0055 struct sun_floppy_ops {
0056     unsigned char (*fd_inb)(int port);
0057     void (*fd_outb)(unsigned char value, int port);
0058 };
0059 
0060 static struct sun_floppy_ops sun_fdops;
0061 
0062 #define fd_inb(base, reg)         sun_fdops.fd_inb(reg)
0063 #define fd_outb(value, base, reg) sun_fdops.fd_outb(value, reg)
0064 #define fd_enable_dma()           sun_fd_enable_dma()
0065 #define fd_disable_dma()          sun_fd_disable_dma()
0066 #define fd_request_dma()          (0) /* nothing... */
0067 #define fd_free_dma()             /* nothing... */
0068 #define fd_clear_dma_ff()         /* nothing... */
0069 #define fd_set_dma_mode(mode)     sun_fd_set_dma_mode(mode)
0070 #define fd_set_dma_addr(addr)     sun_fd_set_dma_addr(addr)
0071 #define fd_set_dma_count(count)   sun_fd_set_dma_count(count)
0072 #define fd_enable_irq()           /* nothing... */
0073 #define fd_disable_irq()          /* nothing... */
0074 #define fd_request_irq()          sun_fd_request_irq()
0075 #define fd_free_irq()             /* nothing... */
0076 #if 0  /* P3: added by Alain, these cause a MMU corruption. 19960524 XXX */
0077 #define fd_dma_mem_alloc(size)    ((unsigned long) vmalloc(size))
0078 #define fd_dma_mem_free(addr,size) (vfree((void *)(addr)))
0079 #endif
0080 
0081 /* XXX This isn't really correct. XXX */
0082 #define get_dma_residue(x)        (0)
0083 
0084 #define FLOPPY0_TYPE  4
0085 #define FLOPPY1_TYPE  0
0086 
0087 /* Super paranoid... */
0088 #undef HAVE_DISABLE_HLT
0089 
0090 /* Here is where we catch the floppy driver trying to initialize,
0091  * therefore this is where we call the PROM device tree probing
0092  * routine etc. on the Sparc.
0093  */
0094 #define FDC1                      sun_floppy_init()
0095 
0096 #define N_FDC    1
0097 #define N_DRIVE  8
0098 
0099 /* No 64k boundary crossing problems on the Sparc. */
0100 #define CROSS_64KB(a,s) (0)
0101 
0102 /* Routines unique to each controller type on a Sun. */
0103 static void sun_set_dor(unsigned char value, int fdc_82077)
0104 {
0105     if (fdc_82077)
0106         sun_fdc->dor_82077 = value;
0107 }
0108 
0109 static unsigned char sun_read_dir(void)
0110 {
0111     return sun_fdc->dir_82077;
0112 }
0113 
0114 static unsigned char sun_82072_fd_inb(int port)
0115 {
0116     udelay(5);
0117     switch (port) {
0118     default:
0119         printk("floppy: Asked to read unknown port %d\n", port);
0120         panic("floppy: Port bolixed.");
0121     case FD_STATUS:
0122         return sun_fdc->status_82072 & ~STATUS_DMA;
0123     case FD_DATA:
0124         return sun_fdc->data_82072;
0125     case FD_DIR:
0126         return sun_read_dir();
0127     }
0128     panic("sun_82072_fd_inb: How did I get here?");
0129 }
0130 
0131 static void sun_82072_fd_outb(unsigned char value, int port)
0132 {
0133     udelay(5);
0134     switch (port) {
0135     default:
0136         printk("floppy: Asked to write to unknown port %d\n", port);
0137         panic("floppy: Port bolixed.");
0138     case FD_DOR:
0139         sun_set_dor(value, 0);
0140         break;
0141     case FD_DATA:
0142         sun_fdc->data_82072 = value;
0143         break;
0144     case FD_DCR:
0145         sun_fdc->dcr_82072 = value;
0146         break;
0147     case FD_DSR:
0148         sun_fdc->status_82072 = value;
0149         break;
0150     }
0151     return;
0152 }
0153 
0154 static unsigned char sun_82077_fd_inb(int port)
0155 {
0156     udelay(5);
0157     switch (port) {
0158     default:
0159         printk("floppy: Asked to read unknown port %d\n", port);
0160         panic("floppy: Port bolixed.");
0161     case FD_SRA:
0162         return sun_fdc->status1_82077;
0163     case FD_SRB:
0164         return sun_fdc->status2_82077;
0165     case FD_DOR:
0166         return sun_fdc->dor_82077;
0167     case FD_TDR:
0168         return sun_fdc->tapectl_82077;
0169     case FD_STATUS:
0170         return sun_fdc->status_82077 & ~STATUS_DMA;
0171     case FD_DATA:
0172         return sun_fdc->data_82077;
0173     case FD_DIR:
0174         return sun_read_dir();
0175     }
0176     panic("sun_82077_fd_inb: How did I get here?");
0177 }
0178 
0179 static void sun_82077_fd_outb(unsigned char value, int port)
0180 {
0181     udelay(5);
0182     switch (port) {
0183     default:
0184         printk("floppy: Asked to write to unknown port %d\n", port);
0185         panic("floppy: Port bolixed.");
0186     case FD_DOR:
0187         sun_set_dor(value, 1);
0188         break;
0189     case FD_DATA:
0190         sun_fdc->data_82077 = value;
0191         break;
0192     case FD_DCR:
0193         sun_fdc->dcr_82077 = value;
0194         break;
0195     case FD_DSR:
0196         sun_fdc->status_82077 = value;
0197         break;
0198     case FD_TDR:
0199         sun_fdc->tapectl_82077 = value;
0200         break;
0201     }
0202     return;
0203 }
0204 
0205 /* For pseudo-dma (Sun floppy drives have no real DMA available to
0206  * them so we must eat the data fifo bytes directly ourselves) we have
0207  * three state variables.  doing_pdma tells our inline low-level
0208  * assembly floppy interrupt entry point whether it should sit and eat
0209  * bytes from the fifo or just transfer control up to the higher level
0210  * floppy interrupt c-code.  I tried very hard but I could not get the
0211  * pseudo-dma to work in c-code without getting many overruns and
0212  * underruns.  If non-zero, doing_pdma encodes the direction of
0213  * the transfer for debugging.  1=read 2=write
0214  */
0215 
0216 /* Common routines to all controller types on the Sparc. */
0217 static inline void virtual_dma_init(void)
0218 {
0219     /* nothing... */
0220 }
0221 
0222 static inline void sun_fd_disable_dma(void)
0223 {
0224     doing_pdma = 0;
0225     pdma_base = NULL;
0226 }
0227 
0228 static inline void sun_fd_set_dma_mode(int mode)
0229 {
0230     switch(mode) {
0231     case DMA_MODE_READ:
0232         doing_pdma = 1;
0233         break;
0234     case DMA_MODE_WRITE:
0235         doing_pdma = 2;
0236         break;
0237     default:
0238         printk("Unknown dma mode %d\n", mode);
0239         panic("floppy: Giving up...");
0240     }
0241 }
0242 
0243 static inline void sun_fd_set_dma_addr(char *buffer)
0244 {
0245     pdma_vaddr = buffer;
0246 }
0247 
0248 static inline void sun_fd_set_dma_count(int length)
0249 {
0250     pdma_size = length;
0251 }
0252 
0253 static inline void sun_fd_enable_dma(void)
0254 {
0255     pdma_base = pdma_vaddr;
0256     pdma_areasize = pdma_size;
0257 }
0258 
0259 int sparc_floppy_request_irq(unsigned int irq, irq_handler_t irq_handler);
0260 
0261 static int sun_fd_request_irq(void)
0262 {
0263     static int once = 0;
0264 
0265     if (!once) {
0266         once = 1;
0267         return sparc_floppy_request_irq(FLOPPY_IRQ, floppy_interrupt);
0268     } else {
0269         return 0;
0270     }
0271 }
0272 
0273 static struct linux_prom_registers fd_regs[2];
0274 
0275 static int sun_floppy_init(void)
0276 {
0277     struct platform_device *op;
0278     struct device_node *dp;
0279     struct resource r;
0280     char state[128];
0281     phandle fd_node;
0282     phandle tnode;
0283     int num_regs;
0284 
0285     use_virtual_dma = 1;
0286 
0287     /* Forget it if we aren't on a machine that could possibly
0288      * ever have a floppy drive.
0289      */
0290     if (sparc_cpu_model != sun4m) {
0291         /* We certainly don't have a floppy controller. */
0292         goto no_sun_fdc;
0293     }
0294     /* Well, try to find one. */
0295     tnode = prom_getchild(prom_root_node);
0296     fd_node = prom_searchsiblings(tnode, "obio");
0297     if (fd_node != 0) {
0298         tnode = prom_getchild(fd_node);
0299         fd_node = prom_searchsiblings(tnode, "SUNW,fdtwo");
0300     } else {
0301         fd_node = prom_searchsiblings(tnode, "fd");
0302     }
0303     if (fd_node == 0) {
0304         goto no_sun_fdc;
0305     }
0306 
0307     /* The sun4m lets us know if the controller is actually usable. */
0308     if (prom_getproperty(fd_node, "status", state, sizeof(state)) != -1) {
0309         if(!strcmp(state, "disabled")) {
0310             goto no_sun_fdc;
0311         }
0312     }
0313     num_regs = prom_getproperty(fd_node, "reg", (char *) fd_regs, sizeof(fd_regs));
0314     num_regs = (num_regs / sizeof(fd_regs[0]));
0315     prom_apply_obio_ranges(fd_regs, num_regs);
0316     memset(&r, 0, sizeof(r));
0317     r.flags = fd_regs[0].which_io;
0318     r.start = fd_regs[0].phys_addr;
0319     sun_fdc = of_ioremap(&r, 0, fd_regs[0].reg_size, "floppy");
0320 
0321     /* Look up irq in platform_device.
0322      * We try "SUNW,fdtwo" and "fd"
0323      */
0324     op = NULL;
0325     for_each_node_by_name(dp, "SUNW,fdtwo") {
0326         op = of_find_device_by_node(dp);
0327         if (op)
0328             break;
0329     }
0330     if (!op) {
0331         for_each_node_by_name(dp, "fd") {
0332             op = of_find_device_by_node(dp);
0333             if (op)
0334                 break;
0335         }
0336     }
0337     if (!op)
0338         goto no_sun_fdc;
0339 
0340     FLOPPY_IRQ = op->archdata.irqs[0];
0341 
0342     /* Last minute sanity check... */
0343     if (sun_fdc->status_82072 == 0xff) {
0344         sun_fdc = NULL;
0345         goto no_sun_fdc;
0346     }
0347 
0348     sun_fdops.fd_inb = sun_82077_fd_inb;
0349     sun_fdops.fd_outb = sun_82077_fd_outb;
0350     fdc_status = &sun_fdc->status_82077;
0351 
0352     if (sun_fdc->dor_82077 == 0x80) {
0353         sun_fdc->dor_82077 = 0x02;
0354         if (sun_fdc->dor_82077 == 0x80) {
0355             sun_fdops.fd_inb = sun_82072_fd_inb;
0356             sun_fdops.fd_outb = sun_82072_fd_outb;
0357             fdc_status = &sun_fdc->status_82072;
0358         }
0359     }
0360 
0361     /* Success... */
0362     allowed_drive_mask = 0x01;
0363     return (int) sun_fdc;
0364 
0365 no_sun_fdc:
0366     return -1;
0367 }
0368 
0369 static int sparc_eject(void)
0370 {
0371     set_dor(0x00, 0xff, 0x90);
0372     udelay(500);
0373     set_dor(0x00, 0x6f, 0x00);
0374     udelay(500);
0375     return 0;
0376 }
0377 
0378 #define fd_eject(drive) sparc_eject()
0379 
0380 #define EXTRA_FLOPPY_PARAMS
0381 
0382 static DEFINE_SPINLOCK(dma_spin_lock);
0383 
0384 #define claim_dma_lock() \
0385 ({  unsigned long flags; \
0386     spin_lock_irqsave(&dma_spin_lock, flags); \
0387     flags; \
0388 })
0389 
0390 #define release_dma_lock(__flags) \
0391     spin_unlock_irqrestore(&dma_spin_lock, __flags);
0392 
0393 #endif /* !(__ASM_SPARC_FLOPPY_H) */