linux/arch/sparc/include/asm/floppy_64.h
<<
>>
Prefs
   1/* floppy.h: Sparc specific parts of the Floppy driver.
   2 *
   3 * Copyright (C) 1996, 2007, 2008 David S. Miller (davem@davemloft.net)
   4 * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
   5 *
   6 * Ultra/PCI support added: Sep 1997  Eddie C. Dost  (ecd@skynet.be)
   7 */
   8
   9#ifndef __ASM_SPARC64_FLOPPY_H
  10#define __ASM_SPARC64_FLOPPY_H
  11
  12#include <linux/of.h>
  13#include <linux/of_device.h>
  14#include <linux/dma-mapping.h>
  15
  16#include <asm/auxio.h>
  17
  18/*
  19 * Define this to enable exchanging drive 0 and 1 if only drive 1 is
  20 * probed on PCI machines.
  21 */
  22#undef PCI_FDC_SWAP_DRIVES
  23
  24
  25/* References:
  26 * 1) Netbsd Sun floppy driver.
  27 * 2) NCR 82077 controller manual
  28 * 3) Intel 82077 controller manual
  29 */
  30struct sun_flpy_controller {
  31        volatile unsigned char status1_82077; /* Auxiliary Status reg. 1 */
  32        volatile unsigned char status2_82077; /* Auxiliary Status reg. 2 */
  33        volatile unsigned char dor_82077;     /* Digital Output reg. */
  34        volatile unsigned char tapectl_82077; /* Tape Control reg */
  35        volatile unsigned char status_82077;  /* Main Status Register. */
  36#define drs_82077              status_82077   /* Digital Rate Select reg. */
  37        volatile unsigned char data_82077;    /* Data fifo. */
  38        volatile unsigned char ___unused;
  39        volatile unsigned char dir_82077;     /* Digital Input reg. */
  40#define dcr_82077              dir_82077      /* Config Control reg. */
  41};
  42
  43/* You'll only ever find one controller on an Ultra anyways. */
  44static struct sun_flpy_controller *sun_fdc = (struct sun_flpy_controller *)-1;
  45unsigned long fdc_status;
  46static struct of_device *floppy_op = NULL;
  47
  48struct sun_floppy_ops {
  49        unsigned char   (*fd_inb) (unsigned long port);
  50        void            (*fd_outb) (unsigned char value, unsigned long port);
  51        void            (*fd_enable_dma) (void);
  52        void            (*fd_disable_dma) (void);
  53        void            (*fd_set_dma_mode) (int);
  54        void            (*fd_set_dma_addr) (char *);
  55        void            (*fd_set_dma_count) (int);
  56        unsigned int    (*get_dma_residue) (void);
  57        int             (*fd_request_irq) (void);
  58        void            (*fd_free_irq) (void);
  59        int             (*fd_eject) (int);
  60};
  61
  62static struct sun_floppy_ops sun_fdops;
  63
  64#define fd_inb(port)              sun_fdops.fd_inb(port)
  65#define fd_outb(value,port)       sun_fdops.fd_outb(value,port)
  66#define fd_enable_dma()           sun_fdops.fd_enable_dma()
  67#define fd_disable_dma()          sun_fdops.fd_disable_dma()
  68#define fd_request_dma()          (0) /* nothing... */
  69#define fd_free_dma()             /* nothing... */
  70#define fd_clear_dma_ff()         /* nothing... */
  71#define fd_set_dma_mode(mode)     sun_fdops.fd_set_dma_mode(mode)
  72#define fd_set_dma_addr(addr)     sun_fdops.fd_set_dma_addr(addr)
  73#define fd_set_dma_count(count)   sun_fdops.fd_set_dma_count(count)
  74#define get_dma_residue(x)        sun_fdops.get_dma_residue()
  75#define fd_cacheflush(addr, size) /* nothing... */
  76#define fd_request_irq()          sun_fdops.fd_request_irq()
  77#define fd_free_irq()             sun_fdops.fd_free_irq()
  78#define fd_eject(drive)           sun_fdops.fd_eject(drive)
  79
  80/* Super paranoid... */
  81#undef HAVE_DISABLE_HLT
  82
  83static int sun_floppy_types[2] = { 0, 0 };
  84
  85/* Here is where we catch the floppy driver trying to initialize,
  86 * therefore this is where we call the PROM device tree probing
  87 * routine etc. on the Sparc.
  88 */
  89#define FLOPPY0_TYPE            sun_floppy_init()
  90#define FLOPPY1_TYPE            sun_floppy_types[1]
  91
  92#define FDC1                    ((unsigned long)sun_fdc)
  93
  94#define N_FDC    1
  95#define N_DRIVE  8
  96
  97/* No 64k boundary crossing problems on the Sparc. */
  98#define CROSS_64KB(a,s) (0)
  99
 100static unsigned char sun_82077_fd_inb(unsigned long port)
 101{
 102        udelay(5);
 103        switch(port & 7) {
 104        default:
 105                printk("floppy: Asked to read unknown port %lx\n", port);
 106                panic("floppy: Port bolixed.");
 107        case 4: /* FD_STATUS */
 108                return sbus_readb(&sun_fdc->status_82077) & ~STATUS_DMA;
 109        case 5: /* FD_DATA */
 110                return sbus_readb(&sun_fdc->data_82077);
 111        case 7: /* FD_DIR */
 112                /* XXX: Is DCL on 0x80 in sun4m? */
 113                return sbus_readb(&sun_fdc->dir_82077);
 114        };
 115        panic("sun_82072_fd_inb: How did I get here?");
 116}
 117
 118static void sun_82077_fd_outb(unsigned char value, unsigned long port)
 119{
 120        udelay(5);
 121        switch(port & 7) {
 122        default:
 123                printk("floppy: Asked to write to unknown port %lx\n", port);
 124                panic("floppy: Port bolixed.");
 125        case 2: /* FD_DOR */
 126                /* Happily, the 82077 has a real DOR register. */
 127                sbus_writeb(value, &sun_fdc->dor_82077);
 128                break;
 129        case 5: /* FD_DATA */
 130                sbus_writeb(value, &sun_fdc->data_82077);
 131                break;
 132        case 7: /* FD_DCR */
 133                sbus_writeb(value, &sun_fdc->dcr_82077);
 134                break;
 135        case 4: /* FD_STATUS */
 136                sbus_writeb(value, &sun_fdc->status_82077);
 137                break;
 138        };
 139        return;
 140}
 141
 142/* For pseudo-dma (Sun floppy drives have no real DMA available to
 143 * them so we must eat the data fifo bytes directly ourselves) we have
 144 * three state variables.  doing_pdma tells our inline low-level
 145 * assembly floppy interrupt entry point whether it should sit and eat
 146 * bytes from the fifo or just transfer control up to the higher level
 147 * floppy interrupt c-code.  I tried very hard but I could not get the
 148 * pseudo-dma to work in c-code without getting many overruns and
 149 * underruns.  If non-zero, doing_pdma encodes the direction of
 150 * the transfer for debugging.  1=read 2=write
 151 */
 152unsigned char *pdma_vaddr;
 153unsigned long pdma_size;
 154volatile int doing_pdma = 0;
 155
 156/* This is software state */
 157char *pdma_base = NULL;
 158unsigned long pdma_areasize;
 159
 160/* Common routines to all controller types on the Sparc. */
 161static void sun_fd_disable_dma(void)
 162{
 163        doing_pdma = 0;
 164        if (pdma_base) {
 165                mmu_unlockarea(pdma_base, pdma_areasize);
 166                pdma_base = NULL;
 167        }
 168}
 169
 170static void sun_fd_set_dma_mode(int mode)
 171{
 172        switch(mode) {
 173        case DMA_MODE_READ:
 174                doing_pdma = 1;
 175                break;
 176        case DMA_MODE_WRITE:
 177                doing_pdma = 2;
 178                break;
 179        default:
 180                printk("Unknown dma mode %d\n", mode);
 181                panic("floppy: Giving up...");
 182        }
 183}
 184
 185static void sun_fd_set_dma_addr(char *buffer)
 186{
 187        pdma_vaddr = buffer;
 188}
 189
 190static void sun_fd_set_dma_count(int length)
 191{
 192        pdma_size = length;
 193}
 194
 195static void sun_fd_enable_dma(void)
 196{
 197        pdma_vaddr = mmu_lockarea(pdma_vaddr, pdma_size);
 198        pdma_base = pdma_vaddr;
 199        pdma_areasize = pdma_size;
 200}
 201
 202irqreturn_t sparc_floppy_irq(int irq, void *dev_cookie)
 203{
 204        if (likely(doing_pdma)) {
 205                void __iomem *stat = (void __iomem *) fdc_status;
 206                unsigned char *vaddr = pdma_vaddr;
 207                unsigned long size = pdma_size;
 208                u8 val;
 209
 210                while (size) {
 211                        val = readb(stat);
 212                        if (unlikely(!(val & 0x80))) {
 213                                pdma_vaddr = vaddr;
 214                                pdma_size = size;
 215                                return IRQ_HANDLED;
 216                        }
 217                        if (unlikely(!(val & 0x20))) {
 218                                pdma_vaddr = vaddr;
 219                                pdma_size = size;
 220                                doing_pdma = 0;
 221                                goto main_interrupt;
 222                        }
 223                        if (val & 0x40) {
 224                                /* read */
 225                                *vaddr++ = readb(stat + 1);
 226                        } else {
 227                                unsigned char data = *vaddr++;
 228
 229                                /* write */
 230                                writeb(data, stat + 1);
 231                        }
 232                        size--;
 233                }
 234
 235                pdma_vaddr = vaddr;
 236                pdma_size = size;
 237
 238                /* Send Terminal Count pulse to floppy controller. */
 239                val = readb(auxio_register);
 240                val |= AUXIO_AUX1_FTCNT;
 241                writeb(val, auxio_register);
 242                val &= ~AUXIO_AUX1_FTCNT;
 243                writeb(val, auxio_register);
 244
 245                doing_pdma = 0;
 246        }
 247
 248main_interrupt:
 249        return floppy_interrupt(irq, dev_cookie);
 250}
 251
 252static int sun_fd_request_irq(void)
 253{
 254        static int once = 0;
 255        int error;
 256
 257        if(!once) {
 258                once = 1;
 259
 260                error = request_irq(FLOPPY_IRQ, sparc_floppy_irq,
 261                                    IRQF_DISABLED, "floppy", NULL);
 262
 263                return ((error == 0) ? 0 : -1);
 264        }
 265        return 0;
 266}
 267
 268static void sun_fd_free_irq(void)
 269{
 270}
 271
 272static unsigned int sun_get_dma_residue(void)
 273{
 274        /* XXX This isn't really correct. XXX */
 275        return 0;
 276}
 277
 278static int sun_fd_eject(int drive)
 279{
 280        set_dor(0x00, 0xff, 0x90);
 281        udelay(500);
 282        set_dor(0x00, 0x6f, 0x00);
 283        udelay(500);
 284        return 0;
 285}
 286
 287#include <asm/ebus_dma.h>
 288#include <asm/ns87303.h>
 289
 290static struct ebus_dma_info sun_pci_fd_ebus_dma;
 291static struct device *sun_floppy_dev;
 292static int sun_pci_broken_drive = -1;
 293
 294struct sun_pci_dma_op {
 295        unsigned int    addr;
 296        int             len;
 297        int             direction;
 298        char            *buf;
 299};
 300static struct sun_pci_dma_op sun_pci_dma_current = { -1U, 0, 0, NULL};
 301static struct sun_pci_dma_op sun_pci_dma_pending = { -1U, 0, 0, NULL};
 302
 303extern irqreturn_t floppy_interrupt(int irq, void *dev_id);
 304
 305static unsigned char sun_pci_fd_inb(unsigned long port)
 306{
 307        udelay(5);
 308        return inb(port);
 309}
 310
 311static void sun_pci_fd_outb(unsigned char val, unsigned long port)
 312{
 313        udelay(5);
 314        outb(val, port);
 315}
 316
 317static void sun_pci_fd_broken_outb(unsigned char val, unsigned long port)
 318{
 319        udelay(5);
 320        /*
 321         * XXX: Due to SUN's broken floppy connector on AX and AXi
 322         *      we need to turn on MOTOR_0 also, if the floppy is
 323         *      jumpered to DS1 (like most PC floppies are). I hope
 324         *      this does not hurt correct hardware like the AXmp.
 325         *      (Eddie, Sep 12 1998).
 326         */
 327        if (port == ((unsigned long)sun_fdc) + 2) {
 328                if (((val & 0x03) == sun_pci_broken_drive) && (val & 0x20)) {
 329                        val |= 0x10;
 330                }
 331        }
 332        outb(val, port);
 333}
 334
 335#ifdef PCI_FDC_SWAP_DRIVES
 336static void sun_pci_fd_lde_broken_outb(unsigned char val, unsigned long port)
 337{
 338        udelay(5);
 339        /*
 340         * XXX: Due to SUN's broken floppy connector on AX and AXi
 341         *      we need to turn on MOTOR_0 also, if the floppy is
 342         *      jumpered to DS1 (like most PC floppies are). I hope
 343         *      this does not hurt correct hardware like the AXmp.
 344         *      (Eddie, Sep 12 1998).
 345         */
 346        if (port == ((unsigned long)sun_fdc) + 2) {
 347                if (((val & 0x03) == sun_pci_broken_drive) && (val & 0x10)) {
 348                        val &= ~(0x03);
 349                        val |= 0x21;
 350                }
 351        }
 352        outb(val, port);
 353}
 354#endif /* PCI_FDC_SWAP_DRIVES */
 355
 356static void sun_pci_fd_enable_dma(void)
 357{
 358        BUG_ON((NULL == sun_pci_dma_pending.buf)        ||
 359            (0    == sun_pci_dma_pending.len)   ||
 360            (0    == sun_pci_dma_pending.direction));
 361
 362        sun_pci_dma_current.buf = sun_pci_dma_pending.buf;
 363        sun_pci_dma_current.len = sun_pci_dma_pending.len;
 364        sun_pci_dma_current.direction = sun_pci_dma_pending.direction;
 365
 366        sun_pci_dma_pending.buf  = NULL;
 367        sun_pci_dma_pending.len  = 0;
 368        sun_pci_dma_pending.direction = 0;
 369        sun_pci_dma_pending.addr = -1U;
 370
 371        sun_pci_dma_current.addr =
 372                dma_map_single(sun_floppy_dev,
 373                               sun_pci_dma_current.buf,
 374                               sun_pci_dma_current.len,
 375                               sun_pci_dma_current.direction);
 376
 377        ebus_dma_enable(&sun_pci_fd_ebus_dma, 1);
 378
 379        if (ebus_dma_request(&sun_pci_fd_ebus_dma,
 380                             sun_pci_dma_current.addr,
 381                             sun_pci_dma_current.len))
 382                BUG();
 383}
 384
 385static void sun_pci_fd_disable_dma(void)
 386{
 387        ebus_dma_enable(&sun_pci_fd_ebus_dma, 0);
 388        if (sun_pci_dma_current.addr != -1U)
 389                dma_unmap_single(sun_floppy_dev,
 390                                 sun_pci_dma_current.addr,
 391                                 sun_pci_dma_current.len,
 392                                 sun_pci_dma_current.direction);
 393        sun_pci_dma_current.addr = -1U;
 394}
 395
 396static void sun_pci_fd_set_dma_mode(int mode)
 397{
 398        if (mode == DMA_MODE_WRITE)
 399                sun_pci_dma_pending.direction = DMA_TO_DEVICE;
 400        else
 401                sun_pci_dma_pending.direction = DMA_FROM_DEVICE;
 402
 403        ebus_dma_prepare(&sun_pci_fd_ebus_dma, mode != DMA_MODE_WRITE);
 404}
 405
 406static void sun_pci_fd_set_dma_count(int length)
 407{
 408        sun_pci_dma_pending.len = length;
 409}
 410
 411static void sun_pci_fd_set_dma_addr(char *buffer)
 412{
 413        sun_pci_dma_pending.buf = buffer;
 414}
 415
 416static unsigned int sun_pci_get_dma_residue(void)
 417{
 418        return ebus_dma_residue(&sun_pci_fd_ebus_dma);
 419}
 420
 421static int sun_pci_fd_request_irq(void)
 422{
 423        return ebus_dma_irq_enable(&sun_pci_fd_ebus_dma, 1);
 424}
 425
 426static void sun_pci_fd_free_irq(void)
 427{
 428        ebus_dma_irq_enable(&sun_pci_fd_ebus_dma, 0);
 429}
 430
 431static int sun_pci_fd_eject(int drive)
 432{
 433        return -EINVAL;
 434}
 435
 436void sun_pci_fd_dma_callback(struct ebus_dma_info *p, int event, void *cookie)
 437{
 438        floppy_interrupt(0, NULL);
 439}
 440
 441/*
 442 * Floppy probing, we'd like to use /dev/fd0 for a single Floppy on PCI,
 443 * even if this is configured using DS1, thus looks like /dev/fd1 with
 444 * the cabling used in Ultras.
 445 */
 446#define DOR     (port + 2)
 447#define MSR     (port + 4)
 448#define FIFO    (port + 5)
 449
 450static void sun_pci_fd_out_byte(unsigned long port, unsigned char val,
 451                                unsigned long reg)
 452{
 453        unsigned char status;
 454        int timeout = 1000;
 455
 456        while (!((status = inb(MSR)) & 0x80) && --timeout)
 457                udelay(100);
 458        outb(val, reg);
 459}
 460
 461static unsigned char sun_pci_fd_sensei(unsigned long port)
 462{
 463        unsigned char result[2] = { 0x70, 0x00 };
 464        unsigned char status;
 465        int i = 0;
 466
 467        sun_pci_fd_out_byte(port, 0x08, FIFO);
 468        do {
 469                int timeout = 1000;
 470
 471                while (!((status = inb(MSR)) & 0x80) && --timeout)
 472                        udelay(100);
 473
 474                if (!timeout)
 475                        break;
 476
 477                if ((status & 0xf0) == 0xd0)
 478                        result[i++] = inb(FIFO);
 479                else
 480                        break;
 481        } while (i < 2);
 482
 483        return result[0];
 484}
 485
 486static void sun_pci_fd_reset(unsigned long port)
 487{
 488        unsigned char mask = 0x00;
 489        unsigned char status;
 490        int timeout = 10000;
 491
 492        outb(0x80, MSR);
 493        do {
 494                status = sun_pci_fd_sensei(port);
 495                if ((status & 0xc0) == 0xc0)
 496                        mask |= 1 << (status & 0x03);
 497                else
 498                        udelay(100);
 499        } while ((mask != 0x0f) && --timeout);
 500}
 501
 502static int sun_pci_fd_test_drive(unsigned long port, int drive)
 503{
 504        unsigned char status, data;
 505        int timeout = 1000;
 506        int ready;
 507
 508        sun_pci_fd_reset(port);
 509
 510        data = (0x10 << drive) | 0x0c | drive;
 511        sun_pci_fd_out_byte(port, data, DOR);
 512
 513        sun_pci_fd_out_byte(port, 0x07, FIFO);
 514        sun_pci_fd_out_byte(port, drive & 0x03, FIFO);
 515
 516        do {
 517                udelay(100);
 518                status = sun_pci_fd_sensei(port);
 519        } while (((status & 0xc0) == 0x80) && --timeout);
 520
 521        if (!timeout)
 522                ready = 0;
 523        else
 524                ready = (status & 0x10) ? 0 : 1;
 525
 526        sun_pci_fd_reset(port);
 527        return ready;
 528}
 529#undef FIFO
 530#undef MSR
 531#undef DOR
 532
 533static int __init ebus_fdthree_p(struct device_node *dp)
 534{
 535        if (!strcmp(dp->name, "fdthree"))
 536                return 1;
 537        if (!strcmp(dp->name, "floppy")) {
 538                const char *compat;
 539
 540                compat = of_get_property(dp, "compatible", NULL);
 541                if (compat && !strcmp(compat, "fdthree"))
 542                        return 1;
 543        }
 544        return 0;
 545}
 546
 547static unsigned long __init sun_floppy_init(void)
 548{
 549        static int initialized = 0;
 550        struct device_node *dp;
 551        struct of_device *op;
 552        const char *prop;
 553        char state[128];
 554
 555        if (initialized)
 556                return sun_floppy_types[0];
 557        initialized = 1;
 558
 559        op = NULL;
 560
 561        for_each_node_by_name(dp, "SUNW,fdtwo") {
 562                if (strcmp(dp->parent->name, "sbus"))
 563                        continue;
 564                op = of_find_device_by_node(dp);
 565                if (op)
 566                        break;
 567        }
 568        if (op) {
 569                floppy_op = op;
 570                FLOPPY_IRQ = op->irqs[0];
 571        } else {
 572                struct device_node *ebus_dp;
 573                void __iomem *auxio_reg;
 574                const char *state_prop;
 575                unsigned long config;
 576
 577                dp = NULL;
 578                for_each_node_by_name(ebus_dp, "ebus") {
 579                        for (dp = ebus_dp->child; dp; dp = dp->sibling) {
 580                                if (ebus_fdthree_p(dp))
 581                                        goto found_fdthree;
 582                        }
 583                }
 584        found_fdthree:
 585                if (!dp)
 586                        return 0;
 587
 588                op = of_find_device_by_node(dp);
 589                if (!op)
 590                        return 0;
 591
 592                state_prop = of_get_property(op->node, "status", NULL);
 593                if (state_prop && !strncmp(state_prop, "disabled", 8))
 594                        return 0;
 595
 596                FLOPPY_IRQ = op->irqs[0];
 597
 598                /* Make sure the high density bit is set, some systems
 599                 * (most notably Ultra5/Ultra10) come up with it clear.
 600                 */
 601                auxio_reg = (void __iomem *) op->resource[2].start;
 602                writel(readl(auxio_reg)|0x2, auxio_reg);
 603
 604                sun_floppy_dev = &op->dev;
 605
 606                spin_lock_init(&sun_pci_fd_ebus_dma.lock);
 607
 608                /* XXX ioremap */
 609                sun_pci_fd_ebus_dma.regs = (void __iomem *)
 610                        op->resource[1].start;
 611                if (!sun_pci_fd_ebus_dma.regs)
 612                        return 0;
 613
 614                sun_pci_fd_ebus_dma.flags = (EBUS_DMA_FLAG_USE_EBDMA_HANDLER |
 615                                             EBUS_DMA_FLAG_TCI_DISABLE);
 616                sun_pci_fd_ebus_dma.callback = sun_pci_fd_dma_callback;
 617                sun_pci_fd_ebus_dma.client_cookie = NULL;
 618                sun_pci_fd_ebus_dma.irq = FLOPPY_IRQ;
 619                strcpy(sun_pci_fd_ebus_dma.name, "floppy");
 620                if (ebus_dma_register(&sun_pci_fd_ebus_dma))
 621                        return 0;
 622
 623                /* XXX ioremap */
 624                sun_fdc = (struct sun_flpy_controller *) op->resource[0].start;
 625
 626                sun_fdops.fd_inb = sun_pci_fd_inb;
 627                sun_fdops.fd_outb = sun_pci_fd_outb;
 628
 629                can_use_virtual_dma = use_virtual_dma = 0;
 630                sun_fdops.fd_enable_dma = sun_pci_fd_enable_dma;
 631                sun_fdops.fd_disable_dma = sun_pci_fd_disable_dma;
 632                sun_fdops.fd_set_dma_mode = sun_pci_fd_set_dma_mode;
 633                sun_fdops.fd_set_dma_addr = sun_pci_fd_set_dma_addr;
 634                sun_fdops.fd_set_dma_count = sun_pci_fd_set_dma_count;
 635                sun_fdops.get_dma_residue = sun_pci_get_dma_residue;
 636
 637                sun_fdops.fd_request_irq = sun_pci_fd_request_irq;
 638                sun_fdops.fd_free_irq = sun_pci_fd_free_irq;
 639
 640                sun_fdops.fd_eject = sun_pci_fd_eject;
 641
 642                fdc_status = (unsigned long) &sun_fdc->status_82077;
 643
 644                /*
 645                 * XXX: Find out on which machines this is really needed.
 646                 */
 647                if (1) {
 648                        sun_pci_broken_drive = 1;
 649                        sun_fdops.fd_outb = sun_pci_fd_broken_outb;
 650                }
 651
 652                allowed_drive_mask = 0;
 653                if (sun_pci_fd_test_drive((unsigned long)sun_fdc, 0))
 654                        sun_floppy_types[0] = 4;
 655                if (sun_pci_fd_test_drive((unsigned long)sun_fdc, 1))
 656                        sun_floppy_types[1] = 4;
 657
 658                /*
 659                 * Find NS87303 SuperIO config registers (through ecpp).
 660                 */
 661                config = 0;
 662                for (dp = ebus_dp->child; dp; dp = dp->sibling) {
 663                        if (!strcmp(dp->name, "ecpp")) {
 664                                struct of_device *ecpp_op;
 665
 666                                ecpp_op = of_find_device_by_node(dp);
 667                                if (ecpp_op)
 668                                        config = ecpp_op->resource[1].start;
 669                                goto config_done;
 670                        }
 671                }
 672        config_done:
 673
 674                /*
 675                 * Sanity check, is this really the NS87303?
 676                 */
 677                switch (config & 0x3ff) {
 678                case 0x02e:
 679                case 0x15c:
 680                case 0x26e:
 681                case 0x398:
 682                        break;
 683                default:
 684                        config = 0;
 685                }
 686
 687                if (!config)
 688                        return sun_floppy_types[0];
 689
 690                /* Enable PC-AT mode. */
 691                ns87303_modify(config, ASC, 0, 0xc0);
 692
 693#ifdef PCI_FDC_SWAP_DRIVES
 694                /*
 695                 * If only Floppy 1 is present, swap drives.
 696                 */
 697                if (!sun_floppy_types[0] && sun_floppy_types[1]) {
 698                        /*
 699                         * Set the drive exchange bit in FCR on NS87303,
 700                         * make sure other bits are sane before doing so.
 701                         */
 702                        ns87303_modify(config, FER, FER_EDM, 0);
 703                        ns87303_modify(config, ASC, ASC_DRV2_SEL, 0);
 704                        ns87303_modify(config, FCR, 0, FCR_LDE);
 705
 706                        config = sun_floppy_types[0];
 707                        sun_floppy_types[0] = sun_floppy_types[1];
 708                        sun_floppy_types[1] = config;
 709
 710                        if (sun_pci_broken_drive != -1) {
 711                                sun_pci_broken_drive = 1 - sun_pci_broken_drive;
 712                                sun_fdops.fd_outb = sun_pci_fd_lde_broken_outb;
 713                        }
 714                }
 715#endif /* PCI_FDC_SWAP_DRIVES */
 716
 717                return sun_floppy_types[0];
 718        }
 719        prop = of_get_property(op->node, "status", NULL);
 720        if (prop && !strncmp(state, "disabled", 8))
 721                return 0;
 722
 723        /*
 724         * We cannot do of_ioremap here: it does request_region,
 725         * which the generic floppy driver tries to do once again.
 726         * But we must use the sdev resource values as they have
 727         * had parent ranges applied.
 728         */
 729        sun_fdc = (struct sun_flpy_controller *)
 730                (op->resource[0].start +
 731                 ((op->resource[0].flags & 0x1ffUL) << 32UL));
 732
 733        /* Last minute sanity check... */
 734        if (sbus_readb(&sun_fdc->status1_82077) == 0xff) {
 735                sun_fdc = (struct sun_flpy_controller *)-1;
 736                return 0;
 737        }
 738
 739        sun_fdops.fd_inb = sun_82077_fd_inb;
 740        sun_fdops.fd_outb = sun_82077_fd_outb;
 741
 742        can_use_virtual_dma = use_virtual_dma = 1;
 743        sun_fdops.fd_enable_dma = sun_fd_enable_dma;
 744        sun_fdops.fd_disable_dma = sun_fd_disable_dma;
 745        sun_fdops.fd_set_dma_mode = sun_fd_set_dma_mode;
 746        sun_fdops.fd_set_dma_addr = sun_fd_set_dma_addr;
 747        sun_fdops.fd_set_dma_count = sun_fd_set_dma_count;
 748        sun_fdops.get_dma_residue = sun_get_dma_residue;
 749
 750        sun_fdops.fd_request_irq = sun_fd_request_irq;
 751        sun_fdops.fd_free_irq = sun_fd_free_irq;
 752
 753        sun_fdops.fd_eject = sun_fd_eject;
 754
 755        fdc_status = (unsigned long) &sun_fdc->status_82077;
 756
 757        /* Success... */
 758        allowed_drive_mask = 0x01;
 759        sun_floppy_types[0] = 4;
 760        sun_floppy_types[1] = 0;
 761
 762        return sun_floppy_types[0];
 763}
 764
 765#define EXTRA_FLOPPY_PARAMS
 766
 767static DEFINE_SPINLOCK(dma_spin_lock);
 768
 769#define claim_dma_lock() \
 770({      unsigned long flags; \
 771        spin_lock_irqsave(&dma_spin_lock, flags); \
 772        flags; \
 773})
 774
 775#define release_dma_lock(__flags) \
 776        spin_unlock_irqrestore(&dma_spin_lock, __flags);
 777
 778#endif /* !(__ASM_SPARC64_FLOPPY_H) */
 779