1/* 2 * linux/drivers/ide/legacy/buddha.c -- Amiga Buddha, Catweasel and X-Surf IDE Driver 3 * 4 * Copyright (C) 1997, 2001 by Geert Uytterhoeven and others 5 * 6 * This driver was written based on the specifications in README.buddha and 7 * the X-Surf info from Inside_XSurf.txt available at 8 * http://www.jschoenfeld.com 9 * 10 * This file is subject to the terms and conditions of the GNU General Public 11 * License. See the file COPYING in the main directory of this archive for 12 * more details. 13 * 14 * TODO: 15 * - test it :-) 16 * - tune the timings using the speed-register 17 */ 18 19#include <linux/types.h> 20#include <linux/mm.h> 21#include <linux/interrupt.h> 22#include <linux/blkdev.h> 23#include <linux/hdreg.h> 24#include <linux/zorro.h> 25#include <linux/ide.h> 26#include <linux/init.h> 27 28#include <asm/amigahw.h> 29#include <asm/amigaints.h> 30 31 32 /* 33 * The Buddha has 2 IDE interfaces, the Catweasel has 3, X-Surf has 2 34 */ 35 36#define BUDDHA_NUM_HWIFS 2 37#define CATWEASEL_NUM_HWIFS 3 38#define XSURF_NUM_HWIFS 2 39 40 /* 41 * Bases of the IDE interfaces (relative to the board address) 42 */ 43 44#define BUDDHA_BASE1 0x800 45#define BUDDHA_BASE2 0xa00 46#define BUDDHA_BASE3 0xc00 47 48#define XSURF_BASE1 0xb000 /* 2.5" Interface */ 49#define XSURF_BASE2 0xd000 /* 3.5" Interface */ 50 51static u_int buddha_bases[CATWEASEL_NUM_HWIFS] __initdata = { 52 BUDDHA_BASE1, BUDDHA_BASE2, BUDDHA_BASE3 53}; 54 55static u_int xsurf_bases[XSURF_NUM_HWIFS] __initdata = { 56 XSURF_BASE1, XSURF_BASE2 57}; 58 59 60 /* 61 * Offsets from one of the above bases 62 */ 63 64#define BUDDHA_DATA 0x00 65#define BUDDHA_ERROR 0x06 /* see err-bits */ 66#define BUDDHA_NSECTOR 0x0a /* nr of sectors to read/write */ 67#define BUDDHA_SECTOR 0x0e /* starting sector */ 68#define BUDDHA_LCYL 0x12 /* starting cylinder */ 69#define BUDDHA_HCYL 0x16 /* high byte of starting cyl */ 70#define BUDDHA_SELECT 0x1a /* 101dhhhh , d=drive, hhhh=head */ 71#define BUDDHA_STATUS 0x1e /* see status-bits */ 72#define BUDDHA_CONTROL 0x11a 73#define XSURF_CONTROL -1 /* X-Surf has no CS1* (Control/AltStat) */ 74 75static int buddha_offsets[IDE_NR_PORTS] __initdata = { 76 BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL, 77 BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, BUDDHA_CONTROL, -1 78}; 79 80static int xsurf_offsets[IDE_NR_PORTS] __initdata = { 81 BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL, 82 BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, XSURF_CONTROL, -1 83}; 84 85 /* 86 * Other registers 87 */ 88 89#define BUDDHA_IRQ1 0xf00 /* MSB = 1, Harddisk is source of */ 90#define BUDDHA_IRQ2 0xf40 /* interrupt */ 91#define BUDDHA_IRQ3 0xf80 92 93#define XSURF_IRQ1 0x7e 94#define XSURF_IRQ2 0x7e 95 96static int buddha_irqports[CATWEASEL_NUM_HWIFS] __initdata = { 97 BUDDHA_IRQ1, BUDDHA_IRQ2, BUDDHA_IRQ3 98}; 99 100static int xsurf_irqports[XSURF_NUM_HWIFS] __initdata = { 101 XSURF_IRQ1, XSURF_IRQ2 102}; 103 104#define BUDDHA_IRQ_MR 0xfc0 /* master interrupt enable */ 105 106 107 /* 108 * Board information 109 */ 110 111typedef enum BuddhaType_Enum { 112 BOARD_BUDDHA, BOARD_CATWEASEL, BOARD_XSURF 113} BuddhaType; 114 115 116 /* 117 * Check and acknowledge the interrupt status 118 */ 119 120static int buddha_ack_intr(ide_hwif_t *hwif) 121{ 122 unsigned char ch; 123 124 ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]); 125 if (!(ch & 0x80)) 126 return 0; 127 return 1; 128} 129 130static int xsurf_ack_intr(ide_hwif_t *hwif) 131{ 132 unsigned char ch; 133 134 ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]); 135 /* X-Surf needs a 0 written to IRQ register to ensure ISA bit A11 stays at 0 */ 136 z_writeb(0, hwif->io_ports[IDE_IRQ_OFFSET]); 137 if (!(ch & 0x80)) 138 return 0; 139 return 1; 140} 141 142 /* 143 * Probe for a Buddha or Catweasel IDE interface 144 */ 145 146void __init buddha_init(void) 147{ 148 hw_regs_t hw; 149 ide_hwif_t *hwif; 150 int i, index; 151 152 struct zorro_dev *z = NULL; 153 u_long buddha_board = 0; 154 BuddhaType type; 155 int buddha_num_hwifs; 156 157 while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { 158 unsigned long board; 159 if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) { 160 buddha_num_hwifs = BUDDHA_NUM_HWIFS; 161 type=BOARD_BUDDHA; 162 } else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_CATWEASEL) { 163 buddha_num_hwifs = CATWEASEL_NUM_HWIFS; 164 type=BOARD_CATWEASEL; 165 } else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF) { 166 buddha_num_hwifs = XSURF_NUM_HWIFS; 167 type=BOARD_XSURF; 168 } else 169 continue; 170 171 board = z->resource.start; 172 173 174 if(type != BOARD_XSURF) { 175 if (!request_mem_region(board+BUDDHA_BASE1, 0x800, "IDE")) 176 continue; 177 } else { 178 if (!request_mem_region(board+XSURF_BASE1, 0x1000, "IDE")) 179 continue; 180 if (!request_mem_region(board+XSURF_BASE2, 0x1000, "IDE")) 181 goto fail_base2; 182 if (!request_mem_region(board+XSURF_IRQ1, 0x8, "IDE")) { 183 release_mem_region(board+XSURF_BASE2, 0x1000); 184fail_base2: 185 release_mem_region(board+XSURF_BASE1, 0x1000); 186 continue; 187 } 188 } 189 buddha_board = ZTWO_VADDR(board); 190 191 /* write to BUDDHA_IRQ_MR to enable the board IRQ */ 192 /* X-Surf doesn't have this. IRQs are always on */ 193 if (type != BOARD_XSURF) 194 z_writeb(0, buddha_board+BUDDHA_IRQ_MR); 195 196 for(i=0;i<buddha_num_hwifs;i++) { 197 if(type != BOARD_XSURF) { 198 ide_setup_ports(&hw, (buddha_board+buddha_bases[i]), 199 buddha_offsets, 0, 200 (buddha_board+buddha_irqports[i]), 201 buddha_ack_intr, 202// budda_iops, 203 IRQ_AMIGA_PORTS); 204 } else { 205 ide_setup_ports(&hw, (buddha_board+xsurf_bases[i]), 206 xsurf_offsets, 0, 207 (buddha_board+xsurf_irqports[i]), 208 xsurf_ack_intr, 209// xsurf_iops, 210 IRQ_AMIGA_PORTS); 211 } 212 213 index = ide_register_hw(&hw, 1, &hwif); 214 if (index != -1) { 215 hwif->mmio = 1; 216 printk("ide%d: ", index); 217 switch(type) { 218 case BOARD_BUDDHA: 219 printk("Buddha"); 220 break; 221 case BOARD_CATWEASEL: 222 printk("Catweasel"); 223 break; 224 case BOARD_XSURF: 225 printk("X-Surf"); 226 break; 227 } 228 printk(" IDE interface\n"); 229 } 230 } 231 } 232} 233