OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [scsi/] [megaraid.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/*===================================================================
2
 *
3
 *                    Linux MegaRAID device driver
4
 *
5
 * Copyright 1998 American Megatrends Inc.
6
 *
7
 *              This program is free software; you can redistribute it and/or
8
 *              modify it under the terms of the GNU General Public License
9
 *              as published by the Free Software Foundation; either version
10
 *              2 of the License, or (at your option) any later version.
11
 *
12
 * Version : 0.93
13
 *
14
 * Description: Linux device driver for AMI MegaRAID controller
15
 *
16
 * Supported controllers: MegaRAID 418, 428, 438, 466
17
 *
18
 * Maintainer: Jeff L Jones <jeffreyj@ami.com>
19
 *
20
 * History:
21
 *
22
 * Version 0.90:
23
 *     Original source contributed by Dell; integrated it into the kernel and
24
 *     cleaned up some things.  Added support for 438/466 controllers.
25
 *
26
 * Version 0.91:
27
 *     Aligned mailbox area on 16-byte boundry.
28
 *     Added schedule() at the end to properly clean up.
29
 *     Made improvements for conformity to linux driver standards.
30
 *
31
 * Version 0.92:
32
 *     Added support for 2.1 kernels.
33
 *         Reads from pci_dev struct, so it's not dependent on pcibios.
34
 *         Added some missing virt_to_bus() translations.
35
 *     Added support for SMP.
36
 *         Changed global cli()'s to spinlocks for 2.1, and simulated
37
 *          spinlocks for 2.0.
38
 *     Removed setting of SA_INTERRUPT flag when requesting Irq.
39
 *
40
 * Version 0.92ac:
41
 *      Small changes to the comments/formatting. Plus a couple of
42
 *      added notes. Returned to the authors. No actual code changes
43
 *      save printk levels.
44
 *      8 Oct 98        Alan Cox <alan.cox@linux.org>
45
 *
46
 *     Merged with 2.1.131 source tree.
47
 *     12 Dec 98       K. Baranowski <kgb@knm.org.pl>
48
 *
49
 * Version 0.93:
50
 *     Added support for vendor specific ioctl commands (0x80+xxh)
51
 *     Changed some fields in MEGARAID struct to better values.
52
 *     Added signature check for Rp controllers under 2.0 kernels
53
 *     Changed busy-wait loop to be time-based
54
 *     Fixed SMP race condition in isr
55
 *     Added kfree (sgList) on release
56
 *     Added #include linux/version.h to megaraid.h for hosts.h
57
 *     Changed max_id to represent max logical drives instead of targets.
58
 *
59
 *
60
 * BUGS:
61
 *     Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that
62
 *     fails to detect the controller as a pci device on the system.
63
 *
64
 *===================================================================*/
65
 
66
#define CRLFSTR "\n"
67
 
68
#include <linux/config.h>
69
#include <linux/version.h>
70
 
71
#ifdef MODULE
72
#include <linux/module.h>
73
 
74
#if LINUX_VERSION_CODE >= 0x20100
75
char kernel_version[] = UTS_RELEASE;
76
 
77
MODULE_AUTHOR ("American Megatrends Inc.");
78
MODULE_DESCRIPTION ("AMI MegaRAID driver");
79
#endif
80
#endif
81
 
82
#include <linux/types.h>
83
#include <linux/errno.h>
84
#include <linux/kernel.h>
85
#include <linux/sched.h>
86
#include <linux/malloc.h>
87
#include <linux/ioport.h>
88
#include <linux/fcntl.h>
89
#include <linux/delay.h>
90
#include <linux/pci.h>
91
#include <linux/proc_fs.h>
92
#include <linux/blk.h>
93
#include <linux/wait.h>
94
#include <linux/tqueue.h>
95
#include <linux/interrupt.h>
96
 
97
#include <linux/sched.h>
98
#include <linux/stat.h>
99
#include <linux/malloc.h>       /* for kmalloc() */
100
#include <linux/config.h>       /* for CONFIG_PCI */
101
#if LINUX_VERSION_CODE < 0x20100
102
#include <linux/bios32.h>
103
#else
104
#include <asm/spinlock.h>
105
#endif
106
 
107
#include <asm/io.h>
108
#include <asm/irq.h>
109
 
110
#include "sd.h"
111
#include "scsi.h"
112
#include "hosts.h"
113
 
114
#include "megaraid.h"
115
 
116
//================================================================
117
//
118
//                          #Defines
119
//
120
//================================================================
121
 
122
#if LINUX_VERSION_CODE < 0x020100
123
#define ioremap vremap
124
#define iounmap vfree
125
 
126
/* simulate spin locks */
127
typedef struct {
128
  volatile char lock;
129
} spinlock_t;
130
 
131
#define spin_lock_init(x) { (x)->lock = 0;}
132
#define spin_lock_irqsave(x,flags) { while ((x)->lock) barrier();\
133
                                        (x)->lock=1; save_flags(flags);\
134
                                        cli();}
135
#define spin_unlock_irqrestore(x,flags) { (x)->lock=0; restore_flags(flags);}
136
 
137
#endif
138
 
139
#if LINUX_VERSION_CODE >= 0x020100
140
#define queue_task_irq(a,b)     queue_task(a,b)
141
#define queue_task_irq_off(a,b) queue_task(a,b)
142
#endif
143
 
144
#define MAX_SERBUF 160
145
#define COM_BASE 0x2f8
146
 
147
#define ENQUEUE(obj,type,list,next) \
148
{ type **node; long cpuflag; \
149
  spin_lock_irqsave(&mega_lock,cpuflag);\
150
  for(node=&(list); *node; node=(type **)&(*node)->##next); \
151
  (*node) = obj; \
152
  (*node)->##next = NULL; \
153
  spin_unlock_irqrestore(&mega_lock,cpuflag);\
154
};
155
 
156
#define DEQUEUE(obj,type,list,next) \
157
{ long cpuflag; \
158
  spin_lock_irqsave(&mega_lock,cpuflag);\
159
  if ((obj=list) != NULL) {\
160
    list = (type *)(list)->##next; \
161
  } \
162
  spin_unlock_irqrestore(&mega_lock,cpuflag);\
163
};
164
 
165
u_long RDINDOOR (mega_host_config * megaCfg)
166
{
167
  return readl (megaCfg->base + 0x20);
168
}
169
 
170
void WRINDOOR (mega_host_config * megaCfg, u_long value)
171
{
172
  writel (value, megaCfg->base + 0x20);
173
}
174
 
175
u_long RDOUTDOOR (mega_host_config * megaCfg)
176
{
177
  return readl (megaCfg->base + 0x2C);
178
}
179
 
180
void WROUTDOOR (mega_host_config * megaCfg, u_long value)
181
{
182
  writel (value, megaCfg->base + 0x2C);
183
}
184
 
185
//================================================================
186
//
187
//                    Function prototypes
188
//
189
//================================================================
190
static int MegaIssueCmd (mega_host_config * megaCfg,
191
                         u_char * mboxData,
192
                         mega_scb * scb,
193
                         int intr);
194
static int build_sglist (mega_host_config * megaCfg, mega_scb * scb,
195
                         u_long * buffer, u_long * length);
196
 
197
static void mega_runque (void *);
198
static void mega_rundoneq (void);
199
static void mega_cmd_done (mega_host_config *, mega_scb *, int);
200
static mega_scb *mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt);
201
 
