1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32#include <linux/kernel.h>
33#include <linux/init.h>
34#include <linux/types.h>
35#include <linux/pci.h>
36#include <linux/spinlock.h>
37#include <linux/blkdev.h>
38#include <linux/delay.h>
39#include <linux/completion.h>
40#include <linux/time.h>
41#include <linux/interrupt.h>
42
43#include <scsi/scsi_host.h>
44
45#include "aacraid.h"
46
47static irqreturn_t aac_sa_intr(int irq, void *dev_id)
48{
49 struct aac_dev *dev = dev_id;
50 unsigned short intstat, mask;
51
52 intstat = sa_readw(dev, DoorbellReg_p);
53
54
55
56
57 mask = ~(sa_readw(dev, SaDbCSR.PRISETIRQMASK));
58
59
60
61 if (intstat & mask) {
62 if (intstat & PrintfReady) {
63 aac_printf(dev, sa_readl(dev, Mailbox5));
64 sa_writew(dev, DoorbellClrReg_p, PrintfReady);
65 sa_writew(dev, DoorbellReg_s, PrintfDone);
66 } else if (intstat & DOORBELL_1) {
67 sa_writew(dev, DoorbellClrReg_p, DOORBELL_1);
68 aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
69 } else if (intstat & DOORBELL_2) {
70 sa_writew(dev, DoorbellClrReg_p, DOORBELL_2);
71 aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
72 } else if (intstat & DOORBELL_3) {
73 sa_writew(dev, DoorbellClrReg_p, DOORBELL_3);
74 } else if (intstat & DOORBELL_4) {
75 sa_writew(dev, DoorbellClrReg_p, DOORBELL_4);
76 }
77 return IRQ_HANDLED;
78 }
79 return IRQ_NONE;
80}
81
82
83
84
85
86
87static void aac_sa_disable_interrupt (struct aac_dev *dev)
88{
89 sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
90}
91
92
93
94
95
96
97static void aac_sa_enable_interrupt (struct aac_dev *dev)
98{
99 sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 |
100 DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
101}
102
103
104
105
106
107
108
109
110
111static void aac_sa_notify_adapter(struct aac_dev *dev, u32 event)
112{
113 switch (event) {
114
115 case AdapNormCmdQue:
116 sa_writew(dev, DoorbellReg_s,DOORBELL_1);
117 break;
118 case HostNormRespNotFull:
119 sa_writew(dev, DoorbellReg_s,DOORBELL_4);
120 break;
121 case AdapNormRespQue:
122 sa_writew(dev, DoorbellReg_s,DOORBELL_2);
123 break;
124 case HostNormCmdNotFull:
125 sa_writew(dev, DoorbellReg_s,DOORBELL_3);
126 break;
127 case HostShutdown:
128
129
130
131
132 break;
133 case FastIo:
134 sa_writew(dev, DoorbellReg_s,DOORBELL_6);
135 break;
136 case AdapPrintfDone:
137 sa_writew(dev, DoorbellReg_s,DOORBELL_5);
138 break;
139 default:
140 BUG();
141 break;
142 }
143}
144
145
146
147
148
149
150
151
152
153
154
155
156
157static int sa_sync_cmd(struct aac_dev *dev, u32 command,
158 u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
159 u32 *ret, u32 *r1, u32 *r2, u32 *r3, u32 *r4)
160{
161 unsigned long start;
162 int ok;
163
164
165
166 sa_writel(dev, Mailbox0, command);
167
168
169
170 sa_writel(dev, Mailbox1, p1);
171 sa_writel(dev, Mailbox2, p2);
172 sa_writel(dev, Mailbox3, p3);
173 sa_writel(dev, Mailbox4, p4);
174
175
176
177
178 sa_writew(dev, DoorbellClrReg_p, DOORBELL_0);
179
180
181
182 sa_writew(dev, DoorbellReg_s, DOORBELL_0);
183
184 ok = 0;
185 start = jiffies;
186
187 while(time_before(jiffies, start+30*HZ))
188 {
189
190
191
192 udelay(5);
193
194
195
196
197 if(sa_readw(dev, DoorbellReg_p) & DOORBELL_0) {
198 ok = 1;
199 break;
200 }
201 msleep(1);
202 }
203
204 if (ok != 1)
205 return -ETIMEDOUT;
206
207
208
209 sa_writew(dev, DoorbellClrReg_p, DOORBELL_0);
210
211
212
213 if (ret)
214 *ret = sa_readl(dev, Mailbox0);
215 if (r1)
216 *r1 = sa_readl(dev, Mailbox1);
217 if (r2)
218 *r2 = sa_readl(dev, Mailbox2);
219 if (r3)
220 *r3 = sa_readl(dev, Mailbox3);
221 if (r4)
222 *r4 = sa_readl(dev, Mailbox4);
223 return 0;
224}
225
226
227
228
229
230
231
232
233static void aac_sa_interrupt_adapter (struct aac_dev *dev)
234{
235 sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0,
236 NULL, NULL, NULL, NULL, NULL);
237}
238
239
240
241
242
243
244
245
246static void aac_sa_start_adapter(struct aac_dev *dev)
247{
248 struct aac_init *init;
249
250
251
252 init = dev->init;
253 init->HostElapsedSeconds = cpu_to_le32(get_seconds());
254
255 sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS,
256 (u32)(ulong)dev->init_pa, 0, 0, 0, 0, 0,
257 NULL, NULL, NULL, NULL, NULL);
258}
259
260static int aac_sa_restart_adapter(struct aac_dev *dev, int bled)
261{
262 return -EINVAL;
263}
264
265
266
267
268
269
270
271
272static int aac_sa_check_health(struct aac_dev *dev)
273{
274 long status = sa_readl(dev, Mailbox7);
275
276
277
278
279 if (status & SELF_TEST_FAILED)
280 return -1;
281
282
283
284 if (status & KERNEL_PANIC)
285 return -2;
286
287
288
289 if (!(status & KERNEL_UP_AND_RUNNING))
290 return -3;
291
292
293
294 return 0;
295}
296
297
298
299
300
301
302static int aac_sa_ioremap(struct aac_dev * dev, u32 size)
303{
304 if (!size) {
305 iounmap(dev->regs.sa);
306 return 0;
307 }
308 dev->base = dev->regs.sa = ioremap(dev->scsi_host_ptr->base, size);
309 return (dev->base == NULL) ? -1 : 0;
310}
311
312
313
314
315
316
317
318
319
320
321int aac_sa_init(struct aac_dev *dev)
322{
323 unsigned long start;
324 unsigned long status;
325 int instance;
326 const char *name;
327
328 instance = dev->id;
329 name = dev->name;
330
331 if (aac_sa_ioremap(dev, dev->base_size)) {
332 printk(KERN_WARNING "%s: unable to map adapter.\n", name);
333 goto error_iounmap;
334 }
335
336
337
338
339 if (sa_readl(dev, Mailbox7) & SELF_TEST_FAILED) {
340 printk(KERN_WARNING "%s%d: adapter self-test failed.\n", name, instance);
341 goto error_iounmap;
342 }
343
344
345
346 if (sa_readl(dev, Mailbox7) & KERNEL_PANIC) {
347 printk(KERN_WARNING "%s%d: adapter kernel panic'd.\n", name, instance);
348 goto error_iounmap;
349 }
350 start = jiffies;
351
352
353
354 while (!(sa_readl(dev, Mailbox7) & KERNEL_UP_AND_RUNNING)) {
355 if (time_after(jiffies, start+startup_timeout*HZ)) {
356 status = sa_readl(dev, Mailbox7);
357 printk(KERN_WARNING "%s%d: adapter kernel failed to start, init status = %lx.\n",
358 name, instance, status);
359 goto error_iounmap;
360 }
361 msleep(1);
362 }
363
364
365
366
367
368 dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter;
369 dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt;
370 dev->a_ops.adapter_enable_int = aac_sa_enable_interrupt;
371 dev->a_ops.adapter_notify = aac_sa_notify_adapter;
372 dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
373 dev->a_ops.adapter_check_health = aac_sa_check_health;
374 dev->a_ops.adapter_restart = aac_sa_restart_adapter;
375 dev->a_ops.adapter_intr = aac_sa_intr;
376 dev->a_ops.adapter_deliver = aac_rx_deliver_producer;
377 dev->a_ops.adapter_ioremap = aac_sa_ioremap;
378
379
380
381
382
383 aac_adapter_disable_int(dev);
384 aac_adapter_enable_int(dev);
385
386 if(aac_init_adapter(dev) == NULL)
387 goto error_irq;
388 if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
389 IRQF_SHARED|IRQF_DISABLED,
390 "aacraid", (void *)dev ) < 0) {
391 printk(KERN_WARNING "%s%d: Interrupt unavailable.\n",
392 name, instance);
393 goto error_iounmap;
394 }
395 dev->dbg_base = dev->scsi_host_ptr->base;
396 dev->dbg_base_mapped = dev->base;
397 dev->dbg_size = dev->base_size;
398
399 aac_adapter_enable_int(dev);
400
401
402
403
404
405 aac_sa_start_adapter(dev);
406 return 0;
407
408error_irq:
409 aac_sa_disable_interrupt(dev);
410 free_irq(dev->pdev->irq, (void *)dev);
411
412error_iounmap:
413
414 return -1;
415}
416
417