Root/
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 iss_storagedev@hp.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 command_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->io_mem_addr + COMMAND_FIFO); |
160 | } |
161 | |
162 | static void smart2e_intr_mask(ctlr_info_t *h, unsigned long val) |
163 | { |
164 | outl(val, h->io_mem_addr + INTR_MASK); |
165 | } |
166 | |
167 | static unsigned long smart2e_fifo_full(ctlr_info_t *h) |
168 | { |
169 | return inl(h->io_mem_addr + COMMAND_FIFO); |
170 | } |
171 | |
172 | static unsigned long smart2e_completed(ctlr_info_t *h) |
173 | { |
174 | return inl(h->io_mem_addr + COMMAND_COMPLETE_FIFO); |
175 | } |
176 | |
177 | static unsigned long smart2e_intr_pending(ctlr_info_t *h) |
178 | { |
179 | return inl(h->io_mem_addr + 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->io_mem_addr + SMART1_SYSTEM_DOORBELL); |
216 | |
217 | outl(c->busaddr, h->io_mem_addr + SMART1_LISTADDR); |
218 | outw(c->size, h->io_mem_addr + SMART1_LISTLEN); |
219 | |
220 | outb(CHANNEL_BUSY, h->io_mem_addr + 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->io_mem_addr + SMART1_SYSTEM_DOORBELL); |
227 | outb(CHANNEL_BUSY, h->io_mem_addr + SMART1_LOCAL_DOORBELL); |
228 | outb(0x01, h->io_mem_addr + SMART1_INTR_MASK); |
229 | outb(0x01, h->io_mem_addr + SMART1_SYSTEM_MASK); |
230 | } else { |
231 | outb(0, h->io_mem_addr + 0xC8E); |
232 | } |
233 | } |
234 | |
235 | static unsigned long smart1_fifo_full(ctlr_info_t *h) |
236 | { |
237 | unsigned char chan; |
238 | chan = inb(h->io_mem_addr + 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->io_mem_addr + SMART1_SYSTEM_DOORBELL) & CHANNEL_BUSY) { |
248 | outb(CHANNEL_BUSY, h->io_mem_addr + SMART1_SYSTEM_DOORBELL); |
249 | |
250 | cmd = inl(h->io_mem_addr + SMART1_COMPLETE_ADDR); |
251 | status = inb(h->io_mem_addr + SMART1_LISTSTATUS); |
252 | |
253 | outb(CHANNEL_CLEAR, h->io_mem_addr + SMART1_LOCAL_DOORBELL); |
254 | |
255 | /* |
256 | * this is x86 (actually compaq x86) only, so it's ok |
257 | */ |
258 | if (cmd) ((cmdlist_t*)bus_to_virt(cmd))->req.hdr.rcode = status; |
259 | } else { |
260 | cmd = 0; |
261 | } |
262 | return cmd; |
263 | } |
264 | |
265 | static unsigned long smart1_intr_pending(ctlr_info_t *h) |
266 | { |
267 | unsigned char chan; |
268 | chan = inb(h->io_mem_addr + SMART1_SYSTEM_DOORBELL) & CHANNEL_BUSY; |
269 | return chan; |
270 | } |
271 | |
272 | static struct access_method smart1_access = { |
273 | smart1_submit_command, |
274 | smart1_intr_mask, |
275 | smart1_fifo_full, |
276 | smart1_intr_pending, |
277 | smart1_completed, |
278 | }; |
279 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9