gayle.c 4.4 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
2
 *  Amiga Gayle IDE Driver
L
Linus Torvalds 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 *     Created 9 Jul 1997 by Geert Uytterhoeven
 *
 *  This file is subject to the terms and conditions of the GNU General Public
 *  License.  See the file COPYING in the main directory of this archive for
 *  more details.
 */

#include <linux/types.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/blkdev.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/zorro.h>
A
Adrian Bunk 已提交
18
#include <linux/module.h>
L
Linus Torvalds 已提交
19 20 21 22 23 24 25 26 27 28 29 30 31 32

#include <asm/setup.h>
#include <asm/amigahw.h>
#include <asm/amigaints.h>
#include <asm/amigayle.h>


    /*
     *  Bases of the IDE interfaces
     */

#define GAYLE_BASE_4000	0xdd2020	/* A4000/A4000T */
#define GAYLE_BASE_1200	0xda0000	/* A1200/A600 and E-Matrix 530 */

33 34
#define GAYLE_IDEREG_SIZE	0x2000

L
Linus Torvalds 已提交
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
    /*
     *  Offsets from one of the above bases
     */

#define GAYLE_CONTROL	0x101a

    /*
     *  These are at different offsets from the base
     */

#define GAYLE_IRQ_4000	0xdd3020	/* MSB = 1, Harddisk is source of */
#define GAYLE_IRQ_1200	0xda9000	/* interrupt */


    /*
     *  Offset of the secondary port for IDE doublers
     *  Note that GAYLE_CONTROL is NOT available then!
     */

#define GAYLE_NEXT_PORT	0x1000

#ifndef CONFIG_BLK_DEV_IDEDOUBLER
#define GAYLE_NUM_HWIFS		1
#define GAYLE_NUM_PROBE_HWIFS	GAYLE_NUM_HWIFS
#define GAYLE_HAS_CONTROL_REG	1
#else /* CONFIG_BLK_DEV_IDEDOUBLER */
#define GAYLE_NUM_HWIFS		2
#define GAYLE_NUM_PROBE_HWIFS	(ide_doubler ? GAYLE_NUM_HWIFS : \
					       GAYLE_NUM_HWIFS-1)
#define GAYLE_HAS_CONTROL_REG	(!ide_doubler)
A
Adrian Bunk 已提交
65

66
static int ide_doubler;
67 68
module_param_named(doubler, ide_doubler, bool, 0);
MODULE_PARM_DESC(doubler, "enable support for IDE doublers");
L
Linus Torvalds 已提交
69 70 71 72 73 74 75 76 77 78 79
#endif /* CONFIG_BLK_DEV_IDEDOUBLER */


    /*
     *  Check and acknowledge the interrupt status
     */

static int gayle_ack_intr_a4000(ide_hwif_t *hwif)
{
    unsigned char ch;

80
    ch = z_readb(hwif->io_ports.irq_addr);
L
Linus Torvalds 已提交
81 82 83 84 85 86 87 88 89
    if (!(ch & GAYLE_IRQ_IDE))
	return 0;
    return 1;
}

static int gayle_ack_intr_a1200(ide_hwif_t *hwif)
{
    unsigned char ch;

90
    ch = z_readb(hwif->io_ports.irq_addr);
L
Linus Torvalds 已提交
91 92
    if (!(ch & GAYLE_IRQ_IDE))
	return 0;
93 94
    (void)z_readb(hwif->io_ports.status_addr);
    z_writeb(0x7c, hwif->io_ports.irq_addr);
L
Linus Torvalds 已提交
95 96 97
    return 1;
}

98 99
static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base,
				     unsigned long ctl, unsigned long irq_port,
100
				     ide_ack_intr_t *ack_intr)
101 102 103 104 105
{
	int i;

	memset(hw, 0, sizeof(*hw));

106
	hw->io_ports.data_addr = base;
107 108

	for (i = 1; i < 8; i++)
109
		hw->io_ports_array[i] = base + 2 + i * 4;
110

111 112
	hw->io_ports.ctl_addr = ctl;
	hw->io_ports.irq_addr = irq_port;
113 114 115

	hw->irq = IRQ_AMIGA_PORTS;
	hw->ack_intr = ack_intr;
116 117

	hw->chipset = ide_generic;
118 119
}

L
Linus Torvalds 已提交
120 121 122 123
    /*
     *  Probe for a Gayle IDE interface (and optionally for an IDE doubler)
     */

124
static int __init gayle_init(void)
L
Linus Torvalds 已提交
125
{
126 127 128
    unsigned long phys_base, res_start, res_n;
    unsigned long base, ctrlport, irqport;
    ide_ack_intr_t *ack_intr;
129
    int a4000, i, rc;
130
    hw_regs_t hw[GAYLE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
L
Linus Torvalds 已提交
131 132

    if (!MACH_IS_AMIGA)
133
	return -ENODEV;
L
Linus Torvalds 已提交
134 135 136 137 138 139 140 141 142

    if ((a4000 = AMIGAHW_PRESENT(A4000_IDE)) || AMIGAHW_PRESENT(A1200_IDE))
	goto found;

#ifdef CONFIG_ZORRO
    if (zorro_find_device(ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE,
			  NULL))
	goto found;
#endif
143
    return -ENODEV;
L
Linus Torvalds 已提交
144 145

found:
146 147 148 149 150 151 152
	printk(KERN_INFO "ide: Gayle IDE controller (A%d style%s)\n",
			 a4000 ? 4000 : 1200,
#ifdef CONFIG_BLK_DEV_IDEDOUBLER
			 ide_doubler ? ", IDE doubler" :
#endif
			 "");

L
Linus Torvalds 已提交
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
	if (a4000) {
	    phys_base = GAYLE_BASE_4000;
	    irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_4000);
	    ack_intr = gayle_ack_intr_a4000;
	} else {
	    phys_base = GAYLE_BASE_1200;
	    irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_1200);
	    ack_intr = gayle_ack_intr_a1200;
	}
/*
 * FIXME: we now have selectable modes between mmio v/s iomio
 */

	res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1);
	res_n = GAYLE_IDEREG_SIZE;

	if (!request_mem_region(res_start, res_n, "IDE"))
170
		return -EBUSY;
L
Linus Torvalds 已提交
171

172 173
    for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
	base = (unsigned long)ZTWO_VADDR(phys_base + i * GAYLE_NEXT_PORT);
L
Linus Torvalds 已提交
174 175
	ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0;

176
	gayle_setup_ports(&hw[i], base, ctrlport, irqport, ack_intr);
L
Linus Torvalds 已提交
177

178
	hws[i] = &hw[i];
L
Linus Torvalds 已提交
179
    }
180

181 182 183 184 185
    rc = ide_host_add(NULL, hws, NULL);
    if (rc)
	release_mem_region(res_start, res_n);

    return rc;
L
Linus Torvalds 已提交
186
}
187 188

module_init(gayle_init);
189 190

MODULE_LICENSE("GPL");