Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sa.c
Go to the documentation of this file.
1 /*
2  * Adaptec AAC series RAID controller driver
3  * (c) Copyright 2001 Red Hat Inc.
4  *
5  * based on the old aacraid driver that is..
6  * Adaptec aacraid device driver for Linux.
7  *
8  * Copyright (c) 2000-2010 Adaptec, Inc.
9  * 2010 PMC-Sierra, Inc. ([email protected])
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2, or (at your option)
14  * any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; see the file COPYING. If not, write to
23  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  * Module Name:
26  * sa.c
27  *
28  * Abstract: Drawbridge specific support functions
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 
47 static 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  * Read mask and invert because drawbridge is reversed.
55  * This allows us to only service interrupts that have been enabled.
56  */
57  mask = ~(sa_readw(dev, SaDbCSR.PRISETIRQMASK));
58 
59  /* Check to see if this is our interrupt. If it isn't just return */
60 
61  if (intstat & mask) {
62  if (intstat & PrintfReady) {
63  aac_printf(dev, sa_readl(dev, Mailbox5));
64  sa_writew(dev, DoorbellClrReg_p, PrintfReady); /* clear PrintfReady */
66  } else if (intstat & DOORBELL_1) { // dev -> Host Normal Command Ready
67  sa_writew(dev, DoorbellClrReg_p, DOORBELL_1);
69  } else if (intstat & DOORBELL_2) { // dev -> Host Normal Response Ready
70  sa_writew(dev, DoorbellClrReg_p, DOORBELL_2);
72  } else if (intstat & DOORBELL_3) { // dev -> Host Normal Command Not Full
73  sa_writew(dev, DoorbellClrReg_p, DOORBELL_3);
74  } else if (intstat & DOORBELL_4) { // dev -> Host Normal Response Not Full
75  sa_writew(dev, DoorbellClrReg_p, DOORBELL_4);
76  }
77  return IRQ_HANDLED;
78  }
79  return IRQ_NONE;
80 }
81 
87 static void aac_sa_disable_interrupt (struct aac_dev *dev)
88 {
89  sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
90 }
91 
97 static 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 
111 static 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:
120  break;
121  case AdapNormRespQue:
122  sa_writew(dev, DoorbellReg_s,DOORBELL_2);
123  break;
124  case HostNormCmdNotFull:
126  break;
127  case HostShutdown:
128  /*
129  sa_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, 0, 0,
130  NULL, NULL, NULL, NULL, NULL);
131  */
132  break;
133  case FastIo:
135  break;
136  case AdapPrintfDone:
138  break;
139  default:
140  BUG();
141  break;
142  }
143 }
144 
145 
157 static 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  * Write the Command into Mailbox 0
165  */
166  sa_writel(dev, Mailbox0, command);
167  /*
168  * Write the parameters into Mailboxes 1 - 4
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  * Clear the synch command doorbell to start on a clean slate.
177  */
179  /*
180  * Signal that there is a new synch command
181  */
183 
184  ok = 0;
185  start = jiffies;
186 
187  while(time_before(jiffies, start+30*HZ))
188  {
189  /*
190  * Delay 5uS so that the monitor gets access
191  */
192  udelay(5);
193  /*
194  * Mon110 will set doorbell0 bit when it has
195  * completed the command.
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  * Clear the synch command doorbell.
208  */
210  /*
211  * Pull the synch status from Mailbox 0.
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 
233 static 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 
246 static void aac_sa_start_adapter(struct aac_dev *dev)
247 {
248  struct aac_init *init;
249  /*
250  * Fill in the remaining pieces of the init.
251  */
252  init = dev->init;
254  /* We can only use a 32 bit address here */
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 
260 static int aac_sa_restart_adapter(struct aac_dev *dev, int bled)
261 {
262  return -EINVAL;
263 }
264 
272 static int aac_sa_check_health(struct aac_dev *dev)
273 {
274  long status = sa_readl(dev, Mailbox7);
275 
276  /*
277  * Check to see if the board failed any self tests.
278  */
279  if (status & SELF_TEST_FAILED)
280  return -1;
281  /*
282  * Check to see if the board panic'd while booting.
283  */
284  if (status & KERNEL_PANIC)
285  return -2;
286  /*
287  * Wait for the adapter to be up and running. Wait up to 3 minutes
288  */
289  if (!(status & KERNEL_UP_AND_RUNNING))
290  return -3;
291  /*
292  * Everything is OK
293  */
294  return 0;
295 }
296 
302 static 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->base_start, size);
309  return (dev->base == NULL) ? -1 : 0;
310 }
311 
321 int 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  * Check to see if the board failed any self tests.
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  * Check to see if the board panic'd while booting.
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  * Wait for the adapter to be up and running. Wait up to 3 minutes.
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  * Fill in the function dispatch table.
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  * First clear out all interrupts. Then enable the one's that
381  * we can handle.
382  */
385 
386  if(aac_init_adapter(dev) == NULL)
387  goto error_irq;
388  dev->sync_mode = 0; /* sync. mode not supported */
389  if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
391  "aacraid", (void *)dev ) < 0) {
392  printk(KERN_WARNING "%s%d: Interrupt unavailable.\n",
393  name, instance);
394  goto error_iounmap;
395  }
396  dev->dbg_base = dev->base_start;
397  dev->dbg_base_mapped = dev->base;
398  dev->dbg_size = dev->base_size;
399 
401 
402  /*
403  * Tell the adapter that all is configure, and it can start
404  * accepting requests
405  */
406  aac_sa_start_adapter(dev);
407  return 0;
408 
409 error_irq:
410  aac_sa_disable_interrupt(dev);
411  free_irq(dev->pdev->irq, (void *)dev);
412 
413 error_iounmap:
414 
415  return -1;
416 }
417