aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aacraid/rkt.c
diff options
context:
space:
mode:
authorMark Haverkamp <markh@osdl.org>2006-09-19 12:00:02 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-09-23 21:09:42 -0400
commit76a7f8fdc0c2381ae1ba55ef71837712223ecb3c (patch)
treeb6672be9f0c94d36841e56e6cf8a8636028268c5 /drivers/scsi/aacraid/rkt.c
parent653ba58d55feb708c6f97e6f3e84901b3a03c9c0 (diff)
[SCSI] aacraid: merge rx and rkt code
Received from Mark Salyzyn: The only real difference between the rkt and rx platform modules is the offset of the message registers. This patch recognizes this similarity and simplifies the driver to reduce it's code footprint and to improve maintainability by reducing the code duplication. Visibly, the 'rkt.c' portion of this patch looks more complicated than it really is. View it as retaining the rkt-only specifics of the interface. Signed-off-by: Mark Haverkamp <markh@osdl.org> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/aacraid/rkt.c')
-rw-r--r--drivers/scsi/aacraid/rkt.c461
1 files changed, 17 insertions, 444 deletions
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
index f850c3a7cce9..643f23b5ded8 100644
--- a/drivers/scsi/aacraid/rkt.c
+++ b/drivers/scsi/aacraid/rkt.c
@@ -28,389 +28,27 @@
28 * 28 *
29 */ 29 */
30 30
31#include <linux/kernel.h>
32#include <linux/init.h>
33#include <linux/types.h>
34#include <linux/sched.h>
35#include <linux/pci.h>
36#include <linux/spinlock.h>
37#include <linux/slab.h>
38#include <linux/blkdev.h> 31#include <linux/blkdev.h>
39#include <linux/delay.h>
40#include <linux/completion.h>
41#include <linux/time.h>
42#include <linux/interrupt.h>
43#include <asm/semaphore.h>
44 32
45#include <scsi/scsi_host.h> 33#include <scsi/scsi_host.h>
46 34
47#include "aacraid.h" 35#include "aacraid.h"
48 36
49static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs)
50{
51 struct aac_dev *dev = dev_id;
52
53 if (dev->new_comm_interface) {
54 u32 Index = rkt_readl(dev, MUnit.OutboundQueue);
55 if (Index == 0xFFFFFFFFL)
56 Index = rkt_readl(dev, MUnit.OutboundQueue);
57 if (Index != 0xFFFFFFFFL) {
58 do {
59 if (aac_intr_normal(dev, Index)) {
60 rkt_writel(dev, MUnit.OutboundQueue, Index);
61 rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady);
62 }
63 Index = rkt_readl(dev, MUnit.OutboundQueue);
64 } while (Index != 0xFFFFFFFFL);
65 return IRQ_HANDLED;
66 }
67 } else {
68 unsigned long bellbits;
69 u8 intstat;
70 intstat = rkt_readb(dev, MUnit.OISR);
71 /*
72 * Read mask and invert because drawbridge is reversed.
73 * This allows us to only service interrupts that have
74 * been enabled.
75 * Check to see if this is our interrupt. If it isn't just return
76 */
77 if (intstat & ~(dev->OIMR))
78 {
79 bellbits = rkt_readl(dev, OutboundDoorbellReg);
80 if (bellbits & DoorBellPrintfReady) {
81 aac_printf(dev, rkt_readl (dev, IndexRegs.Mailbox[5]));
82 rkt_writel(dev, MUnit.ODR,DoorBellPrintfReady);
83 rkt_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
84 }
85 else if (bellbits & DoorBellAdapterNormCmdReady) {
86 rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
87 aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
88// rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
89 }
90 else if (bellbits & DoorBellAdapterNormRespReady) {
91 rkt_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
92 aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
93 }
94 else if (bellbits & DoorBellAdapterNormCmdNotFull) {
95 rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
96 }
97 else if (bellbits & DoorBellAdapterNormRespNotFull) {
98 rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
99 rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull);
100 }
101 return IRQ_HANDLED;
102 }
103 }
104 return IRQ_NONE;
105}
106
107/**
108 * aac_rkt_disable_interrupt - Disable interrupts
109 * @dev: Adapter
110 */
111
112static void aac_rkt_disable_interrupt(struct aac_dev *dev)
113{
114 rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
115}
116
117/**
118 * rkt_sync_cmd - send a command and wait
119 * @dev: Adapter
120 * @command: Command to execute
121 * @p1: first parameter
122 * @ret: adapter status
123 *
124 * This routine will send a synchronous command to the adapter and wait
125 * for its completion.
126 */
127
128static int rkt_sync_cmd(struct aac_dev *dev, u32 command,
129 u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
130 u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4)
131{
132 unsigned long start;
133 int ok;
134 /*
135 * Write the command into Mailbox 0
136 */
137 rkt_writel(dev, InboundMailbox0, command);
138 /*
139 * Write the parameters into Mailboxes 1 - 6
140 */
141 rkt_writel(dev, InboundMailbox1, p1);
142 rkt_writel(dev, InboundMailbox2, p2);
143 rkt_writel(dev, InboundMailbox3, p3);
144 rkt_writel(dev, InboundMailbox4, p4);
145 /*
146 * Clear the synch command doorbell to start on a clean slate.
147 */
148 rkt_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
149 /*
150 * Disable doorbell interrupts
151 */
152 rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
153 /*
154 * Force the completion of the mask register write before issuing
155 * the interrupt.
156 */
157 rkt_readb (dev, MUnit.OIMR);
158 /*
159 * Signal that there is a new synch command
160 */
161 rkt_writel(dev, InboundDoorbellReg, INBOUNDDOORBELL_0);
162
163 ok = 0;
164 start = jiffies;
165
166 /*
167 * Wait up to 30 seconds
168 */
169 while (time_before(jiffies, start+30*HZ))
170 {
171 udelay(5); /* Delay 5 microseconds to let Mon960 get info. */
172 /*
173 * Mon960 will set doorbell0 bit when it has completed the command.
174 */
175 if (rkt_readl(dev, OutboundDoorbellReg) & OUTBOUNDDOORBELL_0) {
176 /*
177 * Clear the doorbell.
178 */
179 rkt_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
180 ok = 1;
181 break;
182 }
183 /*
184 * Yield the processor in case we are slow
185 */
186 msleep(1);
187 }
188 if (ok != 1) {
189 /*
190 * Restore interrupt mask even though we timed out
191 */
192 if (dev->new_comm_interface)
193 rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
194 else
195 rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
196 return -ETIMEDOUT;
197 }
198 /*
199 * Pull the synch status from Mailbox 0.
200 */
201 if (status)
202 *status = rkt_readl(dev, IndexRegs.Mailbox[0]);
203 if (r1)
204 *r1 = rkt_readl(dev, IndexRegs.Mailbox[1]);
205 if (r2)
206 *r2 = rkt_readl(dev, IndexRegs.Mailbox[2]);
207 if (r3)
208 *r3 = rkt_readl(dev, IndexRegs.Mailbox[3]);
209 if (r4)
210 *r4 = rkt_readl(dev, IndexRegs.Mailbox[4]);
211 /*
212 * Clear the synch command doorbell.
213 */
214 rkt_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
215 /*
216 * Restore interrupt mask
217 */
218 if (dev->new_comm_interface)
219 rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
220 else
221 rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
222 return 0;
223
224}
225
226/**
227 * aac_rkt_interrupt_adapter - interrupt adapter
228 * @dev: Adapter
229 *
230 * Send an interrupt to the i960 and breakpoint it.
231 */
232
233static void aac_rkt_interrupt_adapter(struct aac_dev *dev)
234{
235 rkt_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0,
236 NULL, NULL, NULL, NULL, NULL);
237}
238
239/** 37/**
240 * aac_rkt_notify_adapter - send an event to the adapter 38 * aac_rkt_ioremap
241 * @dev: Adapter 39 * @size: mapping resize request
242 * @event: Event to send
243 * 40 *
244 * Notify the i960 that something it probably cares about has
245 * happened.
246 */ 41 */
247 42static int aac_rkt_ioremap(struct aac_dev * dev, u32 size)
248static void aac_rkt_notify_adapter(struct aac_dev *dev, u32 event)
249{ 43{
250 switch (event) { 44 if (!size) {
251 45 iounmap(dev->regs.rkt);
252 case AdapNormCmdQue: 46 return 0;
253 rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_1);
254 break;
255 case HostNormRespNotFull:
256 rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_4);
257 break;
258 case AdapNormRespQue:
259 rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_2);
260 break;
261 case HostNormCmdNotFull:
262 rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3);
263 break;
264 case HostShutdown:
265// rkt_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, 0, 0,
266// NULL, NULL, NULL, NULL, NULL);
267 break;
268 case FastIo:
269 rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6);
270 break;
271 case AdapPrintfDone:
272 rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_5);
273 break;
274 default:
275 BUG();
276 break;
277 } 47 }
278} 48 dev->base = dev->regs.rkt = ioremap(dev->scsi_host_ptr->base, size);
279 49 if (dev->base == NULL)
280/**
281 * aac_rkt_start_adapter - activate adapter
282 * @dev: Adapter
283 *
284 * Start up processing on an i960 based AAC adapter
285 */
286
287static void aac_rkt_start_adapter(struct aac_dev *dev)
288{
289 struct aac_init *init;
290
291 init = dev->init;
292 init->HostElapsedSeconds = cpu_to_le32(get_seconds());
293 // We can only use a 32 bit address here
294 rkt_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
295 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
296}
297
298/**
299 * aac_rkt_check_health
300 * @dev: device to check if healthy
301 *
302 * Will attempt to determine if the specified adapter is alive and
303 * capable of handling requests, returning 0 if alive.
304 */
305static int aac_rkt_check_health(struct aac_dev *dev)
306{
307 u32 status = rkt_readl(dev, MUnit.OMRx[0]);
308
309 /*
310 * Check to see if the board failed any self tests.
311 */
312 if (status & SELF_TEST_FAILED)
313 return -1; 50 return -1;
314 /* 51 dev->IndexRegs = &dev->regs.rkt->IndexRegs;
315 * Check to see if the board panic'd.
316 */
317 if (status & KERNEL_PANIC) {
318 char * buffer;
319 struct POSTSTATUS {
320 __le32 Post_Command;
321 __le32 Post_Address;
322 } * post;
323 dma_addr_t paddr, baddr;
324 int ret;
325
326 if ((status & 0xFF000000L) == 0xBC000000L)
327 return (status >> 16) & 0xFF;
328 buffer = pci_alloc_consistent(dev->pdev, 512, &baddr);
329 ret = -2;
330 if (buffer == NULL)
331 return ret;
332 post = pci_alloc_consistent(dev->pdev,
333 sizeof(struct POSTSTATUS), &paddr);
334 if (post == NULL) {
335 pci_free_consistent(dev->pdev, 512, buffer, baddr);
336 return ret;
337 }
338 memset(buffer, 0, 512);
339 post->Post_Command = cpu_to_le32(COMMAND_POST_RESULTS);
340 post->Post_Address = cpu_to_le32(baddr);
341 rkt_writel(dev, MUnit.IMRx[0], paddr);
342 rkt_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, 0, 0, 0, 0, 0,
343 NULL, NULL, NULL, NULL, NULL);
344 pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
345 post, paddr);
346 if ((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X'))) {
347 ret = (buffer[2] <= '9') ? (buffer[2] - '0') : (buffer[2] - 'A' + 10);
348 ret <<= 4;
349 ret += (buffer[3] <= '9') ? (buffer[3] - '0') : (buffer[3] - 'A' + 10);
350 }
351 pci_free_consistent(dev->pdev, 512, buffer, baddr);
352 return ret;
353 }
354 /*
355 * Wait for the adapter to be up and running.
356 */
357 if (!(status & KERNEL_UP_AND_RUNNING))
358 return -3;
359 /*
360 * Everything is OK
361 */
362 return 0;
363}
364
365/**
366 * aac_rkt_send
367 * @fib: fib to issue
368 *
369 * Will send a fib, returning 0 if successful.
370 */
371static int aac_rkt_send(struct fib * fib)
372{
373 u64 addr = fib->hw_fib_pa;
374 struct aac_dev *dev = fib->dev;
375 volatile void __iomem *device = dev->regs.rkt;
376 u32 Index;
377
378 dprintk((KERN_DEBUG "%p->aac_rkt_send(%p->%llx)\n", dev, fib, addr));
379 Index = rkt_readl(dev, MUnit.InboundQueue);
380 if (Index == 0xFFFFFFFFL)
381 Index = rkt_readl(dev, MUnit.InboundQueue);
382 dprintk((KERN_DEBUG "Index = 0x%x\n", Index));
383 if (Index == 0xFFFFFFFFL)
384 return Index;
385 device += Index;
386 dprintk((KERN_DEBUG "entry = %x %x %u\n", (u32)(addr & 0xffffffff),
387 (u32)(addr >> 32), (u32)le16_to_cpu(fib->hw_fib->header.Size)));
388 writel((u32)(addr & 0xffffffff), device);
389 device += sizeof(u32);
390 writel((u32)(addr >> 32), device);
391 device += sizeof(u32);
392 writel(le16_to_cpu(fib->hw_fib->header.Size), device);
393 rkt_writel(dev, MUnit.InboundQueue, Index);
394 dprintk((KERN_DEBUG "aac_rkt_send - return 0\n"));
395 return 0;
396}
397
398static int aac_rkt_restart_adapter(struct aac_dev *dev)
399{
400 u32 var;
401
402 printk(KERN_ERR "%s%d: adapter kernel panic'd.\n",
403 dev->name, dev->id);
404
405 if (aac_rkt_check_health(dev) <= 0)
406 return 1;
407 if (rkt_sync_cmd(dev, IOP_RESET, 0, 0, 0, 0, 0, 0,
408 &var, NULL, NULL, NULL, NULL))
409 return 1;
410 if (var != 0x00000001)
411 return 1;
412 if (rkt_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC)
413 return 1;
414 return 0; 52 return 0;
415} 53}
416 54
@@ -425,74 +63,18 @@ static int aac_rkt_restart_adapter(struct aac_dev *dev)
425 63
426int aac_rkt_init(struct aac_dev *dev) 64int aac_rkt_init(struct aac_dev *dev)
427{ 65{
428 unsigned long start; 66 int retval;
429 unsigned long status; 67 extern int _aac_rx_init(struct aac_dev *dev);
430 int instance; 68 extern void aac_rx_start_adapter(struct aac_dev *dev);
431 const char * name;
432
433 instance = dev->id;
434 name = dev->name;
435 69
436 /* 70 /*
437 * Check to see if the board panic'd while booting.
438 */
439 if (rkt_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC)
440 if (aac_rkt_restart_adapter(dev))
441 goto error_iounmap;
442 /*
443 * Check to see if the board failed any self tests.
444 */
445 if (rkt_readl(dev, MUnit.OMRx[0]) & SELF_TEST_FAILED) {
446 printk(KERN_ERR "%s%d: adapter self-test failed.\n", dev->name, instance);
447 goto error_iounmap;
448 }
449 /*
450 * Check to see if the monitor panic'd while booting.
451 */
452 if (rkt_readl(dev, MUnit.OMRx[0]) & MONITOR_PANIC) {
453 printk(KERN_ERR "%s%d: adapter monitor panic.\n", dev->name, instance);
454 goto error_iounmap;
455 }
456 start = jiffies;
457 /*
458 * Wait for the adapter to be up and running. Wait up to 3 minutes
459 */
460 while (!(rkt_readl(dev, MUnit.OMRx[0]) & KERNEL_UP_AND_RUNNING))
461 {
462 if(time_after(jiffies, start+startup_timeout*HZ))
463 {
464 status = rkt_readl(dev, MUnit.OMRx[0]);
465 printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n",
466 dev->name, instance, status);
467 goto error_iounmap;
468 }
469 msleep(1);
470 }
471 if (request_irq(dev->scsi_host_ptr->irq, aac_rkt_intr, IRQF_SHARED|IRQF_DISABLED, "aacraid", (void *)dev)<0)
472 {
473 printk(KERN_ERR "%s%d: Interrupt unavailable.\n", name, instance);
474 goto error_iounmap;
475 }
476 /*
477 * Fill in the function dispatch table. 71 * Fill in the function dispatch table.
478 */ 72 */
479 dev->a_ops.adapter_interrupt = aac_rkt_interrupt_adapter; 73 dev->a_ops.adapter_ioremap = aac_rkt_ioremap;
480 dev->a_ops.adapter_disable_int = aac_rkt_disable_interrupt;
481 dev->a_ops.adapter_notify = aac_rkt_notify_adapter;
482 dev->a_ops.adapter_sync_cmd = rkt_sync_cmd;
483 dev->a_ops.adapter_check_health = aac_rkt_check_health;
484 dev->a_ops.adapter_send = aac_rkt_send;
485
486 /*
487 * First clear out all interrupts. Then enable the one's that we
488 * can handle.
489 */
490 rkt_writeb(dev, MUnit.OIMR, 0xff);
491 rkt_writel(dev, MUnit.ODR, 0xffffffff);
492 rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
493 74
494 if (aac_init_adapter(dev) == NULL) 75 retval = _aac_rx_init(dev);
495 goto error_irq; 76 if (retval)
77 return retval;
496 if (dev->new_comm_interface) { 78 if (dev->new_comm_interface) {
497 /* 79 /*
498 * FIB Setup has already been done, but we can minimize the 80 * FIB Setup has already been done, but we can minimize the
@@ -509,20 +91,11 @@ int aac_rkt_init(struct aac_dev *dev)
509 dev->init->MaxIoCommands = cpu_to_le32(246); 91 dev->init->MaxIoCommands = cpu_to_le32(246);
510 dev->scsi_host_ptr->can_queue = 246 - AAC_NUM_MGT_FIB; 92 dev->scsi_host_ptr->can_queue = 246 - AAC_NUM_MGT_FIB;
511 } 93 }
512 rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
513 } 94 }
514 /* 95 /*
515 * Tell the adapter that all is configured, and it can start 96 * Tell the adapter that all is configured, and it can start
516 * accepting requests 97 * accepting requests
517 */ 98 */
518 aac_rkt_start_adapter(dev); 99 aac_rx_start_adapter(dev);
519 return 0; 100 return 0;
520
521error_irq:
522 rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
523 free_irq(dev->scsi_host_ptr->irq, (void *)dev);
524
525error_iounmap:
526
527 return -1;
528} 101}