202
/* set SERDEBUG to 1 to enable serial debugging */
203
#define SERDEBUG 0
204
#if SERDEBUG
205
static void ser_init (void);
206
static void ser_puts (char *str);
207
static void ser_putc (char c);
208
static int ser_printk (const char *fmt,...);
209
#endif
210
 
211
//================================================================
212
//
213
//                    Global variables
214
//
215
//================================================================
216
static int numCtlrs = 0;
217
static mega_host_config *megaCtlrs[12] = {0};
218
 
219
/* Change this to 0 if you want to see the raw drives */
220
static int use_raid = 1;
221
 
222
/* Queue of pending/completed SCBs */
223
static mega_scb *qPending = NULL;
224
static Scsi_Cmnd *qCompleted = NULL;
225
 
226
volatile static spinlock_t mega_lock;
227
static struct tq_struct runq = {0, 0, mega_runque, NULL};
228
 
229
struct proc_dir_entry proc_scsi_megaraid =
230
{
231
  PROC_SCSI_MEGARAID, 8, "megaraid",
232
  S_IFDIR | S_IRUGO | S_IXUGO, 2
233
};
234
 
235
#if SERDEBUG
236
static char strbuf[MAX_SERBUF + 1];
237
 
238
static void ser_init ()
239
{
240
  unsigned port = COM_BASE;
241
 
242
  outb (0x80, port + 3);
243
  outb (0, port + 1);
244
  /* 9600 Baud, if 19200: outb(6,port) */
245
  outb (12, port);
246
  outb (3, port + 3);
247
  outb (0, port + 1);
248
}
249
 
250
static void ser_puts (char *str)
251
{
252
  char *ptr;
253
 
254
  ser_init ();
255
  for (ptr = str; *ptr; ++ptr)
256
    ser_putc (*ptr);
257
}
258
 
259
static void ser_putc (char c)
260
{
261
  unsigned port = COM_BASE;
262
 
263
  while ((inb (port + 5) & 0x20) == 0);
264
  outb (c, port);
265
  if (c == 0x0a) {
266
    while ((inb (port + 5) & 0x20) == 0);
267
    outb (0x0d, port);
268
  }
269
}
270
 
271
static int ser_printk (const char *fmt,...)
272
{
273
  va_list args;
274
  int i;
275
  long flags;
276
 
277
  va_start (args, fmt);
278
  i = vsprintf (strbuf, fmt, args);
279
  ser_puts (strbuf);
280
  va_end (args);
281
 
282
  return i;
283
}
284
 
285
#define TRACE(a)    { ser_printk a;}
286
 
287
#else
288
#define TRACE(A)
289
#endif
290
 
291
void callDone (Scsi_Cmnd * SCpnt)
292
{
293
  if (SCpnt->result) {
294
    TRACE (("*** %.08lx %.02x <%d.%d.%d> = %x\n", SCpnt->serial_number,
295
            SCpnt->cmnd[0], SCpnt->channel, SCpnt->target, SCpnt->lun,
296
            SCpnt->result));
297
  }
298
  SCpnt->scsi_done (SCpnt);
299
}
300
 
301
/*-------------------------------------------------------------------------
302
 *
303
 *                      Local functions
304
 *
305
 *-------------------------------------------------------------------------*/
306
 
307
//================================================
308
// Initialize SCB structures
309
//================================================
310
static void initSCB (mega_host_config * megaCfg)
311
{
312
  int idx;
313
 
314
  for (idx = 0; idx < megaCfg->max_cmds; idx++) {
315
    megaCfg->scbList[idx].idx = -1;
316
    megaCfg->scbList[idx].flag = 0;
317
    megaCfg->scbList[idx].sgList = NULL;
318
    megaCfg->scbList[idx].SCpnt = NULL;
319
  }
320
}
321
 
