linux/drivers/ide/legacy/gayle.c
<<
>>
Prefs
   1/*
   2 *  linux/drivers/ide/legacy/gayle.c -- Amiga Gayle IDE Driver
   3 *
   4 *     Created 9 Jul 1997 by Geert Uytterhoeven
   5 *
   6 *  This file is subject to the terms and conditions of the GNU General Public
   7 *  License.  See the file COPYING in the main directory of this archive for
   8 *  more details.
   9 */
  10
  11#include <linux/types.h>
  12#include <linux/mm.h>
  13#include <linux/interrupt.h>
  14#include <linux/blkdev.h>
  15#include <linux/hdreg.h>
  16#include <linux/ide.h>
  17#include <linux/init.h>
  18#include <linux/zorro.h>
  19
  20#include <asm/setup.h>
  21#include <asm/amigahw.h>
  22#include <asm/amigaints.h>
  23#include <asm/amigayle.h>
  24
  25
  26    /*
  27     *  Bases of the IDE interfaces
  28     */
  29
  30#define GAYLE_BASE_4000 0xdd2020        /* A4000/A4000T */
  31#define GAYLE_BASE_1200 0xda0000        /* A1200/A600 and E-Matrix 530 */
  32
  33    /*
  34     *  Offsets from one of the above bases
  35     */
  36
  37#define GAYLE_DATA      0x00
  38#define GAYLE_ERROR     0x06            /* see err-bits */
  39#define GAYLE_NSECTOR   0x0a            /* nr of sectors to read/write */
  40#define GAYLE_SECTOR    0x0e            /* starting sector */
  41#define GAYLE_LCYL      0x12            /* starting cylinder */
  42#define GAYLE_HCYL      0x16            /* high byte of starting cyl */
  43#define GAYLE_SELECT    0x1a            /* 101dhhhh , d=drive, hhhh=head */
  44#define GAYLE_STATUS    0x1e            /* see status-bits */
  45#define GAYLE_CONTROL   0x101a
  46
  47static int gayle_offsets[IDE_NR_PORTS] __initdata = {
  48    GAYLE_DATA, GAYLE_ERROR, GAYLE_NSECTOR, GAYLE_SECTOR, GAYLE_LCYL,
  49    GAYLE_HCYL, GAYLE_SELECT, GAYLE_STATUS, -1, -1
  50};
  51
  52
  53    /*
  54     *  These are at different offsets from the base
  55     */
  56
  57#define GAYLE_IRQ_4000  0xdd3020        /* MSB = 1, Harddisk is source of */
  58#define GAYLE_IRQ_1200  0xda9000        /* interrupt */
  59
  60
  61    /*
  62     *  Offset of the secondary port for IDE doublers
  63     *  Note that GAYLE_CONTROL is NOT available then!
  64     */
  65
  66#define GAYLE_NEXT_PORT 0x1000
  67
  68#ifndef CONFIG_BLK_DEV_IDEDOUBLER
  69#define GAYLE_NUM_HWIFS         1
  70#define GAYLE_NUM_PROBE_HWIFS   GAYLE_NUM_HWIFS
  71#define GAYLE_HAS_CONTROL_REG   1
  72#define GAYLE_IDEREG_SIZE       0x2000
  73#else /* CONFIG_BLK_DEV_IDEDOUBLER */
  74#define GAYLE_NUM_HWIFS         2
  75#define GAYLE_NUM_PROBE_HWIFS   (ide_doubler ? GAYLE_NUM_HWIFS : \
  76                                               GAYLE_NUM_HWIFS-1)
  77#define GAYLE_HAS_CONTROL_REG   (!ide_doubler)
  78#define GAYLE_IDEREG_SIZE       (ide_doubler ? 0x1000 : 0x2000)
  79int ide_doubler = 0;    /* support IDE doublers? */
  80#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
  81
  82
  83    /*
  84     *  Check and acknowledge the interrupt status
  85     */
  86
  87static int gayle_ack_intr_a4000(ide_hwif_t *hwif)
  88{
  89    unsigned char ch;
  90
  91    ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]);
  92    if (!(ch & GAYLE_IRQ_IDE))
  93        return 0;
  94    return 1;
  95}
  96
  97static int gayle_ack_intr_a1200(ide_hwif_t *hwif)
  98{
  99    unsigned char ch;
 100
 101    ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]);
 102    if (!(ch & GAYLE_IRQ_IDE))
 103        return 0;
 104    (void)z_readb(hwif->io_ports[IDE_STATUS_OFFSET]);
 105    z_writeb(0x7c, hwif->io_ports[IDE_IRQ_OFFSET]);
 106    return 1;
 107}
 108
 109    /*
 110     *  Probe for a Gayle IDE interface (and optionally for an IDE doubler)
 111     */
 112
 113void __init gayle_init(void)
 114{
 115    int a4000, i;
 116
 117    if (!MACH_IS_AMIGA)
 118        return;
 119
 120    if ((a4000 = AMIGAHW_PRESENT(A4000_IDE)) || AMIGAHW_PRESENT(A1200_IDE))
 121        goto found;
 122
 123#ifdef CONFIG_ZORRO
 124    if (zorro_find_device(ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE,
 125                          NULL))
 126        goto found;
 127#endif
 128    return;
 129
 130found:
 131    for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
 132        unsigned long base, ctrlport, irqport;
 133        ide_ack_intr_t *ack_intr;
 134        hw_regs_t hw;
 135        ide_hwif_t *hwif;
 136        int index;
 137        unsigned long phys_base, res_start, res_n;
 138
 139        if (a4000) {
 140            phys_base = GAYLE_BASE_4000;
 141            irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_4000);
 142            ack_intr = gayle_ack_intr_a4000;
 143        } else {
 144            phys_base = GAYLE_BASE_1200;
 145            irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_1200);
 146            ack_intr = gayle_ack_intr_a1200;
 147        }
 148/*
 149 * FIXME: we now have selectable modes between mmio v/s iomio
 150 */
 151
 152        phys_base += i*GAYLE_NEXT_PORT;
 153
 154        res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1);
 155        res_n = GAYLE_IDEREG_SIZE;
 156
 157        if (!request_mem_region(res_start, res_n, "IDE"))
 158            continue;
 159
 160        base = (unsigned long)ZTWO_VADDR(phys_base);
 161        ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0;
 162
 163        ide_setup_ports(&hw, base, gayle_offsets,
 164                        ctrlport, irqport, ack_intr,
 165//                      &gayle_iops,
 166                        IRQ_AMIGA_PORTS);
 167
 168        index = ide_register_hw(&hw, NULL, 1, &hwif);
 169        if (index != -1) {
 170            hwif->mmio = 1;
 171            switch (i) {
 172                case 0:
 173                    printk("ide%d: Gayle IDE interface (A%d style)\n", index,
 174                           a4000 ? 4000 : 1200);
 175                    break;
 176#ifdef CONFIG_BLK_DEV_IDEDOUBLER
 177                case 1:
 178                    printk("ide%d: IDE doubler\n", index);
 179                    break;
 180#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
 181            }
 182        } else
 183            release_mem_region(res_start, res_n);
 184    }
 185}
 186
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.