linux/arch/m68k/include/asm/sun3xflop.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/* sun3xflop.h: Sun3/80 specific parts of the floppy driver.
   3 *
   4 * Derived partially from asm-sparc/floppy.h, which is:
   5 *     Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
   6 *
   7 * Sun3x version 2/4/2000 Sam Creasey (sammy@sammy.net)
   8 */
   9
  10#ifndef __ASM_SUN3X_FLOPPY_H
  11#define __ASM_SUN3X_FLOPPY_H
  12
  13#include <linux/pgtable.h>
  14#include <asm/page.h>
  15#include <asm/irq.h>
  16#include <asm/sun3x.h>
  17
  18/* default interrupt vector */
  19#define SUN3X_FDC_IRQ 0x40
  20
  21/* some constants */
  22#define FCR_TC 0x1
  23#define FCR_EJECT 0x2
  24#define FCR_MTRON 0x4
  25#define FCR_DSEL1 0x8
  26#define FCR_DSEL0 0x10
  27
  28/* We don't need no stinkin' I/O port allocation crap. */
  29#undef release_region
  30#undef request_region
  31#define release_region(X, Y)    do { } while(0)
  32#define request_region(X, Y, Z) (1)
  33
  34struct sun3xflop_private {
  35        volatile unsigned char *status_r;
  36        volatile unsigned char *data_r;
  37        volatile unsigned char *fcr_r;
  38        volatile unsigned char *fvr_r;
  39        unsigned char fcr;
  40} sun3x_fdc;
  41
  42/* Super paranoid... */
  43#undef HAVE_DISABLE_HLT
  44
  45/* Routines unique to each controller type on a Sun. */
  46static unsigned char sun3x_82072_fd_inb(int port)
  47{
  48        static int once = 0;
  49//      udelay(5);
  50        switch(port & 7) {
  51        default:
  52                pr_crit("floppy: Asked to read unknown port %d\n", port);
  53                panic("floppy: Port bolixed.");
  54        case 4: /* FD_STATUS */
  55                return (*sun3x_fdc.status_r) & ~STATUS_DMA;
  56        case 5: /* FD_DATA */
  57                return (*sun3x_fdc.data_r);
  58        case 7: /* FD_DIR */
  59                /* ugly hack, I can't find a way to actually detect the disk */
  60                if(!once) {
  61                        once = 1;
  62                        return 0x80;
  63                }
  64                return 0;
  65        };
  66        panic("sun_82072_fd_inb: How did I get here?");
  67}
  68
  69static void sun3x_82072_fd_outb(unsigned char value, int port)
  70{
  71//      udelay(5);
  72        switch(port & 7) {
  73        default:
  74                pr_crit("floppy: Asked to write to unknown port %d\n", port);
  75                panic("floppy: Port bolixed.");
  76        case 2: /* FD_DOR */
  77                /* Oh geese, 82072 on the Sun has no DOR register,
  78                 * so we make do with taunting the FCR.
  79                 *
  80                 * ASSUMPTIONS:  There will only ever be one floppy
  81                 *               drive attached to a Sun controller
  82                 *               and it will be at drive zero.
  83                 */
  84
  85        {
  86                unsigned char fcr = sun3x_fdc.fcr;
  87
  88                if(value & 0x10) {
  89                        fcr |= (FCR_DSEL0 | FCR_MTRON);
  90                } else
  91                        fcr &= ~(FCR_DSEL0 | FCR_MTRON);
  92
  93
  94                if(fcr != sun3x_fdc.fcr) {
  95                        *(sun3x_fdc.fcr_r) = fcr;
  96                        sun3x_fdc.fcr = fcr;
  97                }
  98        }
  99                break;
 100        case 5: /* FD_DATA */
 101                *(sun3x_fdc.data_r) = value;
 102                break;
 103        case 7: /* FD_DCR */
 104                *(sun3x_fdc.status_r) = value;
 105                break;
 106        case 4: /* FD_STATUS */
 107                *(sun3x_fdc.status_r) = value;
 108                break;
 109        }
 110        return;
 111}
 112
 113
 114asmlinkage irqreturn_t sun3xflop_hardint(int irq, void *dev_id)
 115{
 116        register unsigned char st;
 117
 118#undef TRACE_FLPY_INT
 119#define NO_FLOPPY_ASSEMBLER
 120
 121#ifdef TRACE_FLPY_INT
 122        static int calls=0;
 123        static int bytes=0;
 124        static int dma_wait=0;
 125#endif
 126        if(!doing_pdma) {
 127                floppy_interrupt(irq, dev_id);
 128                return IRQ_HANDLED;
 129        }
 130
 131//      pr_info("doing pdma\n");// st %x\n", sun_fdc->status_82072);
 132
 133#ifdef TRACE_FLPY_INT
 134        if(!calls)
 135                bytes = virtual_dma_count;
 136#endif
 137
 138        {
 139                register int lcount;
 140                register char *lptr;
 141
 142                for(lcount=virtual_dma_count, lptr=virtual_dma_addr;
 143                    lcount; lcount--, lptr++) {
 144/*                      st=fd_inb(virtual_dma_port+4) & 0x80 ;  */
 145                        st = *(sun3x_fdc.status_r);
 146/*                      if(st != 0xa0)                  */
 147/*                              break;                  */
 148
 149                        if((st & 0x80) == 0) {
 150                                virtual_dma_count = lcount;
 151                                virtual_dma_addr = lptr;
 152                                return IRQ_HANDLED;
 153                        }
 154
 155                        if((st & 0x20) == 0)
 156                                break;
 157
 158                        if(virtual_dma_mode)
 159/*                              fd_outb(*lptr, virtual_dma_port+5); */
 160                                *(sun3x_fdc.data_r) = *lptr;
 161                        else
 162/*                              *lptr = fd_inb(virtual_dma_port+5); */
 163                                *lptr = *(sun3x_fdc.data_r);
 164                }
 165
 166                virtual_dma_count = lcount;
 167                virtual_dma_addr = lptr;
 168/*              st = fd_inb(virtual_dma_port+4);   */
 169                st = *(sun3x_fdc.status_r);
 170        }
 171
 172#ifdef TRACE_FLPY_INT
 173        calls++;
 174#endif
 175//      pr_info("st=%02x\n", st);
 176        if(st == 0x20)
 177                return IRQ_HANDLED;
 178        if(!(st & 0x20)) {
 179                virtual_dma_residue += virtual_dma_count;
 180                virtual_dma_count=0;
 181                doing_pdma = 0;
 182
 183#ifdef TRACE_FLPY_INT
 184                pr_info("count=%x, residue=%x calls=%d bytes=%x dma_wait=%d\n",
 185                        virtual_dma_count, virtual_dma_residue, calls, bytes,
 186                        dma_wait);
 187                calls = 0;
 188                dma_wait=0;
 189#endif
 190
 191                floppy_interrupt(irq, dev_id);
 192                return IRQ_HANDLED;
 193        }
 194
 195
 196#ifdef TRACE_FLPY_INT
 197        if(!virtual_dma_count)
 198                dma_wait++;
 199#endif
 200        return IRQ_HANDLED;
 201}
 202
 203static int sun3xflop_request_irq(void)
 204{
 205        static int once = 0;
 206        int error;
 207
 208        if(!once) {
 209                once = 1;
 210                error = request_irq(FLOPPY_IRQ, sun3xflop_hardint,
 211                                    0, "floppy", NULL);
 212                return ((error == 0) ? 0 : -1);
 213        } else return 0;
 214}
 215
 216static void __init floppy_set_flags(int *ints,int param, int param2);
 217
 218static int sun3xflop_init(void)
 219{
 220        if(FLOPPY_IRQ < 0x40)
 221                FLOPPY_IRQ = SUN3X_FDC_IRQ;
 222
 223        sun3x_fdc.status_r = (volatile unsigned char *)SUN3X_FDC;
 224        sun3x_fdc.data_r  = (volatile unsigned char *)(SUN3X_FDC+1);
 225        sun3x_fdc.fcr_r = (volatile unsigned char *)SUN3X_FDC_FCR;
 226        sun3x_fdc.fvr_r = (volatile unsigned char *)SUN3X_FDC_FVR;
 227        sun3x_fdc.fcr = 0;
 228
 229        /* Last minute sanity check... */
 230        if(*sun3x_fdc.status_r == 0xff) {
 231                return -1;
 232        }
 233
 234        *sun3x_fdc.fvr_r = FLOPPY_IRQ;
 235
 236        *sun3x_fdc.fcr_r = FCR_TC;
 237        udelay(10);
 238        *sun3x_fdc.fcr_r = 0;
 239
 240        /* Success... */
 241        floppy_set_flags(NULL, 1, FD_BROKEN_DCL); // I don't know how to detect this.
 242        allowed_drive_mask = 0x01;
 243        return (int) SUN3X_FDC;
 244}
 245
 246/* I'm not precisely sure this eject routine works */
 247static int sun3x_eject(void)
 248{
 249        if(MACH_IS_SUN3X) {
 250
 251                sun3x_fdc.fcr |= (FCR_DSEL0 | FCR_EJECT);
 252                *(sun3x_fdc.fcr_r) = sun3x_fdc.fcr;
 253                udelay(10);
 254                sun3x_fdc.fcr &= ~(FCR_DSEL0 | FCR_EJECT);
 255                *(sun3x_fdc.fcr_r) = sun3x_fdc.fcr;
 256        }
 257
 258        return 0;
 259}
 260
 261#define fd_eject(drive) sun3x_eject()
 262
 263#endif /* !(__ASM_SUN3X_FLOPPY_H) */
 264