322
//===========================
323
// Allocate a SCB structure
324
//===========================
325
static mega_scb * allocateSCB (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
326
{
327
  int idx;
328
  long flags;
329
 
330
  spin_lock_irqsave (&mega_lock, flags);
331
  for (idx = 0; idx < megaCfg->max_cmds; idx++) {
332
    if (megaCfg->scbList[idx].idx < 0) {
333
 
334
      /* Set Index and SCB pointer */
335
      megaCfg->scbList[idx].flag = 0;
336
      megaCfg->scbList[idx].idx = idx;
337
      megaCfg->scbList[idx].SCpnt = SCpnt;
338
      megaCfg->scbList[idx].next = NULL;
339
      spin_unlock_irqrestore (&mega_lock, flags);
340
 
341
      if (megaCfg->scbList[idx].sgList == NULL) {
342
        megaCfg->scbList[idx].sgList =
343
          kmalloc (sizeof (mega_sglist) * MAX_SGLIST, GFP_ATOMIC | GFP_DMA);
344
      }
345
 
346
      return &megaCfg->scbList[idx];
347
    }
348
  }
349
  spin_unlock_irqrestore (&mega_lock, flags);
350
 
351
  printk (KERN_WARNING "Megaraid: Could not allocate free SCB!!!\n");
352
 
353
  return NULL;
354
}
355
 
356
//=======================
357
// Free a SCB structure
358
//=======================
359
static void freeSCB (mega_scb * scb)
360
{
361
  scb->flag = 0;
362
  scb->idx = -1;
363
  scb->next = NULL;
364
  scb->SCpnt = NULL;
365
}
366
 
367
/* Run through the list of completed requests */
368
static void mega_rundoneq ()
369
{
370
  mega_host_config *megaCfg;
371
  Scsi_Cmnd *SCpnt;
372
  long islogical;
373
 
374
  while (1) {
375
    DEQUEUE (SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
376
    if (SCpnt == NULL)
377
      return;
378
 
379
    megaCfg = (mega_host_config *) SCpnt->host->hostdata;
380
 
381
    /* Check if we're allowing access to RAID drives or physical
382
     *  if use_raid == 1 and this wasn't a disk on the max channel or
383
     *  if use_raid == 0 and this was a disk on the max channel
384
     *  then fail.
385
     */
386
    islogical = (SCpnt->channel == megaCfg->host->max_channel) ? 1 : 0;
387
    if (SCpnt->cmnd[0] == INQUIRY &&
388
        ((((u_char *) SCpnt->request_buffer)[0] & 0x1F) == TYPE_DISK) &&
389
        (islogical != use_raid)) {
390
      SCpnt->result = 0xF0;
391
    }
392
 
393
    /* Convert result to error */
394
    switch (SCpnt->result) {
395
    case 0x00:
396
    case 0x02:
397
      SCpnt->result |= (DID_OK << 16);
398
      break;
399
    case 0x8:
400
      SCpnt->result |= (DID_BUS_BUSY << 16);
401
      break;
402
    default:
403
      SCpnt->result |= (DID_BAD_TARGET << 16);
404
      break;
405
    }
406
 
407
    /* Callback */
408
    callDone (SCpnt);
409
  }
410
}
411
 
412
/* Add command to the list of completed requests */
413
static void mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb, int status)
414
{
415
  long flags;
416
 
417
  pScb->SCpnt->result = status;
418
  ENQUEUE (pScb->SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
419
  spin_lock_irqsave (&mega_lock, flags);
420
  freeSCB (pScb);
421
  spin_unlock_irqrestore (&mega_lock, flags);
422
}
423
 
424
/*----------------------------------------------------
425
 * Process pending queue list
426
 *
427
 * Run as a scheduled task
428
 *----------------------------------------------------*/
429
static void mega_runque (void *dummy)
430
{
431
  mega_host_config *megaCfg;
432
  mega_scb *pScb;
433
  long flags;
434
 
435
  /* Take care of any completed requests */
436
  mega_rundoneq ();
437
 
438
  DEQUEUE (pScb, mega_scb, qPending, next);
439
 
440
  if (pScb) {
441
    megaCfg = (mega_host_config *) pScb->SCpnt->host->hostdata;
442
 
443
    if (megaCfg->mbox->busy || megaCfg->flag & (IN_ISR | PENDING)) {
444
      TRACE (("%.08lx %.02x <%d.%d.%d> busy%d isr%d pending%d\n",
445
              pScb->SCpnt->serial_number,
446
              pScb->SCpnt->cmnd[0],
447
              pScb->SCpnt->channel,
448
              pScb->SCpnt->target,
449
              pScb->SCpnt->lun,
450
              megaCfg->mbox->busy,
451
              (megaCfg->flag & IN_ISR) ? 1 : 0,
452
              (megaCfg->flag & PENDING) ? 1 : 0));
453
    }
454
 
455
    if (MegaIssueCmd (megaCfg, pScb->mboxData, pScb, 1)) {
456
      /* We're BUSY... come back later */
457
      spin_lock_irqsave (&mega_lock, flags);
458
      pScb->next = qPending;
459
      qPending = pScb;
460
      spin_unlock_irqrestore (&mega_lock, flags);
461
 
462
      if (!(megaCfg->flag & PENDING)) {
463
        /* If PENDING, irq will schedule task */
464
        queue_task (&runq, &tq_scheduler);
465
      }
466
    }
467
  }
468
}
469
 
470
/*-------------------------------------------------------------------
471
 *
472
 *                 Build a SCB from a Scsi_Cmnd
473
 *
474
 * Returns a SCB pointer, or NULL
475
 * If NULL is returned, the scsi_done function MUST have been called
476
 *
477
 *-------------------------------------------------------------------*/
478
static mega_scb * mega_build_cmd (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
479
{
480
  mega_scb *pScb;
481
  mega_mailbox *mbox;
482
  mega_passthru *pthru;
483
  long seg;
484
 
485
  if (SCpnt->cmnd[0] & 0x80)     /* ioctl from megamgr */
486
    return mega_ioctl (megaCfg, SCpnt);
487
 
488
  /* We don't support multi-luns */
489
  if (SCpnt->lun != 0) {
490
    SCpnt->result = (DID_BAD_TARGET << 16);
491
    callDone (SCpnt);
492
    return NULL;
493
  }
494
 
495
  /*-----------------------------------------------------
496
   *
497
   *               Logical drive commands
498
   *
499
   *-----------------------------------------------------*/
500
  if (SCpnt->channel == megaCfg->host->max_channel) {
501
    switch (SCpnt->cmnd[0]) {
502
    case TEST_UNIT_READY:
503
      memset (SCpnt->request_buffer, 0, SCpnt->request_bufflen);
504
      SCpnt->result = (DID_OK << 16);
505
      callDone (SCpnt);
506
      return NULL;
507
 
508
    case MODE_SENSE:
509
      memset (SCpnt->request_buffer, 0, SCpnt->cmnd[4]);
510
      SCpnt->result = (DID_OK << 16);
511
      callDone (SCpnt);
512
      return NULL;
513
 
514
    case READ_CAPACITY:
515
    case INQUIRY:
516
      /* Allocate a SCB and initialize passthru */
517
      if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
518
        SCpnt->result = (DID_ERROR << 16);
519
        callDone (SCpnt);
520
        return NULL;
521
      }
522
      pthru = &pScb->pthru;
523
      mbox = (mega_mailbox *) & pScb->mboxData;
524
 
525
      memset (mbox, 0, sizeof (pScb->mboxData));
526
      memset (pthru, 0, sizeof (mega_passthru));
527
      pthru->timeout = 0;
528
      pthru->ars = 0;
529
      pthru->islogical = 1;
530
      pthru->logdrv = SCpnt->target;
531
      pthru->cdblen = SCpnt->cmd_len;
532
      pthru->dataxferaddr = virt_to_bus (SCpnt->request_buffer);
533
      pthru->dataxferlen = SCpnt->request_bufflen;
534
      memcpy (pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len);
535
 
536
      /* Initialize mailbox area */
537
      mbox->cmd = MEGA_MBOXCMD_PASSTHRU;
538
      mbox->xferaddr = virt_to_bus (pthru);
539
 
540
      return pScb;
541
 
542
    case READ_6:
543
    case WRITE_6:
544
    case READ_10:
545
    case WRITE_10:
546
      /* Allocate a SCB and initialize mailbox */
547
      if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
548
        SCpnt->result = (DID_ERROR << 16);
549
        callDone (SCpnt);
550
        return NULL;
551
      }
552
      mbox = (mega_mailbox *) & pScb->mboxData;
553
 
554
      memset (mbox, 0, sizeof (pScb->mboxData));
555
      mbox->logdrv = SCpnt->target;
556
      mbox->cmd = (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == READ_10) ?
557
        MEGA_MBOXCMD_LREAD : MEGA_MBOXCMD_LWRITE;
558
 
559
      /* 6-byte */
560
      if (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == WRITE_6) {
561
        mbox->numsectors =
562
          (u_long) SCpnt->cmnd[4];
563
        mbox->lba =
564
          ((u_long) SCpnt->cmnd[1] << 16) |
565
          ((u_long) SCpnt->cmnd[2] << 8) |
566
          (u_long) SCpnt->cmnd[3];
567
        mbox->lba &= 0x1FFFFF;
568
      }
569
 
570
      /* 10-byte */
571
      if (*SCpnt->cmnd == READ_10 || *SCpnt->cmnd == WRITE_10) {
572
        mbox->numsectors =
573
          (u_long) SCpnt->cmnd[8] |
574
          ((u_long) SCpnt->cmnd[7] << 8);
575
        mbox->lba =
576
          ((u_long) SCpnt->cmnd[2] << 24) |
577
          ((u_long) SCpnt->cmnd[3] << 16) |
578
          ((u_long) SCpnt->cmnd[4] << 8) |
579
          (u_long) SCpnt->cmnd[5];
580
      }
581
 
582
      /* Calculate Scatter-Gather info */
583
      mbox->numsgelements = build_sglist (megaCfg, pScb,
584
                                          (u_long *) & mbox->xferaddr,
585
                                          (u_long *) & seg);
586
 
587
      return pScb;
588
 
589
    default:
590
      SCpnt->result = (DID_BAD_TARGET << 16);
591
      callDone (SCpnt);
592
      return NULL;
593
    }
594
  }
595
  /*-----------------------------------------------------
596
   *
597
   *               Passthru drive commands
598
   *
599
   *-----------------------------------------------------*/
600
  else {
601
    /* Allocate a SCB and initialize passthru */
602
    if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
603
      SCpnt->result = (DID_ERROR << 16);
604
      callDone (SCpnt);
605
      return NULL;
606
    }
607
    pthru = &pScb->pthru;
608
    mbox = (mega_mailbox *) pScb->mboxData;
609
 
610
    memset (mbox, 0, sizeof (pScb->mboxData));
611
    memset (pthru, 0, sizeof (mega_passthru));
612
    pthru->timeout = 0;
613
    pthru->ars = 0;
614
    pthru->islogical = 0;
615
    pthru->channel = SCpnt->channel;
616
    pthru->target = SCpnt->target;
617
    pthru->cdblen = SCpnt->cmd_len;
618
    memcpy (pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len);
619
 
620
    pthru->numsgelements = build_sglist (megaCfg, pScb,
621
                                         (u_long *) & pthru->dataxferaddr,
622
                                         (u_long *) & pthru->dataxferlen);
623
 
624
    /* Initialize mailbox */
625
    mbox->cmd = MEGA_MBOXCMD_PASSTHRU;
626
    mbox->xferaddr = virt_to_bus (pthru);
627
 
628
    return pScb;
629
  }
630
  return NULL;
631
}
632
 
