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