OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [include/] [asm-sparc64/] [floppy.h] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.