633
/*--------------------------------------------------------------------
634
 * build RAID commands for controller, passed down through ioctl()
635
 *--------------------------------------------------------------------*/
636
static mega_scb * mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
637
{
638
  mega_scb *pScb;
639
  mega_ioctl_mbox *mbox;
640
  mega_mailbox *mailbox;
641
  mega_passthru *pthru;
642
  long seg;
643
 
644
  if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
645
    SCpnt->result = (DID_ERROR << 16);
646
    callDone (SCpnt);
647
    return NULL;
648
  }
649
 
650
  mbox = (mega_ioctl_mbox *) & pScb->mboxData;
651
  mailbox = (mega_mailbox *) & pScb->mboxData;
652
  memset (mailbox, 0, sizeof (pScb->mboxData));
653
 
654
  if (SCpnt->cmnd[0] == 0x83) {  /* passthrough command */
655
    char cdblen = SCpnt->cmnd[2];
656
 
657
    pthru = &pScb->pthru;
658
    memset (pthru, 0, sizeof (mega_passthru));
659
    pthru->islogical = SCpnt->cmnd[cdblen + 3] & 0x80;
660
    pthru->timeout = SCpnt->cmnd[cdblen + 3] & 0x07;
661
    pthru->reqsenselen = 10;    /* ? MAX_SENSE; */
662
    pthru->ars = SCpnt->cmnd[cdblen + 3] & 0x08;
663
    pthru->logdrv = SCpnt->cmnd[cdblen + 4];
664
    pthru->channel = SCpnt->cmnd[cdblen + 5];
665
    pthru->target = SCpnt->cmnd[cdblen + 6];
666
    pthru->cdblen = cdblen;
667
    memcpy (pthru->cdb, SCpnt->cmnd, SCpnt->cmnd[2]);
668
 
669
    mailbox->cmd = MEGA_MBOXCMD_PASSTHRU;
670
    mailbox->xferaddr = virt_to_bus (pthru);
671
 
672
    pthru->numsgelements = build_sglist (megaCfg, pScb,
673
                                         (u_long *) & pthru->dataxferaddr,
674
                                         (u_long *) & pthru->dataxferlen);
675
 
676
    return pScb;
677
  }
678
  /* else normal (nonpassthru) command */
679
 
680
  mbox->cmd = SCpnt->cmnd[0] & 0x7F;
681
  mbox->channel = SCpnt->cmnd[1];
682
  mbox->param = SCpnt->cmnd[2];
683
  mbox->pad[0] = SCpnt->cmnd[3];
684
  mbox->logdrv = SCpnt->cmnd[4];
685
 
686
  mbox->numsgelements = build_sglist (megaCfg, pScb,
687
                                      (u_long *) & mbox->xferaddr,
688
                                      (u_long *) & seg);
689
 
690
  return (pScb);
691
}
692
 
693
 
694
/*--------------------------------------------------------------------
695
 * Interrupt service routine
696
 *--------------------------------------------------------------------*/
697
static void megaraid_isr (int irq, void *devp, struct pt_regs *regs)
698
{
699
  mega_host_config    *megaCfg;
700
  u_char byte, idx, sIdx;
701
  u_long dword;
702
  mega_mailbox *mbox;
703
  mega_scb *pScb;
704
  long flags;
705
  int qCnt, qStatus;
706
 
707
  megaCfg = (mega_host_config *) devp;
708
  mbox = (mega_mailbox *) megaCfg->mbox;
709
 
710
  if (megaCfg->host->irq == irq) {
711
 
712
#if LINUX_VERSION_CODE >= 0x20100
713
    spin_lock_irqsave (&io_request_lock, flags);
714
#endif
715
 
716
    spin_lock_irqsave (&mega_lock, flags);
717
 
718
    if (megaCfg->flag & IN_ISR) {
719
      TRACE (("ISR called reentrantly!!\n"));
720
    }
721
 
722
    megaCfg->flag |= IN_ISR;
723
 
724
    /* Check if a valid interrupt is pending */
725
    if (megaCfg->flag & BOARD_QUARTZ) {
726
      dword = RDOUTDOOR (megaCfg);
727
      if (dword != 0x10001234) {
728
        /* Spurious interrupt */
729
        megaCfg->flag &= ~IN_ISR;
730
        spin_unlock_irqrestore (&mega_lock, flags);
731
#if LINUX_VERSION_CODE >= 0x20100
732
        spin_unlock_irqrestore (&io_request_lock, flags);
733
#endif
734
        return;
735
      }
736
      WROUTDOOR (megaCfg, dword);
737
    }
738
    else {
739
      byte = READ_PORT (megaCfg->host->io_port, INTR_PORT);
740
      if ((byte & VALID_INTR_BYTE) == 0) {
741
        /* Spurious interrupt */
742
        megaCfg->flag &= ~IN_ISR;
743
        spin_unlock_irqrestore (&mega_lock, flags);
744
#if LINUX_VERSION_CODE >= 0x20100
745
        spin_unlock_irqrestore (&io_request_lock, flags);
746
#endif
747
        return;
748
      }
749
      WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
750
    }
751
 
752
    qCnt = mbox->numstatus;
753
    qStatus = mbox->status;
754
 
755
    if (qCnt > 1) {
756
      TRACE (("ISR: Received %d status\n", qCnt))
757
        printk (KERN_DEBUG "Got numstatus = %d\n", qCnt);
758
    }
759
 
760
    for (idx = 0; idx < qCnt; idx++) {
761
      sIdx = mbox->completed[idx];
762
      if (sIdx > 0) {
763
        pScb = &megaCfg->scbList[sIdx - 1];
764
        spin_unlock_irqrestore (&mega_lock, flags); /* megalock within cmd_done */
765
        mega_cmd_done (megaCfg, &megaCfg->scbList[sIdx - 1], qStatus);
766
        spin_lock_irqsave (&mega_lock, flags);
767
      }
768
    }
769
    if (megaCfg->flag & BOARD_QUARTZ) {
770
      WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);
771
      while (RDINDOOR (megaCfg) & 0x02);
772
    }
773
    else {
774
      CLEAR_INTR (megaCfg->host->io_port);
775
    }
776
 
777
    megaCfg->flag &= ~IN_ISR;
778
    megaCfg->flag &= ~PENDING;
779
 
780
    spin_unlock_irqrestore (&mega_lock, flags);
781
    mega_runque (NULL);
782
 
783
#if LINUX_VERSION_CODE >= 0x20100
784
    spin_unlock_irqrestore (&io_request_lock, flags);
785
#endif
786
 
787
#if 0
788
    /* Queue as a delayed ISR routine */
789
    queue_task_irq_off (&runq, &tq_immediate);
790
    mark_bh (IMMEDIATE_BH);
791
#endif
792
 
793
  }
