File: /usr/src/linux/drivers/block/smart1,2.h

1     /*
2      *    Disk Array driver for Compaq SMART2 Controllers
3      *    Copyright 1998 Compaq Computer Corporation
4      *
5      *    This program is free software; you can redistribute it and/or modify
6      *    it under the terms of the GNU General Public License as published by
7      *    the Free Software Foundation; either version 2 of the License, or
8      *    (at your option) any later version.
9      *
10      *    This program is distributed in the hope that it will be useful,
11      *    but WITHOUT ANY WARRANTY; without even the implied warranty of
12      *    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
13      *    NON INFRINGEMENT.  See the GNU General Public License for more details.
14      *
15      *    You should have received a copy of the GNU General Public License
16      *    along with this program; if not, write to the Free Software
17      *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18      *
19      *    Questions/Comments/Bugfixes to arrays@compaq.com
20      *
21      *    If you want to make changes, improve or add functionality to this
22      *    driver, you'll probably need the Compaq Array Controller Interface
23      *    Specificiation (Document number ECG086/1198)
24      */
25     
26     /*
27      * This file contains the controller communication implementation for
28      * Compaq SMART-1 and SMART-2 controllers.  To the best of my knowledge,
29      * this should support:
30      *
31      *  PCI:
32      *  SMART-2/P, SMART-2DH, SMART-2SL, SMART-221, SMART-3100ES, SMART-3200
33      *  Integerated SMART Array Controller, SMART-4200, SMART-4250ES
34      *
35      *  EISA:
36      *  SMART-2/E, SMART, IAES, IDA-2, IDA
37      */
38     
39     /*
40      * Memory mapped FIFO interface (SMART 42xx cards)
41      */
42     static void smart4_submit_command(ctlr_info_t *h, cmdlist_t *c)
43     {
44             writel(c->busaddr, h->vaddr + S42XX_REQUEST_PORT_OFFSET);
45     }
46     
47     /*  
48      *  This card is the opposite of the other cards.  
49      *   0 turns interrupts on... 
50      *   0x08 turns them off... 
51      */
52     static void smart4_intr_mask(ctlr_info_t *h, unsigned long val)
53     {
54     	if (val) 
55     	{ /* Turn interrupts on */
56     		writel(0, h->vaddr + S42XX_REPLY_INTR_MASK_OFFSET);
57     	} else /* Turn them off */
58     	{
59             	writel( S42XX_INTR_OFF, 
60     			h->vaddr + S42XX_REPLY_INTR_MASK_OFFSET);
61     	}
62     }
63     
64     /*
65      *  For older cards FIFO Full = 0. 
66      *  On this card 0 means there is room, anything else FIFO Full. 
67      * 
68      */ 
69     static unsigned long smart4_fifo_full(ctlr_info_t *h)
70     {
71     	
72             return (!readl(h->vaddr + S42XX_REQUEST_PORT_OFFSET));
73     }
74     
75     /* This type of controller returns -1 if the fifo is empty, 
76      *    Not 0 like the others.
77      *    And we need to let it know we read a value out 
78      */ 
79     static unsigned long smart4_completed(ctlr_info_t *h)
80     {
81     	long register_value 
82     		= readl(h->vaddr + S42XX_REPLY_PORT_OFFSET);
83     
84     	/* Fifo is empty */
85     	if( register_value == 0xffffffff)
86     		return 0; 	
87     
88     	/* Need to let it know we got the reply */
89     	/* We do this by writing a 0 to the port we just read from */
90     	writel(0, h->vaddr + S42XX_REPLY_PORT_OFFSET);
91     
92     	return ((unsigned long) register_value); 
93     }
94     
95      /*
96      *  This hardware returns interrupt pending at a different place and 
97      *  it does not tell us if the fifo is empty, we will have check  
98      *  that by getting a 0 back from the comamnd_completed call. 
99      */
100     static unsigned long smart4_intr_pending(ctlr_info_t *h)
101     {
102     	unsigned long register_value  = 
103     		readl(h->vaddr + S42XX_INTR_STATUS);
104     
105     	if( register_value &  S42XX_INTR_PENDING) 
106     		return  FIFO_NOT_EMPTY;	
107     	return 0 ;
108     }
109     
110     static struct access_method smart4_access = {
111     	smart4_submit_command,
112     	smart4_intr_mask,
113     	smart4_fifo_full,
114     	smart4_intr_pending,
115     	smart4_completed,
116     };
117     
118     /*
119      * Memory mapped FIFO interface (PCI SMART2 and SMART 3xxx cards)
120      */
121     static void smart2_submit_command(ctlr_info_t *h, cmdlist_t *c)
122     {
123     	writel(c->busaddr, h->vaddr + COMMAND_FIFO);
124     }
125     
126     static void smart2_intr_mask(ctlr_info_t *h, unsigned long val)
127     {
128     	writel(val, h->vaddr + INTR_MASK);
129     }
130     
131     static unsigned long smart2_fifo_full(ctlr_info_t *h)
132     {
133     	return readl(h->vaddr + COMMAND_FIFO);
134     }
135     
136     static unsigned long smart2_completed(ctlr_info_t *h)
137     {
138     	return readl(h->vaddr + COMMAND_COMPLETE_FIFO);
139     }
140     
141     static unsigned long smart2_intr_pending(ctlr_info_t *h)
142     {
143     	return readl(h->vaddr + INTR_PENDING);
144     }
145     
146     static struct access_method smart2_access = {
147     	smart2_submit_command,
148     	smart2_intr_mask,
149     	smart2_fifo_full,
150     	smart2_intr_pending,
151     	smart2_completed,
152     };
153     
154     /*
155      *  IO access for SMART-2/E cards
156      */
157     static void smart2e_submit_command(ctlr_info_t *h, cmdlist_t *c)
158     {
159     	outl(c->busaddr, h->ioaddr + COMMAND_FIFO);
160     }
161     
162     static void smart2e_intr_mask(ctlr_info_t *h, unsigned long val)
163     {
164     	outl(val, h->ioaddr + INTR_MASK);
165     }
166     
167     static unsigned long smart2e_fifo_full(ctlr_info_t *h)
168     {
169     	return inl(h->ioaddr + COMMAND_FIFO);
170     }
171     
172     static unsigned long smart2e_completed(ctlr_info_t *h)
173     {
174     	return inl(h->ioaddr + COMMAND_COMPLETE_FIFO);
175     }
176     
177     static unsigned long smart2e_intr_pending(ctlr_info_t *h)
178     {
179     	return inl(h->ioaddr + INTR_PENDING);
180     }
181     
182     static struct access_method smart2e_access = {
183     	smart2e_submit_command,
184     	smart2e_intr_mask,
185     	smart2e_fifo_full,
186     	smart2e_intr_pending,
187     	smart2e_completed,
188     };
189     
190     /*
191      *  IO access for older SMART-1 type cards
192      */
193     #define SMART1_SYSTEM_MASK		0xC8E
194     #define SMART1_SYSTEM_DOORBELL		0xC8F
195     #define SMART1_LOCAL_MASK		0xC8C
196     #define SMART1_LOCAL_DOORBELL		0xC8D
197     #define SMART1_INTR_MASK		0xC89
198     #define SMART1_LISTADDR			0xC90
199     #define SMART1_LISTLEN			0xC94
200     #define SMART1_TAG			0xC97
201     #define SMART1_COMPLETE_ADDR		0xC98
202     #define SMART1_LISTSTATUS		0xC9E
203     
204     #define CHANNEL_BUSY			0x01
205     #define CHANNEL_CLEAR			0x02
206     
207     static void smart1_submit_command(ctlr_info_t *h, cmdlist_t *c)
208     {
209     	/*
210     	 * This __u16 is actually a bunch of control flags on SMART
211     	 * and below.  We want them all to be zero.
212     	 */
213     	c->hdr.size = 0;
214     
215     	outb(CHANNEL_CLEAR, h->ioaddr + SMART1_SYSTEM_DOORBELL);
216     
217     	outl(c->busaddr, h->ioaddr + SMART1_LISTADDR);
218     	outw(c->size, h->ioaddr + SMART1_LISTLEN);
219     
220     	outb(CHANNEL_BUSY, h->ioaddr + SMART1_LOCAL_DOORBELL);
221     }
222     
223     static void smart1_intr_mask(ctlr_info_t *h, unsigned long val)
224     {
225     	if (val == 1) {
226     		outb(0xFD, h->ioaddr + SMART1_SYSTEM_DOORBELL);
227     		outb(CHANNEL_BUSY, h->ioaddr + SMART1_LOCAL_DOORBELL);
228     		outb(0x01, h->ioaddr + SMART1_INTR_MASK);
229     		outb(0x01, h->ioaddr + SMART1_SYSTEM_MASK);
230     	} else {
231     		outb(0, h->ioaddr + 0xC8E);
232     	}
233     }
234     
235     static unsigned long smart1_fifo_full(ctlr_info_t *h)
236     {
237     	unsigned char chan;
238     	chan = inb(h->ioaddr + SMART1_SYSTEM_DOORBELL) & CHANNEL_CLEAR;
239     	return chan;
240     }
241     
242     static unsigned long smart1_completed(ctlr_info_t *h)
243     {
244     	unsigned char status;
245     	unsigned long cmd;
246     
247     	if (inb(h->ioaddr + SMART1_SYSTEM_DOORBELL) & CHANNEL_BUSY) {
248     		outb(CHANNEL_BUSY, h->ioaddr + SMART1_SYSTEM_DOORBELL);
249     
250     		cmd = inl(h->ioaddr + SMART1_COMPLETE_ADDR);
251     		status = inb(h->ioaddr + SMART1_LISTSTATUS);
252     
253     		outb(CHANNEL_CLEAR, h->ioaddr + SMART1_LOCAL_DOORBELL);
254     
255     		if (cmd) ((cmdlist_t*)bus_to_virt(cmd))->req.hdr.rcode = status;
256     	} else {
257     		cmd = 0;
258     	}
259     	return cmd;
260     }
261     
262     static unsigned long smart1_intr_pending(ctlr_info_t *h)
263     {
264     	unsigned char chan;
265     	chan = inb(h->ioaddr + SMART1_SYSTEM_DOORBELL) & CHANNEL_BUSY;
266     	return chan;
267     }
268     
269     static struct access_method smart1_access = {
270     	smart1_submit_command,
271     	smart1_intr_mask,
272     	smart1_fifo_full,
273     	smart1_intr_pending,
274     	smart1_completed,
275     };
276