File: /usr/src/linux/drivers/ide/buddha.c

1     /*
2      *  linux/drivers/ide/buddha.c -- Amiga Buddha and Catweasel IDE Driver
3      *
4      *	Copyright (C) 1997 by Geert Uytterhoeven
5      *
6      *  This driver was written by based on the specifications in README.buddha.
7      *
8      *  This file is subject to the terms and conditions of the GNU General Public
9      *  License.  See the file COPYING in the main directory of this archive for
10      *  more details.
11      *
12      *  TODO:
13      *    - test it :-)
14      *    - tune the timings using the speed-register
15      */
16     
17     #include <linux/types.h>
18     #include <linux/mm.h>
19     #include <linux/interrupt.h>
20     #include <linux/blkdev.h>
21     #include <linux/hdreg.h>
22     #include <linux/zorro.h>
23     #include <linux/ide.h>
24     #include <linux/init.h>
25     
26     #include <asm/amigahw.h>
27     #include <asm/amigaints.h>
28     
29     
30         /*
31          *  The Buddha has 2 IDE interfaces, the Catweasel has 3
32          */
33     
34     #define BUDDHA_NUM_HWIFS	2
35     #define CATWEASEL_NUM_HWIFS	3
36     
37     
38         /*
39          *  Bases of the IDE interfaces (relative to the board address)
40          */
41     
42     #define BUDDHA_BASE1	0x800
43     #define BUDDHA_BASE2	0xa00
44     #define BUDDHA_BASE3	0xc00
45     
46     static u_int buddha_bases[CATWEASEL_NUM_HWIFS] __initdata = {
47         BUDDHA_BASE1, BUDDHA_BASE2, BUDDHA_BASE3
48     };
49     
50     
51         /*
52          *  Offsets from one of the above bases
53          */
54     
55     #define BUDDHA_DATA	0x00
56     #define BUDDHA_ERROR	0x06		/* see err-bits */
57     #define BUDDHA_NSECTOR	0x0a		/* nr of sectors to read/write */
58     #define BUDDHA_SECTOR	0x0e		/* starting sector */
59     #define BUDDHA_LCYL	0x12		/* starting cylinder */
60     #define BUDDHA_HCYL	0x16		/* high byte of starting cyl */
61     #define BUDDHA_SELECT	0x1a		/* 101dhhhh , d=drive, hhhh=head */
62     #define BUDDHA_STATUS	0x1e		/* see status-bits */
63     #define BUDDHA_CONTROL	0x11a
64     
65     static int buddha_offsets[IDE_NR_PORTS] __initdata = {
66         BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL,
67         BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, BUDDHA_CONTROL
68     };
69     
70     
71         /*
72          *  Other registers
73          */
74     
75     #define BUDDHA_IRQ1	0xf00		/* MSB = 1, Harddisk is source of */
76     #define BUDDHA_IRQ2	0xf40		/* interrupt */
77     #define BUDDHA_IRQ3	0xf80
78     
79     static int buddha_irqports[CATWEASEL_NUM_HWIFS] __initdata = {
80         BUDDHA_IRQ1, BUDDHA_IRQ2, BUDDHA_IRQ3
81     };
82     
83     #define BUDDHA_IRQ_MR	0xfc0		/* master interrupt enable */
84     
85     
86         /*
87          *  Board information
88          */
89     
90     static u_long buddha_board;
91     static int buddha_num_hwifs = -1;
92     
93     
94         /*
95          *  Check and acknowledge the interrupt status
96          */
97     
98     static int buddha_ack_intr(ide_hwif_t *hwif)
99     {
100         unsigned char ch;
101     
102         ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]);
103         if (!(ch & 0x80))
104     	return 0;
105         return 1;
106     }
107     
108     
109         /*
110          *  Any Buddha or Catweasel boards present?
111          */
112     
113     static int __init find_buddha(void)
114     {
115         struct zorro_dev *z = NULL;
116     
117         buddha_num_hwifs = 0;
118         while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
119     	unsigned long board;
120     	if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA)
121     	    buddha_num_hwifs = BUDDHA_NUM_HWIFS;
122     	else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_CATWEASEL)
123     	    buddha_num_hwifs = CATWEASEL_NUM_HWIFS;
124     	else
125     	    continue;
126     	board = z->resource.start;
127     	if (!request_mem_region(board+BUDDHA_BASE1, 0x800, "IDE"))
128     	    continue;
129     	buddha_board = ZTWO_VADDR(board);
130     	/* write to BUDDHA_IRQ_MR to enable the board IRQ */
131     	*(char *)(buddha_board+BUDDHA_IRQ_MR) = 0;
132     	break;
133         }
134         return buddha_num_hwifs;
135     }
136     
137     
138         /*
139          *  Probe for a Buddha or Catweasel IDE interface
140          *  We support only _one_ of them, no multiple boards!
141          */
142     
143     void __init buddha_init(void)
144     {
145         hw_regs_t hw;
146         int i, index;
147     
148         if (buddha_num_hwifs < 0 && !find_buddha())
149     	return;
150     
151         for (i = 0; i < buddha_num_hwifs; i++) {
152     	ide_setup_ports(&hw, (ide_ioreg_t)(buddha_board+buddha_bases[i]),
153     			buddha_offsets, 0,
154     			(ide_ioreg_t)(buddha_board+buddha_irqports[i]),
155     			buddha_ack_intr, IRQ_AMIGA_PORTS);
156     	index = ide_register_hw(&hw, NULL);
157     	if (index != -1)
158     	    printk("ide%d: %s IDE interface\n", index,
159     		   buddha_num_hwifs == BUDDHA_NUM_HWIFS ? "Buddha" :
160     		   					  "Catweasel");
161         }
162     }
163