794
}
795
 
796
/*==================================================*/
797
/* Wait until the controller's mailbox is available */
798
/*==================================================*/
799
static int busyWaitMbox (mega_host_config * megaCfg)
800
{
801
  mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox;
802
  long counter;
803
 
804
  for (counter = 0; counter < 30000; counter++) {
805
    udelay (100);
806
    if (!mbox->busy)
807
      return 0;
808
  }
809
  return -1;                    /* give up after 3 seconds */
810
}
811
 
812
//=====================================================
813
// Post a command to the card
814
//
815
// Arguments:
816
//   mega_host_config *megaCfg - Controller structure
817
//   u_char *mboxData - Mailbox area, 16 bytes
818
//   mega_scb *pScb   - SCB posting (or NULL if N/A)
819
//   int intr         - if 1, interrupt, 0 is blocking
820
//=====================================================
821
static int MegaIssueCmd (mega_host_config * megaCfg,
822
              u_char * mboxData,
823
              mega_scb * pScb,
824
              int intr)
825
{
826
  mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox;
827
  long flags;
828
  u_char byte;
829
  u_long cmdDone;
830
 
831
  mboxData[0x1] = (pScb ? pScb->idx + 1 : 0x00);        /* Set cmdid */
832
  mboxData[0xF] = 1;            /* Set busy */
833
 
834
  spin_lock_irqsave(&mega_lock,flags);
835
 
836
  /* one bad report of problem when issuing a command while pending.
837
   * Wasn't able to duplicate, but it doesn't really affect performance
838
   * anyway, so don't allow command while PENDING
839
   */
840
 
841
  if (megaCfg->flag & PENDING) {
842
    spin_unlock_irqrestore(&mega_lock,flags);
843
    return -1;
844
  }
845
 
846
  /* Wait until mailbox is free */
847
  if (busyWaitMbox (megaCfg)) {
848
    if (pScb) {
849
      TRACE (("Mailbox busy %.08lx <%d.%d.%d>\n", pScb->SCpnt->serial_number,
850
              pScb->SCpnt->channel, pScb->SCpnt->target, pScb->SCpnt->lun));
851
    } else {
852
        TRACE(("pScb NULL in MegaIssueCmd!\n"));
853
    }
854
    spin_unlock_irqrestore(&mega_lock,flags);
855
    return -1;
856
  }
857
 
858
  /* Copy mailbox data into host structure */
859
  memset (mbox, 0, sizeof (mega_mailbox));
860
  memcpy (mbox, mboxData, 16);
861
 
862
  /* Kick IO */
863
  megaCfg->flag |= PENDING;
864
  if (intr) {
865
    /* Issue interrupt (non-blocking) command */
866
    if (megaCfg->flag & BOARD_QUARTZ) {
867
      mbox->mraid_poll = 0;
868
      mbox->mraid_ack = 0;
869
      WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x1);
870
    }
871
    else {
872
      ENABLE_INTR (megaCfg->host->io_port);
873
      ISSUE_COMMAND (megaCfg->host->io_port);
874
    }
875
    spin_unlock_irqrestore(&mega_lock,flags);
876
  }
877
  else {                        /* Issue non-ISR (blocking) command */
878
 
879
    if (megaCfg->flag & BOARD_QUARTZ) {
880
 
881
      mbox->mraid_poll = 0;
882
      mbox->mraid_ack = 0;
883
      WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x1);
884
 
885
      while ((cmdDone = RDOUTDOOR (megaCfg)) != 0x10001234);
886
      WROUTDOOR (megaCfg, cmdDone);
887
 
888
      spin_unlock_irqrestore(&mega_lock,flags);
889
      if (pScb) {
890
        mega_cmd_done (megaCfg, pScb, mbox->status);
891
        mega_rundoneq ();
892
      }
893
 
894
      WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);
895
      while (RDINDOOR (megaCfg) & 0x2);
896
 
897
      megaCfg->flag &= ~PENDING;
898
 
899
    }
900
    else {
901
      DISABLE_INTR (megaCfg->host->io_port);
902
      ISSUE_COMMAND (megaCfg->host->io_port);
903
 
904
      while (!((byte = READ_PORT (megaCfg->host->io_port, INTR_PORT)) & INTR_VALID));
905
      WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
906
 
907
 
908
      ENABLE_INTR (megaCfg->host->io_port);
909
      CLEAR_INTR (megaCfg->host->io_port);
910
      megaCfg->flag &= ~PENDING;
911
      spin_unlock_irqrestore(&mega_lock,flags);
912
 
913
      if (pScb) {
914
        mega_cmd_done (megaCfg, pScb, mbox->status);
915
        mega_rundoneq ();
916
      }
917
      else {
918
        TRACE (("Error: NULL pScb!\n"));
919
      }
920
 
921
    }
922
  }
923
 
924
  return 0;
925
}
926
 
927
/*-------------------------------------------------------------------
928
 * Copies data to SGLIST
929
 *-------------------------------------------------------------------*/
930
static int build_sglist (mega_host_config * megaCfg, mega_scb * scb,
931
              u_long * buffer, u_long * length)
932
{
933
  struct scatterlist *sgList;
934
  int idx;
935
 
936
  /* Scatter-gather not used */
937
  if (scb->SCpnt->use_sg == 0) {
938
    *buffer = virt_to_bus (scb->SCpnt->request_buffer);
939
    *length = (u_long) scb->SCpnt->request_bufflen;
940
    return 0;
941
  }
942
 
943
  sgList = (struct scatterlist *) scb->SCpnt->buffer;
944
  if (scb->SCpnt->use_sg == 1) {
945
    *buffer = virt_to_bus (sgList[0].address);
946
    *length = (u_long) sgList[0].length;
947
    return 0;
948
  }
949
 
950
  /* Copy Scatter-Gather list info into controller structure */
951
  for (idx = 0; idx < scb->SCpnt->use_sg; idx++) {
952
    scb->sgList[idx].address = virt_to_bus (sgList[idx].address);
953
    scb->sgList[idx].length = (u_long) sgList[idx].length;
954
  }
955
 
956
  /* Reset pointer and length fields */
957
  *buffer = virt_to_bus (scb->sgList);
958
  *length = 0;
959
 
960
  /* Return count of SG requests */
961
  return scb->SCpnt->use_sg;
962
}
963
 
964
/*--------------------------------------------------------------------
965
 * Initializes the adress of the controller's mailbox register
966
 *  The mailbox register is used to issue commands to the card.
967
 *  Format of the mailbox area:
968
 *   00 01 command
969
 *   01 01 command id
970
 *   02 02 # of sectors
971
 *   04 04 logical bus address
972
 *   08 04 physical buffer address
973
 *   0C 01 logical drive #
974
 *   0D 01 length of scatter/gather list
975
 *   0E 01 reserved
976
 *   0F 01 mailbox busy
977
 *   10 01 numstatus byte
978
 *   11 01 status byte
979
 *--------------------------------------------------------------------*/
980
static int mega_register_mailbox (mega_host_config * megaCfg, u_long paddr)
981
{
982
  /* align on 16-byte boundry */
983
  megaCfg->mbox = &megaCfg->mailbox;
984
  megaCfg->mbox = (mega_mailbox *) ((((ulong) megaCfg->mbox) + 16) & 0xfffffff0);
985
  paddr = (paddr + 16) & 0xfffffff0;
986
 
987
  /* Register mailbox area with the firmware */
988
  if (megaCfg->flag & BOARD_QUARTZ) {
989
  }
990
  else {
991
    WRITE_PORT (megaCfg->host->io_port, MBOX_PORT0, paddr & 0xFF);
992
    WRITE_PORT (megaCfg->host->io_port, MBOX_PORT1, (paddr >> 8) & 0xFF);
993
    WRITE_PORT (megaCfg->host->io_port, MBOX_PORT2, (paddr >> 16) & 0xFF);
994
    WRITE_PORT (megaCfg->host->io_port, MBOX_PORT3, (paddr >> 24) & 0xFF);
995
    WRITE_PORT (megaCfg->host->io_port, ENABLE_MBOX_REGION, ENABLE_MBOX_BYTE);
996
 
997
    CLEAR_INTR (megaCfg->host->io_port);
998
    ENABLE_INTR (megaCfg->host->io_port);
999
  }
1000
  return 0;
1001
}
1002
 
1003
/*-------------------------------------------------------------------
1004
 * Issue an adapter info query to the controller
1005
 *-------------------------------------------------------------------*/
1006
static int mega_i_query_adapter (mega_host_config * megaCfg)
1007
{
1008
  mega_RAIDINQ *adapterInfo;
1009
  mega_mailbox *mbox;
1010
  u_char mboxData[16];
1011
  u_long paddr;
1012
 
1013
  spin_lock_init (&mega_lock);
1014
  /* Initialize adapter inquiry */
1015
  paddr = virt_to_bus (megaCfg->mega_buffer);
1016
  mbox = (mega_mailbox *) mboxData;
1017
 
1018
  memset ((void *) megaCfg->mega_buffer, 0, sizeof (megaCfg->mega_buffer));
1019
  memset (mbox, 0, 16);
1020
 
1021
  /* Initialize mailbox registers */
1022
  mbox->cmd = MEGA_MBOXCMD_ADAPTERINQ;
1023
  mbox->xferaddr = paddr;
1024
 
1025
  /* Issue a blocking command to the card */
1026
  MegaIssueCmd (megaCfg, mboxData, NULL, 0);
1027
 
1028
  /* Initialize host/local structures with Adapter info */
1029
  adapterInfo = (mega_RAIDINQ *) megaCfg->mega_buffer;
1030
  megaCfg->host->max_channel = adapterInfo->AdpInfo.ChanPresent;
1031
/*  megaCfg->host->max_id = adapterInfo->AdpInfo.MaxTargPerChan; */
1032
  megaCfg->host->max_id = 9; /* max logical drives + 1 */
1033
  megaCfg->numldrv = adapterInfo->LogdrvInfo.NumLDrv;
1034
 
1035
#if 0
1036
  printk ("KERN_DEBUG ---- Logical drive info ----\n");
1037
  for (i = 0; i < megaCfg->numldrv; i++) {
1038
    printk ("%d: size: %ld prop: %x state: %x\n", i,
1039
            adapterInfo->LogdrvInfo.LDrvSize[i],
1040
            adapterInfo->LogdrvInfo.LDrvProp[i],
1041
            adapterInfo->LogdrvInfo.LDrvState[i]);
1042
  }
1043
  printk (KERN_DEBUG "---- Physical drive info ----\n");
1044
  for (i = 0; i < MAX_PHYSICAL_DRIVES; i++) {
1045
    if (i && !(i % 8))
1046
      printk ("\n");
1047
    printk ("%d: %x   ", i, adapterInfo->PhysdrvInfo.PDrvState[i]);
1048
  }
1049
  printk ("\n");
1050
#endif
1051
 
1052
  megaCfg->max_cmds = adapterInfo->AdpInfo.MaxConcCmds;
1053
 
1054
#ifdef HP                       /* use HP firmware and bios version encoding */
1055
  sprintf (megaCfg->fwVer, "%c%d%d.%d%d",
1056
           adapterInfo->AdpInfo.FwVer[2],
1057
           adapterInfo->AdpInfo.FwVer[1] >> 8,
1058
           adapterInfo->AdpInfo.FwVer[1] & 0x0f,
1059
           adapterInfo->AdpInfo.FwVer[2] >> 8,
1060
           adapterInfo->AdpInfo.FwVer[2] & 0x0f);
1061
  sprintf (megaCfg->biosVer, "%c%d%d.%d%d",
1062
           adapterInfo->AdpInfo.BiosVer[2],
1063
           adapterInfo->AdpInfo.BiosVer[1] >> 8,
1064
           adapterInfo->AdpInfo.BiosVer[1] & 0x0f,
1065
           adapterInfo->AdpInfo.BiosVer[2] >> 8,
1066
           adapterInfo->AdpInfo.BiosVer[2] & 0x0f);
1067
#else
1068
  memcpy (megaCfg->fwVer, adapterInfo->AdpInfo.FwVer, 4);
1069
  megaCfg->fwVer[4] = 0;
1070
 
1071
  memcpy (megaCfg->biosVer, adapterInfo->AdpInfo.BiosVer, 4);
1072
  megaCfg->biosVer[4] = 0;
1073
#endif
1074
 
1075
  printk (KERN_INFO "megaraid: [%s:%s] detected %d logical drives" CRLFSTR,
1076
          megaCfg->fwVer,
1077
          megaCfg->biosVer,
1078
          megaCfg->numldrv);
1079
  return 0;
1080
}
1081
 
1082
/*-------------------------------------------------------------------------
1083
 *
1084
 *                      Driver interface functions
1085
 *
1086
 *-------------------------------------------------------------------------*/
1087
 
1088
/*----------------------------------------------------------
1089
 * Returns data to be displayed in /proc/scsi/megaraid/X
1090
 *----------------------------------------------------------*/
1091
int megaraid_proc_info (char *buffer, char **start, off_t offset,
1092
                    int length, int inode, int inout)
1093
{
1094
  *start = buffer;
1095
  return 0;
1096
}
1097
 
1098
int findCard (Scsi_Host_Template * pHostTmpl,
1099
          u_short pciVendor, u_short pciDev,
1100
          long flag)
1101
{
1102
  mega_host_config *megaCfg;
1103
  struct Scsi_Host *host;
1104
  u_char pciBus, pciDevFun, megaIrq;
1105
  u_long megaBase;
1106
  u_short pciIdx = 0;
1107
 
1108
#if LINUX_VERSION_CODE < 0x20100
1109
  while (!pcibios_find_device (pciVendor, pciDev, pciIdx, &pciBus, &pciDevFun)) {
1110
    if (flag & BOARD_QUARTZ) {
1111
      u_int magic;
1112
      pcibios_read_config_dword (pciBus, pciDevFun,
1113
                                 PCI_CONF_AMISIG,
1114
                                 &magic);
1115
      if (magic != AMI_SIGNATURE) {
1116
        continue;               /* not an AMI board */
1117
      }
1118
    }
1119
#else
1120
  struct pci_dev *pdev = pci_devices;
1121
 
1122
  while ((pdev = pci_find_device (pciVendor, pciDev, pdev))) {
1123
    pciBus = pdev->bus->number;
1124
    pciDevFun = pdev->devfn;
1125
#endif
1126
    printk (KERN_INFO "megaraid: found 0x%4.04x:0x%4.04x:idx %d:bus %d:slot %d:fun %d\n",
1127
            pciVendor,
1128
            pciDev,
1129
            pciIdx, pciBus,
1130
            PCI_SLOT (pciDevFun),
1131
            PCI_FUNC (pciDevFun));
1132
 
1133
    /* Read the base port and IRQ from PCI */
1134
#if LINUX_VERSION_CODE < 0x20100
1135
    pcibios_read_config_dword (pciBus, pciDevFun,
1136
                               PCI_BASE_ADDRESS_0,
1137
                               (u_int *) & megaBase);
1138
    pcibios_read_config_byte (pciBus, pciDevFun,
1139
                              PCI_INTERRUPT_LINE,
1140
                              &megaIrq);
1141
#else
1142
    megaBase = pdev->base_address[0];
1143
    megaIrq = pdev->irq;
1144
#endif
1145
    pciIdx++;
1146
 
1147
    if (flag & BOARD_QUARTZ) {
1148
      megaBase &= PCI_BASE_ADDRESS_MEM_MASK;
1149
      megaBase = (long) ioremap (megaBase, 128);
1150
    }
1151
    else {
1152
      megaBase &= PCI_BASE_ADDRESS_IO_MASK;
1153
      megaBase += 0x10;
1154
    }
1155
 
1156
    /* Initialize SCSI Host structure */
1157
    host = scsi_register (pHostTmpl, sizeof (mega_host_config));
1158
    megaCfg = (mega_host_config *) host->hostdata;
1159
    memset (megaCfg, 0, sizeof (mega_host_config));
1160
 
1161
    printk (KERN_INFO " scsi%d: Found a MegaRAID controller at 0x%x, IRQ: %d" CRLFSTR,
1162
            host->host_no, (u_int) megaBase, megaIrq);
1163
 
1164
    /* Copy resource info into structure */
1165
    megaCfg->flag = flag;
1166
    megaCfg->host = host;
1167
    megaCfg->base = megaBase;
1168
    megaCfg->host->irq = megaIrq;
1169
    megaCfg->host->io_port = megaBase;
1170
    megaCfg->host->n_io_port = 16;
1171
    megaCfg->host->unique_id = (pciBus << 8) | pciDevFun;
1172
    megaCtlrs[numCtlrs++] = megaCfg;
1173
 
1174
    if (flag != BOARD_QUARTZ) {
1175
      /* Request our IO Range */
1176
      if (check_region (megaBase, 16)) {
1177
        printk (KERN_WARNING "megaraid: Couldn't register I/O range!" CRLFSTR);
1178
        scsi_unregister (host);
1179
        continue;
1180
      }
1181
      request_region (megaBase, 16, "megaraid");
1182
    }
1183
 
1184
    /* Request our IRQ */
1185
    if (request_irq (megaIrq, megaraid_isr, SA_SHIRQ,
1186
                     "megaraid", megaCfg)) {
1187
      printk (KERN_WARNING "megaraid: Couldn't register IRQ %d!" CRLFSTR,
1188
              megaIrq);
1189
      scsi_unregister (host);
1190
      continue;
1191
    }
1192
 
1193
    mega_register_mailbox (megaCfg, virt_to_bus ((void *) &megaCfg->mailbox));
1194
    mega_i_query_adapter (megaCfg);
1195
 
1196
    /* Initialize SCBs */
1197
    initSCB (megaCfg);
1198
 
1199
  }
1200
  return pciIdx;
1201
}
1202
 
1203
/*---------------------------------------------------------
1204
 * Detects if a megaraid controller exists in this system
1205
 *---------------------------------------------------------*/
1206
int megaraid_detect (Scsi_Host_Template * pHostTmpl)
1207
{
1208
  int count = 0;
1209
 
1210
  pHostTmpl->proc_dir = &proc_scsi_megaraid;
1211
 
1212
#if LINUX_VERSION_CODE < 0x20100
1213
  if (!pcibios_present ()) {
1214
    printk (KERN_WARNING "megaraid: PCI bios not present." CRLFSTR);
1215
    return 0;
1216
  }
1217
#endif
1218
 
1219
  count += findCard (pHostTmpl, 0x101E, 0x9010, 0);
1220
  count += findCard (pHostTmpl, 0x101E, 0x9060, 0);
1221
  count += findCard (pHostTmpl, 0x8086, 0x1960, BOARD_QUARTZ);
1222
 
1223
  return count;
1224
}
1225
 
1226
/*---------------------------------------------------------------------
1227
 * Release the controller's resources
1228
 *---------------------------------------------------------------------*/
1229
int megaraid_release (struct Scsi_Host *pSHost)
1230
{
1231
  mega_host_config *megaCfg;
1232
  mega_mailbox *mbox;
1233
  u_char mboxData[16];
1234
  int i;
1235
 
1236
  megaCfg = (mega_host_config *) pSHost->hostdata;
1237
  mbox = (mega_mailbox *) mboxData;
1238
 
1239
  /* Flush cache to disk */
1240
  memset (mbox, 0, 16);
1241
  mboxData[0] = 0xA;
1242
 
1243
  /* Issue a blocking (interrupts disabled) command to the card */
1244
  MegaIssueCmd (megaCfg, mboxData, NULL, 0);
1245
 
1246
  schedule ();
1247
 
1248
  /* Free our resources */
1249
  if (megaCfg->flag & BOARD_QUARTZ) {
1250
    iounmap ((void *) megaCfg->base);
1251
  }
1252
  else {
1253
    release_region (megaCfg->host->io_port, 16);
1254
  }
1255
  free_irq (megaCfg->host->irq, megaCfg);       /* Must be freed first, otherwise
1256
 
1257
                                                   extra interrupt is generated */
1258
  for (i = 0; i < megaCfg->max_cmds; i++) {
1259
    if (megaCfg->scbList[i].sgList)
1260
      kfree (megaCfg->scbList[i].sgList);       /* free sgList */
1261
  }
1262
  scsi_unregister (pSHost);
1263
 
1264
  return 0;
1265
}
1266
 
1267
/*----------------------------------------------
1268
 * Get information about the card/driver
1269
 *----------------------------------------------*/
1270
const char * megaraid_info (struct Scsi_Host *pSHost)
1271
{
1272
  static char buffer[512];
1273
  mega_host_config *megaCfg;
1274
  mega_RAIDINQ *adapterInfo;
1275
 
1276
  megaCfg = (mega_host_config *) pSHost->hostdata;
1277
  adapterInfo = (mega_RAIDINQ *) megaCfg->mega_buffer;
1278
 
1279
  sprintf (buffer, "AMI MegaRAID %s %d commands %d targs %d chans",
1280
           megaCfg->fwVer,
1281
           adapterInfo->AdpInfo.MaxConcCmds,
1282
           megaCfg->host->max_id,
1283
           megaCfg->host->max_channel);
1284
  return buffer;
1285
}
1286
 
1287
/*-----------------------------------------------------------------
1288
 * Perform a SCSI command
1289
 * Mailbox area:
1290
 *   00 01 command
1291
 *   01 01 command id
1292
 *   02 02 # of sectors
1293
 *   04 04 logical bus address
1294
 *   08 04 physical buffer address
1295
 *   0C 01 logical drive #
1296
 *   0D 01 length of scatter/gather list
1297
 *   0E 01 reserved
1298
 *   0F 01 mailbox busy
1299
 *   10 01 numstatus byte
1300
 *   11 01 status byte
1301
 *-----------------------------------------------------------------*/
1302
int megaraid_queue (Scsi_Cmnd * SCpnt, void (*pktComp) (Scsi_Cmnd *))
1303
{
1304
  mega_host_config *megaCfg;
1305
  mega_scb *pScb;
1306
 
1307
  megaCfg = (mega_host_config *) SCpnt->host->hostdata;
1308
 
1309
  if (!(megaCfg->flag & (1L << SCpnt->channel))) {
1310
    printk (KERN_INFO "scsi%d: scanning channel %c for devices.\n",
1311
            megaCfg->host->host_no,
1312
            SCpnt->channel + 'A');
1313
    megaCfg->flag |= (1L << SCpnt->channel);
1314
  }
1315
 
1316
  SCpnt->scsi_done = pktComp;
1317
 
1318
  /* Allocate and build a SCB request */
1319
  if ((pScb = mega_build_cmd (megaCfg, SCpnt)) != NULL) {
1320
    /* Add SCB to the head of the pending queue */
1321
    ENQUEUE (pScb, mega_scb, qPending, next);
1322
 
1323
    /* Issue the command to the card */
1324
    mega_runque (NULL);
1325
  }
1326
 
1327
  return 0;
1328
}
1329
 
1330
/*----------------------------------------------------------------------
1331
 * Issue a blocking command to the controller
1332
 *----------------------------------------------------------------------*/
1333
volatile static int internal_done_flag = 0;
1334
volatile static int internal_done_errcode = 0;
1335
 
1336
static void internal_done (Scsi_Cmnd * SCpnt)
1337
{
1338
  internal_done_errcode = SCpnt->result;
1339
  internal_done_flag++;
1340
}
1341
 
1342
/*
1343
 *      This seems dangerous in an SMP environment because
1344
 *      while spinning on internal_done_flag in 2.0.x SMP
1345
 *      no IRQ's will be taken, including those that might
1346
 *      be needed to clear this.
1347
 *
1348
 *      I think this should be using a wait queue ?
1349
 *                              -- AC
1350
 */
1351
 
1352
/*
1353
 *      I'll probably fix this in the next version, but
1354
 *      megaraid_command() will never get called since can_queue is set,
1355
 *      except maybe in a *really* old kernel in which case it's very
1356
 *      unlikely they'd be using SMP anyway.  Really this function is
1357
 *      just here for completeness.
1358
 *                              - JLJ
1359
 */
1360
 
1361
int megaraid_command (Scsi_Cmnd * SCpnt)
1362
{
1363
  internal_done_flag = 0;
1364
 
1365
  /* Queue command, and wait until it has completed */
1366
  megaraid_queue (SCpnt, internal_done);
1367
 
1368
  while (!internal_done_flag)
1369
    barrier ();
1370
 
1371
  return internal_done_errcode;
1372
}
1373
 
1374
/*---------------------------------------------------------------------
1375
 * Abort a previous SCSI request
1376
 *---------------------------------------------------------------------*/
1377
int megaraid_abort (Scsi_Cmnd * SCpnt)
1378
{
1379
  mega_host_config *megaCfg;
1380
  int idx;
1381
  long flags;
1382
 
1383
  spin_lock_irqsave (&mega_lock, flags);
1384
 
1385
  megaCfg = (mega_host_config *) SCpnt->host->hostdata;
1386
 
1387
  TRACE (("ABORT!!! %.08lx %.02x <%d.%d.%d>\n",
1388
        SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
1389
          SCpnt->lun));
1390
  /*
1391
   * Walk list of SCBs for any that are still outstanding
1392
   */
1393
  for (idx = 0; idx < megaCfg->max_cmds; idx++) {
1394
    if (megaCfg->scbList[idx].idx >= 0) {
1395
      if (megaCfg->scbList[idx].SCpnt == SCpnt) {
1396
        freeSCB (&megaCfg->scbList[idx]);
1397
 
1398
        SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24);
1399
        callDone (SCpnt);
1400
      }
1401
    }
1402
  }
1403
  spin_unlock_irqrestore (&mega_lock, flags);
1404
  return SCSI_ABORT_SNOOZE;
1405
}
1406
 
1407
/*---------------------------------------------------------------------
1408
 * Reset a previous SCSI request
1409
 *---------------------------------------------------------------------*/
1410
int megaraid_reset (Scsi_Cmnd * SCpnt, unsigned int rstflags)
1411
{
1412
  mega_host_config *megaCfg;
1413
  int idx;
1414
  long flags;
1415
 
1416
  spin_lock_irqsave (&mega_lock, flags);
1417
 
1418
  megaCfg = (mega_host_config *) SCpnt->host->hostdata;
1419
 
1420
  TRACE (("RESET: %.08lx %.02x <%d.%d.%d>\n",
1421
        SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
1422
          SCpnt->lun));
1423
 
1424
  /*
1425
   * Walk list of SCBs for any that are still outstanding
1426
   */
1427
  for (idx = 0; idx < megaCfg->max_cmds; idx++) {
1428
    if (megaCfg->scbList[idx].idx >= 0) {
1429
      SCpnt = megaCfg->scbList[idx].SCpnt;
1430
      freeSCB (&megaCfg->scbList[idx]);
1431
      SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24);
1432
      callDone (SCpnt);
1433
    }
1434
  }
1435
  spin_unlock_irqrestore (&mega_lock, flags);
1436
  return SCSI_RESET_PUNT;
1437
}
1438
 
1439
/*-------------------------------------------------------------
1440
 * Return the disk geometry for a particular disk
1441
 * Input:
1442
 *   Disk *disk - Disk geometry
1443
 *   kdev_t dev - Device node
1444
 *   int *geom  - Returns geometry fields
1445
 *     geom[0] = heads
1446
 *     geom[1] = sectors
1447
 *     geom[2] = cylinders
1448
 *-------------------------------------------------------------*/
1449
int megaraid_biosparam (Disk * disk, kdev_t dev, int *geom)
1450
{
1451
  int heads, sectors, cylinders;
1452
  mega_host_config *megaCfg;
1453
 
1454
  /* Get pointer to host config structure */
1455
  megaCfg = (mega_host_config *) disk->device->host->hostdata;
1456
 
1457
  /* Default heads (64) & sectors (32) */
1458
  heads = 64;
1459
  sectors = 32;
1460
  cylinders = disk->capacity / (heads * sectors);
1461
 
1462
  /* Handle extended translation size for logical drives > 1Gb */
1463
  if (disk->capacity >= 0x200000) {
1464
    heads = 255;
1465
    sectors = 63;
1466
    cylinders = disk->capacity / (heads * sectors);
1467
  }
1468
 
1469
  /* return result */
1470
  geom[0] = heads;
1471
  geom[1] = sectors;
1472
  geom[2] = cylinders;
1473
 
1474
  return 0;
1475
}
1476
 
1477
#ifdef MODULE
1478
Scsi_Host_Template driver_template = MEGARAID;
1479
 
1480
#include "scsi_module.c"
1481
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.