VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / drivers / scsi / aacraid / aachba.c
1 /*
2  *      Adaptec AAC series RAID controller driver
3  *      (c) Copyright 2001 Red Hat Inc. <alan@redhat.com>
4  *
5  * based on the old aacraid driver that is..
6  * Adaptec aacraid device driver for Linux.
7  *
8  * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2, or (at your option)
13  * any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; see the file COPYING.  If not, write to
22  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25
26 #include <linux/kernel.h>
27 #include <linux/init.h>
28 #include <linux/types.h>
29 #include <linux/sched.h>
30 #include <linux/pci.h>
31 #include <linux/spinlock.h>
32 #include <linux/slab.h>
33 #include <linux/completion.h>
34 #include <linux/blkdev.h>
35 #include <asm/semaphore.h>
36 #include <asm/uaccess.h>
37
38 #include <scsi/scsi.h>
39 #include <scsi/scsi_cmnd.h>
40 #include <scsi/scsi_device.h>
41 #include <scsi/scsi_host.h>
42
43 #include "aacraid.h"
44
45 /* values for inqd_pdt: Peripheral device type in plain English */
46 #define INQD_PDT_DA     0x00    /* Direct-access (DISK) device */
47 #define INQD_PDT_PROC   0x03    /* Processor device */
48 #define INQD_PDT_CHNGR  0x08    /* Changer (jukebox, scsi2) */
49 #define INQD_PDT_COMM   0x09    /* Communication device (scsi2) */
50 #define INQD_PDT_NOLUN2 0x1f    /* Unknown Device (scsi2) */
51 #define INQD_PDT_NOLUN  0x7f    /* Logical Unit Not Present */
52
53 #define INQD_PDT_DMASK  0x1F    /* Peripheral Device Type Mask */
54 #define INQD_PDT_QMASK  0xE0    /* Peripheral Device Qualifer Mask */
55
56 #define MAX_FIB_DATA (sizeof(struct hw_fib) - sizeof(FIB_HEADER))
57
58 #define MAX_DRIVER_SG_SEGMENT_COUNT 17
59
60 /*
61  *      Sense codes
62  */
63  
64 #define SENCODE_NO_SENSE                        0x00
65 #define SENCODE_END_OF_DATA                     0x00
66 #define SENCODE_BECOMING_READY                  0x04
67 #define SENCODE_INIT_CMD_REQUIRED               0x04
68 #define SENCODE_PARAM_LIST_LENGTH_ERROR         0x1A
69 #define SENCODE_INVALID_COMMAND                 0x20
70 #define SENCODE_LBA_OUT_OF_RANGE                0x21
71 #define SENCODE_INVALID_CDB_FIELD               0x24
72 #define SENCODE_LUN_NOT_SUPPORTED               0x25
73 #define SENCODE_INVALID_PARAM_FIELD             0x26
74 #define SENCODE_PARAM_NOT_SUPPORTED             0x26
75 #define SENCODE_PARAM_VALUE_INVALID             0x26
76 #define SENCODE_RESET_OCCURRED                  0x29
77 #define SENCODE_LUN_NOT_SELF_CONFIGURED_YET     0x3E
78 #define SENCODE_INQUIRY_DATA_CHANGED            0x3F
79 #define SENCODE_SAVING_PARAMS_NOT_SUPPORTED     0x39
80 #define SENCODE_DIAGNOSTIC_FAILURE              0x40
81 #define SENCODE_INTERNAL_TARGET_FAILURE         0x44
82 #define SENCODE_INVALID_MESSAGE_ERROR           0x49
83 #define SENCODE_LUN_FAILED_SELF_CONFIG          0x4c
84 #define SENCODE_OVERLAPPED_COMMAND              0x4E
85
86 /*
87  *      Additional sense codes
88  */
89  
90 #define ASENCODE_NO_SENSE                       0x00
91 #define ASENCODE_END_OF_DATA                    0x05
92 #define ASENCODE_BECOMING_READY                 0x01
93 #define ASENCODE_INIT_CMD_REQUIRED              0x02
94 #define ASENCODE_PARAM_LIST_LENGTH_ERROR        0x00
95 #define ASENCODE_INVALID_COMMAND                0x00
96 #define ASENCODE_LBA_OUT_OF_RANGE               0x00
97 #define ASENCODE_INVALID_CDB_FIELD              0x00
98 #define ASENCODE_LUN_NOT_SUPPORTED              0x00
99 #define ASENCODE_INVALID_PARAM_FIELD            0x00
100 #define ASENCODE_PARAM_NOT_SUPPORTED            0x01
101 #define ASENCODE_PARAM_VALUE_INVALID            0x02
102 #define ASENCODE_RESET_OCCURRED                 0x00
103 #define ASENCODE_LUN_NOT_SELF_CONFIGURED_YET    0x00
104 #define ASENCODE_INQUIRY_DATA_CHANGED           0x03
105 #define ASENCODE_SAVING_PARAMS_NOT_SUPPORTED    0x00
106 #define ASENCODE_DIAGNOSTIC_FAILURE             0x80
107 #define ASENCODE_INTERNAL_TARGET_FAILURE        0x00
108 #define ASENCODE_INVALID_MESSAGE_ERROR          0x00
109 #define ASENCODE_LUN_FAILED_SELF_CONFIG         0x00
110 #define ASENCODE_OVERLAPPED_COMMAND             0x00
111
112 #define BYTE0(x) (unsigned char)(x)
113 #define BYTE1(x) (unsigned char)((x) >> 8)
114 #define BYTE2(x) (unsigned char)((x) >> 16)
115 #define BYTE3(x) (unsigned char)((x) >> 24)
116
117 /*------------------------------------------------------------------------------
118  *              S T R U C T S / T Y P E D E F S
119  *----------------------------------------------------------------------------*/
120 /* SCSI inquiry data */
121 struct inquiry_data {
122         u8 inqd_pdt;    /* Peripheral qualifier | Peripheral Device Type  */
123         u8 inqd_dtq;    /* RMB | Device Type Qualifier  */
124         u8 inqd_ver;    /* ISO version | ECMA version | ANSI-approved version */
125         u8 inqd_rdf;    /* AENC | TrmIOP | Response data format */
126         u8 inqd_len;    /* Additional length (n-4) */
127         u8 inqd_pad1[2];/* Reserved - must be zero */
128         u8 inqd_pad2;   /* RelAdr | WBus32 | WBus16 |  Sync  | Linked |Reserved| CmdQue | SftRe */
129         u8 inqd_vid[8]; /* Vendor ID */
130         u8 inqd_pid[16];/* Product ID */
131         u8 inqd_prl[4]; /* Product Revision Level */
132 };
133
134 struct sense_data {
135         u8 error_code;          /* 70h (current errors), 71h(deferred errors) */
136         u8 valid:1;             /* A valid bit of one indicates that the information  */
137                                 /* field contains valid information as defined in the
138                                  * SCSI-2 Standard.
139                                  */
140         u8 segment_number;      /* Only used for COPY, COMPARE, or COPY AND VERIFY Commands */
141         u8 sense_key:4;         /* Sense Key */
142         u8 reserved:1;
143         u8 ILI:1;               /* Incorrect Length Indicator */
144         u8 EOM:1;               /* End Of Medium - reserved for random access devices */
145         u8 filemark:1;          /* Filemark - reserved for random access devices */
146
147         u8 information[4];      /* for direct-access devices, contains the unsigned 
148                                  * logical block address or residue associated with 
149                                  * the sense key 
150                                  */
151         u8 add_sense_len;       /* number of additional sense bytes to follow this field */
152         u8 cmnd_info[4];        /* not used */
153         u8 ASC;                 /* Additional Sense Code */
154         u8 ASCQ;                /* Additional Sense Code Qualifier */
155         u8 FRUC;                /* Field Replaceable Unit Code - not used */
156         u8 bit_ptr:3;           /* indicates which byte of the CDB or parameter data
157                                  * was in error
158                                  */
159         u8 BPV:1;               /* bit pointer valid (BPV): 1- indicates that 
160                                  * the bit_ptr field has valid value
161                                  */
162         u8 reserved2:2;
163         u8 CD:1;                /* command data bit: 1- illegal parameter in CDB.
164                                  * 0- illegal parameter in data.
165                                  */
166         u8 SKSV:1;
167         u8 field_ptr[2];        /* byte of the CDB or parameter data in error */
168 };
169
170 /*
171  *              M O D U L E   G L O B A L S
172  */
173  
174 static struct sense_data sense_data[MAXIMUM_NUM_CONTAINERS];
175 static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* sgmap);
176 static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg);
177 static int aac_send_srb_fib(struct scsi_cmnd* scsicmd);
178 #ifdef AAC_DETAILED_STATUS_INFO
179 static char *aac_get_status_string(u32 status);
180 #endif
181
182 /**
183  *      aac_get_containers      -       list containers
184  *      @common: adapter to probe
185  *
186  *      Make a list of all containers on this controller
187  */
188 int aac_get_containers(struct aac_dev *dev)
189 {
190         struct fsa_scsi_hba *fsa_dev_ptr;
191         u32 index; 
192         int status = 0;
193         struct aac_query_mount *dinfo;
194         struct aac_mount *dresp;
195         struct fib * fibptr;
196         unsigned instance;
197
198         fsa_dev_ptr = &(dev->fsa_dev);
199         instance = dev->scsi_host_ptr->unique_id;
200
201         if (!(fibptr = fib_alloc(dev)))
202                 return -ENOMEM;
203
204         for (index = 0; index < MAXIMUM_NUM_CONTAINERS; index++) {
205                 fib_init(fibptr);
206                 dinfo = (struct aac_query_mount *) fib_data(fibptr);
207
208                 dinfo->command = cpu_to_le32(VM_NameServe);
209                 dinfo->count = cpu_to_le32(index);
210                 dinfo->type = cpu_to_le32(FT_FILESYS);
211
212                 status = fib_send(ContainerCommand,
213                                     fibptr,
214                                     sizeof (struct aac_query_mount),
215                                     FsaNormal,
216                                     1, 1,
217                                     NULL, NULL);
218                 if (status < 0 ) {
219                         printk(KERN_WARNING "aac_get_containers: SendFIB failed.\n");
220                         break;
221                 }
222                 dresp = (struct aac_mount *)fib_data(fibptr);
223
224                 if ((le32_to_cpu(dresp->status) == ST_OK) &&
225                     (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) &&
226                     (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) {
227                         fsa_dev_ptr->valid[index] = 1;
228                         fsa_dev_ptr->type[index] = le32_to_cpu(dresp->mnt[0].vol);
229                         fsa_dev_ptr->size[index] = le32_to_cpu(dresp->mnt[0].capacity);
230                         if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY)
231                                     fsa_dev_ptr->ro[index] = 1;
232                 }
233                 fib_complete(fibptr);
234                 /*
235                  *      If there are no more containers, then stop asking.
236                  */
237                 if ((index + 1) >= le32_to_cpu(dresp->count)){
238                         break;
239                 }
240         }
241         fib_free(fibptr);
242         return status;
243 }
244
245 /**
246  *      probe_container         -       query a logical volume
247  *      @dev: device to query
248  *      @cid: container identifier
249  *
250  *      Queries the controller about the given volume. The volume information
251  *      is updated in the struct fsa_scsi_hba structure rather than returned.
252  */
253  
254 static int probe_container(struct aac_dev *dev, int cid)
255 {
256         struct fsa_scsi_hba *fsa_dev_ptr;
257         int status;
258         struct aac_query_mount *dinfo;
259         struct aac_mount *dresp;
260         struct fib * fibptr;
261         unsigned instance;
262
263         fsa_dev_ptr = &(dev->fsa_dev);
264         instance = dev->scsi_host_ptr->unique_id;
265
266         if (!(fibptr = fib_alloc(dev)))
267                 return -ENOMEM;
268
269         fib_init(fibptr);
270
271         dinfo = (struct aac_query_mount *)fib_data(fibptr);
272
273         dinfo->command = cpu_to_le32(VM_NameServe);
274         dinfo->count = cpu_to_le32(cid);
275         dinfo->type = cpu_to_le32(FT_FILESYS);
276
277         status = fib_send(ContainerCommand,
278                             fibptr,
279                             sizeof(struct aac_query_mount),
280                             FsaNormal,
281                             1, 1,
282                             NULL, NULL);
283         if (status < 0) {
284                 printk(KERN_WARNING "aacraid: probe_containers query failed.\n");
285                 goto error;
286         }
287
288         dresp = (struct aac_mount *) fib_data(fibptr);
289
290         if ((le32_to_cpu(dresp->status) == ST_OK) &&
291             (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) &&
292             (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) {
293                 fsa_dev_ptr->valid[cid] = 1;
294                 fsa_dev_ptr->type[cid] = le32_to_cpu(dresp->mnt[0].vol);
295                 fsa_dev_ptr->size[cid] = le32_to_cpu(dresp->mnt[0].capacity);
296                 if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY)
297                         fsa_dev_ptr->ro[cid] = 1;
298         }
299
300 error:
301         fib_complete(fibptr);
302         fib_free(fibptr);
303
304         return status;
305 }
306
307 /* Local Structure to set SCSI inquiry data strings */
308 struct scsi_inq {
309         char vid[8];         /* Vendor ID */
310         char pid[16];        /* Product ID */
311         char prl[4];         /* Product Revision Level */
312 };
313
314 /**
315  *      InqStrCopy      -       string merge
316  *      @a:     string to copy from
317  *      @b:     string to copy to
318  *
319  *      Copy a String from one location to another
320  *      without copying \0
321  */
322
323 static void inqstrcpy(char *a, char *b)
324 {
325
326         while(*a != (char)0) 
327                 *b++ = *a++;
328 }
329
330 static char *container_types[] = {
331         "None",
332         "Volume",
333         "Mirror",
334         "Stripe",
335         "RAID5",
336         "SSRW",
337         "SSRO",
338         "Morph",
339         "Legacy",
340         "RAID4",
341         "RAID10",             
342         "RAID00",             
343         "V-MIRRORS",          
344         "PSEUDO R4",          
345         "RAID50",
346         "Unknown"
347 };
348
349
350
351 /* Function: setinqstr
352  *
353  * Arguments: [1] pointer to void [1] int
354  *
355  * Purpose: Sets SCSI inquiry data strings for vendor, product
356  * and revision level. Allows strings to be set in platform dependent
357  * files instead of in OS dependent driver source.
358  */
359
360 static void setinqstr(int devtype, void *data, int tindex)
361 {
362         struct scsi_inq *str;
363         char *findit;
364         struct aac_driver_ident *mp;
365
366         mp = aac_get_driver_ident(devtype);
367    
368         str = (struct scsi_inq *)(data); /* cast data to scsi inq block */
369
370         inqstrcpy (mp->vname, str->vid); 
371         inqstrcpy (mp->model, str->pid); /* last six chars reserved for vol type */
372
373         findit = str->pid;
374
375         for ( ; *findit != ' '; findit++); /* walk till we find a space then incr by 1 */
376                 findit++;
377         
378         if (tindex < (sizeof(container_types)/sizeof(char *))){
379                 inqstrcpy (container_types[tindex], findit);
380         }
381         inqstrcpy ("V1.0", str->prl);
382 }
383
384 void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code,
385                     u8 a_sense_code, u8 incorrect_length,
386                     u8 bit_pointer, u16 field_pointer,
387                     u32 residue)
388 {
389         sense_buf[0] = 0xF0;    /* Sense data valid, err code 70h (current error) */
390         sense_buf[1] = 0;       /* Segment number, always zero */
391
392         if (incorrect_length) {
393                 sense_buf[2] = sense_key | 0x20;/* Set ILI bit | sense key */
394                 sense_buf[3] = BYTE3(residue);
395                 sense_buf[4] = BYTE2(residue);
396                 sense_buf[5] = BYTE1(residue);
397                 sense_buf[6] = BYTE0(residue);
398         } else
399                 sense_buf[2] = sense_key;       /* Sense key */
400
401         if (sense_key == ILLEGAL_REQUEST)
402                 sense_buf[7] = 10;      /* Additional sense length */
403         else
404                 sense_buf[7] = 6;       /* Additional sense length */
405
406         sense_buf[12] = sense_code;     /* Additional sense code */
407         sense_buf[13] = a_sense_code;   /* Additional sense code qualifier */
408         if (sense_key == ILLEGAL_REQUEST) {
409                 sense_buf[15] = 0;
410
411                 if (sense_code == SENCODE_INVALID_PARAM_FIELD)
412                         sense_buf[15] = 0x80;/* Std sense key specific field */
413                 /* Illegal parameter is in the parameter block */
414
415                 if (sense_code == SENCODE_INVALID_CDB_FIELD)
416                         sense_buf[15] = 0xc0;/* Std sense key specific field */
417                 /* Illegal parameter is in the CDB block */
418                 sense_buf[15] |= bit_pointer;
419                 sense_buf[16] = field_pointer >> 8;     /* MSB */
420                 sense_buf[17] = field_pointer;          /* LSB */
421         }
422 }
423
424 static void aac_io_done(struct scsi_cmnd * scsicmd)
425 {
426         unsigned long cpu_flags;
427         struct Scsi_Host *host = scsicmd->device->host;
428         spin_lock_irqsave(host->host_lock, cpu_flags);
429         scsicmd->scsi_done(scsicmd);
430         spin_unlock_irqrestore(host->host_lock, cpu_flags);
431 }
432
433 static void __aac_io_done(struct scsi_cmnd * scsicmd)
434 {
435         scsicmd->scsi_done(scsicmd);
436 }
437
438 int aac_get_adapter_info(struct aac_dev* dev)
439 {
440         struct fib* fibptr;
441         struct aac_adapter_info* info;
442         int rcode;
443         u32 tmp;
444         if (!(fibptr = fib_alloc(dev)))
445                 return -ENOMEM;
446
447         fib_init(fibptr);
448         info = (struct aac_adapter_info*) fib_data(fibptr);
449
450         memset(info,0,sizeof(struct aac_adapter_info));
451
452         rcode = fib_send(RequestAdapterInfo,
453                         fibptr, 
454                         sizeof(struct aac_adapter_info),
455                         FsaNormal, 
456                         1, 1, 
457                         NULL, 
458                         NULL);
459
460         memcpy(&dev->adapter_info, info, sizeof(struct aac_adapter_info));
461
462         tmp = dev->adapter_info.kernelrev;
463         printk(KERN_INFO"%s%d: kernel %d.%d.%d build %d\n", 
464                         dev->name, dev->id,
465                         tmp>>24,(tmp>>16)&0xff,(tmp>>8)&0xff,
466                         dev->adapter_info.kernelbuild);
467         tmp = dev->adapter_info.monitorrev;
468         printk(KERN_INFO"%s%d: monitor %d.%d.%d build %d\n", 
469                         dev->name, dev->id,
470                         tmp>>24,(tmp>>16)&0xff,(tmp>>8)&0xff,
471                         dev->adapter_info.monitorbuild);
472         tmp = dev->adapter_info.biosrev;
473         printk(KERN_INFO"%s%d: bios %d.%d.%d build %d\n", 
474                         dev->name, dev->id,
475                         tmp>>24,(tmp>>16)&0xff,(tmp>>8)&0xff,
476                         dev->adapter_info.biosbuild);
477         printk(KERN_INFO"%s%d: serial %x%x\n",
478                         dev->name, dev->id,
479                         dev->adapter_info.serial[0],
480                         dev->adapter_info.serial[1]);
481
482         dev->nondasd_support = 0;
483         if(dev->adapter_info.options & AAC_OPT_NONDASD){
484 //              dev->nondasd_support = 1;
485 // dmb - temporarily disable nondasd
486         }
487         if(nondasd != -1) {  
488                 dev->nondasd_support = (nondasd!=0);
489         }
490         if(dev->nondasd_support != 0){
491                 printk(KERN_INFO "%s%d: Non-DASD support enabled.\n",dev->name, dev->id);
492         }
493
494         dev->pae_support = 0;
495         if( (sizeof(dma_addr_t) > 4) && (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)){
496                 printk(KERN_INFO "%s%d: 64bit support enabled.\n", dev->name, dev->id);
497                 dev->pae_support = 1;
498         }
499
500         if(paemode != -1){
501                 dev->pae_support = (paemode!=0);
502         }
503         if(dev->pae_support != 0) {
504                 printk(KERN_INFO"%s%d: 64 Bit PAE enabled\n", dev->name, dev->id);
505                 pci_set_dma_mask(dev->pdev, (dma_addr_t)0xFFFFFFFFFFFFFFFFULL);
506         }
507
508         fib_complete(fibptr);
509         fib_free(fibptr);
510
511         return rcode;
512 }
513
514
515 static void read_callback(void *context, struct fib * fibptr)
516 {
517         struct aac_dev *dev;
518         struct aac_read_reply *readreply;
519         struct scsi_cmnd *scsicmd;
520         u32 lba;
521         u32 cid;
522
523         scsicmd = (struct scsi_cmnd *) context;
524
525         dev = (struct aac_dev *)scsicmd->device->host->hostdata;
526         cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun);
527
528         lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
529         dprintk((KERN_DEBUG "read_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies));
530
531         if (fibptr == NULL)
532                 BUG();
533                 
534         if(scsicmd->use_sg)
535                 pci_unmap_sg(dev->pdev, 
536                         (struct scatterlist *)scsicmd->buffer,
537                         scsicmd->use_sg,
538                         scsicmd->sc_data_direction);
539         else if(scsicmd->request_bufflen)
540                 pci_unmap_single(dev->pdev, (dma_addr_t)(ulong)scsicmd->SCp.ptr,
541                                  scsicmd->request_bufflen,
542                                  scsicmd->sc_data_direction);
543         readreply = (struct aac_read_reply *)fib_data(fibptr);
544         if (le32_to_cpu(readreply->status) == ST_OK)
545                 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
546         else {
547                 printk(KERN_WARNING "read_callback: read failed, status = %d\n", readreply->status);
548                 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
549                 set_sense((u8 *) &sense_data[cid],
550                                     HARDWARE_ERROR,
551                                     SENCODE_INTERNAL_TARGET_FAILURE,
552                                     ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
553                                     0, 0);
554                 memcpy(scsicmd->sense_buffer, &sense_data[cid], sizeof(struct sense_data));
555         }
556         fib_complete(fibptr);
557         fib_free(fibptr);
558
559         aac_io_done(scsicmd);
560 }
561
562 static void write_callback(void *context, struct fib * fibptr)
563 {
564         struct aac_dev *dev;
565         struct aac_write_reply *writereply;
566         struct scsi_cmnd *scsicmd;
567         u32 lba;
568         u32 cid;
569
570         scsicmd = (struct scsi_cmnd *) context;
571         dev = (struct aac_dev *)scsicmd->device->host->hostdata;
572         cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun);
573
574         lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
575         dprintk((KERN_DEBUG "write_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies));
576         if (fibptr == NULL)
577                 BUG();
578
579         if(scsicmd->use_sg)
580                 pci_unmap_sg(dev->pdev, 
581                         (struct scatterlist *)scsicmd->buffer,
582                         scsicmd->use_sg,
583                         scsicmd->sc_data_direction);
584         else if(scsicmd->request_bufflen)
585                 pci_unmap_single(dev->pdev, (dma_addr_t)(ulong)scsicmd->SCp.ptr,
586                                  scsicmd->request_bufflen,
587                                  scsicmd->sc_data_direction);
588
589         writereply = (struct aac_write_reply *) fib_data(fibptr);
590         if (le32_to_cpu(writereply->status) == ST_OK)
591                 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
592         else {
593                 printk(KERN_WARNING "write_callback: write failed, status = %d\n", writereply->status);
594                 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
595                 set_sense((u8 *) &sense_data[cid],
596                                     HARDWARE_ERROR,
597                                     SENCODE_INTERNAL_TARGET_FAILURE,
598                                     ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
599                                     0, 0);
600                 memcpy(scsicmd->sense_buffer, &sense_data[cid], sizeof(struct sense_data));
601         }
602
603         fib_complete(fibptr);
604         fib_free(fibptr);
605         aac_io_done(scsicmd);
606 }
607
608 int aac_read(struct scsi_cmnd * scsicmd, int cid)
609 {
610         u32 lba;
611         u32 count;
612         int status;
613
614         u16 fibsize;
615         struct aac_dev *dev;
616         struct fib * cmd_fibcontext;
617
618         dev = (struct aac_dev *)scsicmd->device->host->hostdata;
619         /*
620          *      Get block address and transfer length
621          */
622         if (scsicmd->cmnd[0] == READ_6) /* 6 byte command */
623         {
624                 dprintk((KERN_DEBUG "aachba: received a read(6) command on id %d.\n", cid));
625
626                 lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
627                 count = scsicmd->cmnd[4];
628
629                 if (count == 0)
630                         count = 256;
631         } else {
632                 dprintk((KERN_DEBUG "aachba: received a read(10) command on id %d.\n", cid));
633
634                 lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
635                 count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
636         }
637         dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies));
638         /*
639          *      Alocate and initialize a Fib
640          */
641         if (!(cmd_fibcontext = fib_alloc(dev))) {
642                 return -1;
643         }
644
645         fib_init(cmd_fibcontext);
646
647         if(dev->pae_support == 1){
648                 struct aac_read64 *readcmd;
649                 readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext);
650                 readcmd->command = cpu_to_le32(VM_CtHostRead64);
651                 readcmd->cid = cpu_to_le16(cid);
652                 readcmd->sector_count = cpu_to_le16(count);
653                 readcmd->block = cpu_to_le32(lba);
654                 readcmd->pad   = cpu_to_le16(0);
655                 readcmd->flags = cpu_to_le16(0); 
656
657                 aac_build_sg64(scsicmd, &readcmd->sg);
658                 if(readcmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT)
659                         BUG();
660                 fibsize = sizeof(struct aac_read64) + ((readcmd->sg.count - 1) * sizeof (struct sgentry64));
661                 /*
662                  *      Now send the Fib to the adapter
663                  */
664                 status = fib_send(ContainerCommand64, 
665                           cmd_fibcontext, 
666                           fibsize, 
667                           FsaNormal, 
668                           0, 1, 
669                           (fib_callback) read_callback, 
670                           (void *) scsicmd);
671         } else {
672                 struct aac_read *readcmd;
673                 readcmd = (struct aac_read *) fib_data(cmd_fibcontext);
674                 readcmd->command = cpu_to_le32(VM_CtBlockRead);
675                 readcmd->cid = cpu_to_le32(cid);
676                 readcmd->block = cpu_to_le32(lba);
677                 readcmd->count = cpu_to_le32(count * 512);
678
679                 if (count * 512 > (64 * 1024))
680                         BUG();
681
682                 aac_build_sg(scsicmd, &readcmd->sg);
683                 if(readcmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT)
684                         BUG();
685                 fibsize = sizeof(struct aac_read) + ((readcmd->sg.count - 1) * sizeof (struct sgentry));
686                 /*
687                  *      Now send the Fib to the adapter
688                  */
689                 status = fib_send(ContainerCommand, 
690                           cmd_fibcontext, 
691                           fibsize, 
692                           FsaNormal, 
693                           0, 1, 
694                           (fib_callback) read_callback, 
695                           (void *) scsicmd);
696         }
697
698         
699
700         /*
701          *      Check that the command queued to the controller
702          */
703         if (status == -EINPROGRESS) 
704         {
705                 dprintk("read queued.\n");
706                 return 0;
707         }
708                 
709         printk(KERN_WARNING "aac_read: fib_send failed with status: %d.\n", status);
710         /*
711          *      For some reason, the Fib didn't queue, return QUEUE_FULL
712          */
713         scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL;
714         aac_io_done(scsicmd);
715         fib_complete(cmd_fibcontext);
716         fib_free(cmd_fibcontext);
717         return -1;
718 }
719
720 static int aac_write(struct scsi_cmnd * scsicmd, int cid)
721 {
722         u32 lba;
723         u32 count;
724         int status;
725         u16 fibsize;
726         struct aac_dev *dev;
727         struct fib * cmd_fibcontext;
728
729         dev = (struct aac_dev *)scsicmd->device->host->hostdata;
730         /*
731          *      Get block address and transfer length
732          */
733         if (scsicmd->cmnd[0] == WRITE_6)        /* 6 byte command */
734         {
735                 lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
736                 count = scsicmd->cmnd[4];
737                 if (count == 0)
738                         count = 256;
739         } else {
740                 dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", cid));
741                 lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
742                 count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
743         }
744         dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies));
745         /*
746          *      Allocate and initialize a Fib then setup a BlockWrite command
747          */
748         if (!(cmd_fibcontext = fib_alloc(dev))) {
749                 scsicmd->result = DID_ERROR << 16;
750                 aac_io_done(scsicmd);
751                 return -1;
752         }
753         fib_init(cmd_fibcontext);
754
755         if(dev->pae_support == 1){
756                 struct aac_write64 *writecmd;
757                 writecmd = (struct aac_write64 *) fib_data(cmd_fibcontext);
758                 writecmd->command = cpu_to_le32(VM_CtHostWrite64);
759                 writecmd->cid = cpu_to_le16(cid);
760                 writecmd->sector_count = cpu_to_le16(count); 
761                 writecmd->block = cpu_to_le32(lba);
762                 writecmd->pad   = cpu_to_le16(0);
763                 writecmd->flags = cpu_to_le16(0);
764
765                 aac_build_sg64(scsicmd, &writecmd->sg);
766                 if(writecmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT)
767                         BUG();
768                 fibsize = sizeof(struct aac_write64) + ((writecmd->sg.count - 1) * sizeof (struct sgentry64));
769                 /*
770                  *      Now send the Fib to the adapter
771                  */
772                 status = fib_send(ContainerCommand64, 
773                           cmd_fibcontext, 
774                           fibsize, 
775                           FsaNormal, 
776                           0, 1, 
777                           (fib_callback) write_callback, 
778                           (void *) scsicmd);
779         } else {
780                 struct aac_write *writecmd;
781                 writecmd = (struct aac_write *) fib_data(cmd_fibcontext);
782                 writecmd->command = cpu_to_le32(VM_CtBlockWrite);
783                 writecmd->cid = cpu_to_le32(cid);
784                 writecmd->block = cpu_to_le32(lba);
785                 writecmd->count = cpu_to_le32(count * 512);
786                 writecmd->sg.count = cpu_to_le32(1);
787                 /* ->stable is not used - it did mean which type of write */
788
789                 if (count * 512 > (64 * 1024)) {
790                         BUG();
791                 }
792
793                 aac_build_sg(scsicmd, &writecmd->sg);
794                 if(writecmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT)
795                         BUG();
796                 fibsize = sizeof(struct aac_write) + ((writecmd->sg.count - 1) * sizeof (struct sgentry));
797                 /*
798                  *      Now send the Fib to the adapter
799                  */
800                 status = fib_send(ContainerCommand, 
801                           cmd_fibcontext, 
802                           fibsize, 
803                           FsaNormal, 
804                           0, 1, 
805                           (fib_callback) write_callback, 
806                           (void *) scsicmd);
807         }
808
809         /*
810          *      Check that the command queued to the controller
811          */
812         if (status == -EINPROGRESS)
813         {
814                 dprintk("write queued.\n");
815                 return 0;
816         }
817
818         printk(KERN_WARNING "aac_write: fib_send failed with status: %d\n", status);
819         /*
820          *      For some reason, the Fib didn't queue, return QUEUE_FULL
821          */
822         scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL;
823         aac_io_done(scsicmd);
824
825         fib_complete(cmd_fibcontext);
826         fib_free(cmd_fibcontext);
827         return -1;
828 }
829
830
831 /**
832  *      aac_scsi_cmd()          -       Process SCSI command
833  *      @scsicmd:               SCSI command block
834  *
835  *      Emulate a SCSI command and queue the required request for the
836  *      aacraid firmware.
837  */
838  
839 int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
840 {
841         u32 cid = 0;
842         int ret;
843         struct Scsi_Host *host = scsicmd->device->host;
844         struct aac_dev *dev = (struct aac_dev *)host->hostdata;
845         struct fsa_scsi_hba *fsa_dev_ptr = &dev->fsa_dev;
846         int cardtype = dev->cardtype;
847         
848         /*
849          *      If the bus, id or lun is out of range, return fail
850          *      Test does not apply to ID 16, the pseudo id for the controller
851          *      itself.
852          */
853         if (scsicmd->device->id != host->this_id) {
854                 if ((scsicmd->device->channel == 0) ){
855                         if( (scsicmd->device->id >= MAXIMUM_NUM_CONTAINERS) || (scsicmd->device->lun != 0)){ 
856                                 scsicmd->result = DID_NO_CONNECT << 16;
857                                 __aac_io_done(scsicmd);
858                                 return 0;
859                         }
860                         cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun);
861
862                         /*
863                          *      If the target container doesn't exist, it may have
864                          *      been newly created
865                          */
866                         if (fsa_dev_ptr->valid[cid] == 0) {
867                                 switch (scsicmd->cmnd[0]) {
868                                 case INQUIRY:
869                                 case READ_CAPACITY:
870                                 case TEST_UNIT_READY:
871                                         spin_unlock_irq(host->host_lock);
872                                         probe_container(dev, cid);
873                                         spin_lock_irq(host->host_lock);
874                                         if (fsa_dev_ptr->valid[cid] == 0) {
875                                                 scsicmd->result = DID_NO_CONNECT << 16;
876                                                 __aac_io_done(scsicmd);
877                                                 return 0;
878                                         }
879                                 default:
880                                         break;
881                                 }
882                         }
883                         /*
884                          *      If the target container still doesn't exist, 
885                          *      return failure
886                          */
887                         if (fsa_dev_ptr->valid[cid] == 0) {
888                                 scsicmd->result = DID_BAD_TARGET << 16;
889                                 __aac_io_done(scsicmd);
890                                 return 0;
891                         }
892                 } else {  /* check for physical non-dasd devices */
893                         if(dev->nondasd_support == 1){
894                                 return aac_send_srb_fib(scsicmd);
895                         } else {
896                                 scsicmd->result = DID_NO_CONNECT << 16;
897                                 __aac_io_done(scsicmd);
898                                 return 0;
899                         }
900                 }
901         }
902         /*
903          * else Command for the controller itself
904          */
905         else if ((scsicmd->cmnd[0] != INQUIRY) &&       /* only INQUIRY & TUR cmnd supported for controller */
906                 (scsicmd->cmnd[0] != TEST_UNIT_READY)) 
907         {
908                 dprintk((KERN_WARNING "Only INQUIRY & TUR command supported for controller, rcvd = 0x%x.\n", scsicmd->cmnd[0]));
909                 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
910                 set_sense((u8 *) &sense_data[cid],
911                             ILLEGAL_REQUEST,
912                             SENCODE_INVALID_COMMAND,
913                             ASENCODE_INVALID_COMMAND, 0, 0, 0, 0);
914                 __aac_io_done(scsicmd);
915                 memcpy(scsicmd->sense_buffer, &sense_data[cid], sizeof(struct sense_data));
916                 return 0;
917         }
918
919
920         /* Handle commands here that don't really require going out to the adapter */
921         switch (scsicmd->cmnd[0]) {
922         case INQUIRY:
923         {
924                 struct inquiry_data *inq_data_ptr;
925
926                 dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scsicmd->device->id));
927                 inq_data_ptr = (struct inquiry_data *)scsicmd->request_buffer;
928                 memset(inq_data_ptr, 0, sizeof (struct inquiry_data));
929
930                 inq_data_ptr->inqd_ver = 2;     /* claim compliance to SCSI-2 */
931                 inq_data_ptr->inqd_dtq = 0x80;  /* set RMB bit to one indicating that the medium is removable */
932                 inq_data_ptr->inqd_rdf = 2;     /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */
933                 inq_data_ptr->inqd_len = 31;
934                 /*Format for "pad2" is  RelAdr | WBus32 | WBus16 |  Sync  | Linked |Reserved| CmdQue | SftRe */
935                 inq_data_ptr->inqd_pad2= 0x32 ;  /*WBus16|Sync|CmdQue */
936                 /*
937                  *      Set the Vendor, Product, and Revision Level
938                  *      see: <vendor>.c i.e. aac.c
939                  */
940                 setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), fsa_dev_ptr->type[cid]);
941                 if (scsicmd->device->id == host->this_id)
942                         inq_data_ptr->inqd_pdt = INQD_PDT_PROC; /* Processor device */
943                 else
944                         inq_data_ptr->inqd_pdt = INQD_PDT_DA;   /* Direct/random access device */
945                 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
946                 __aac_io_done(scsicmd);
947                 return 0;
948         }
949         case READ_CAPACITY:
950         {
951                 int capacity;
952                 char *cp;
953
954                 dprintk((KERN_DEBUG "READ CAPACITY command.\n"));
955                 capacity = fsa_dev_ptr->size[cid] - 1;
956                 cp = scsicmd->request_buffer;
957                 cp[0] = (capacity >> 24) & 0xff;
958                 cp[1] = (capacity >> 16) & 0xff;
959                 cp[2] = (capacity >> 8) & 0xff;
960                 cp[3] = (capacity >> 0) & 0xff;
961                 cp[4] = 0;
962                 cp[5] = 0;
963                 cp[6] = 2;
964                 cp[7] = 0;
965
966                 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
967                 __aac_io_done(scsicmd);
968
969                 return 0;
970         }
971
972         case MODE_SENSE:
973         {
974                 char *mode_buf;
975
976                 dprintk((KERN_DEBUG "MODE SENSE command.\n"));
977                 mode_buf = scsicmd->request_buffer;
978                 mode_buf[0] = 3;        /* Mode data length */
979                 mode_buf[1] = 0;        /* Medium type - default */
980                 mode_buf[2] = 0;        /* Device-specific param, bit 8: 0/1 = write enabled/protected */
981                 mode_buf[3] = 0;        /* Block descriptor length */
982
983                 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
984                 __aac_io_done(scsicmd);
985
986                 return 0;
987         }
988         case MODE_SENSE_10:
989         {
990                 char *mode_buf;
991
992                 dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n"));
993                 mode_buf = scsicmd->request_buffer;
994                 mode_buf[0] = 0;        /* Mode data length (MSB) */
995                 mode_buf[1] = 6;        /* Mode data length (LSB) */
996                 mode_buf[2] = 0;        /* Medium type - default */
997                 mode_buf[3] = 0;        /* Device-specific param, bit 8: 0/1 = write enabled/protected */
998                 mode_buf[4] = 0;        /* reserved */
999                 mode_buf[5] = 0;        /* reserved */
1000                 mode_buf[6] = 0;        /* Block descriptor length (MSB) */
1001                 mode_buf[7] = 0;        /* Block descriptor length (LSB) */
1002
1003                 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
1004                 __aac_io_done(scsicmd);
1005
1006                 return 0;
1007         }
1008         case REQUEST_SENSE:
1009                 dprintk((KERN_DEBUG "REQUEST SENSE command.\n"));
1010                 memcpy(scsicmd->sense_buffer, &sense_data[cid], sizeof (struct sense_data));
1011                 memset(&sense_data[cid], 0, sizeof (struct sense_data));
1012                 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
1013                 __aac_io_done(scsicmd);
1014                 return 0;
1015
1016         case ALLOW_MEDIUM_REMOVAL:
1017                 dprintk((KERN_DEBUG "LOCK command.\n"));
1018                 if (scsicmd->cmnd[4])
1019                         fsa_dev_ptr->locked[cid] = 1;
1020                 else
1021                         fsa_dev_ptr->locked[cid] = 0;
1022
1023                 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
1024                 __aac_io_done(scsicmd);
1025                 return 0;
1026         /*
1027          *      These commands are all No-Ops
1028          */
1029         case TEST_UNIT_READY:
1030         case RESERVE:
1031         case RELEASE:
1032         case REZERO_UNIT:
1033         case REASSIGN_BLOCKS:
1034         case SEEK_10:
1035         case START_STOP:
1036                 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
1037                 __aac_io_done(scsicmd);
1038                 return 0;
1039         }
1040
1041         switch (scsicmd->cmnd[0]) 
1042         {
1043                 case READ_6:
1044                 case READ_10:
1045                         /*
1046                          *      Hack to keep track of ordinal number of the device that
1047                          *      corresponds to a container. Needed to convert
1048                          *      containers to /dev/sd device names
1049                          */
1050                          
1051                         spin_unlock_irq(host->host_lock);
1052                         if  (scsicmd->request->rq_disk)
1053                                 memcpy(fsa_dev_ptr->devname[cid],
1054                                         scsicmd->request->rq_disk->disk_name,
1055                                         8);
1056
1057                         ret = aac_read(scsicmd, cid);
1058                         spin_lock_irq(host->host_lock);
1059                         return ret;
1060
1061                 case WRITE_6:
1062                 case WRITE_10:
1063                         spin_unlock_irq(host->host_lock);
1064                         ret = aac_write(scsicmd, cid);
1065                         spin_lock_irq(host->host_lock);
1066                         return ret;
1067                 default:
1068                         /*
1069                          *      Unhandled commands
1070                          */
1071                         printk(KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", scsicmd->cmnd[0]);
1072                         scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
1073                         set_sense((u8 *) &sense_data[cid],
1074                                 ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND,
1075                         ASENCODE_INVALID_COMMAND, 0, 0, 0, 0);
1076                         memcpy(scsicmd->sense_buffer, &sense_data[cid],
1077                                 sizeof(struct sense_data));
1078                         __aac_io_done(scsicmd);
1079                         return 0;
1080         }
1081 }
1082
1083 static int query_disk(struct aac_dev *dev, void __user *arg)
1084 {
1085         struct aac_query_disk qd;
1086         struct fsa_scsi_hba *fsa_dev_ptr;
1087
1088         fsa_dev_ptr = &(dev->fsa_dev);
1089         if (copy_from_user(&qd, arg, sizeof (struct aac_query_disk)))
1090                 return -EFAULT;
1091         if (qd.cnum == -1)
1092                 qd.cnum = ID_LUN_TO_CONTAINER(qd.id, qd.lun);
1093         else if ((qd.bus == -1) && (qd.id == -1) && (qd.lun == -1)) 
1094         {
1095                 if (qd.cnum < 0 || qd.cnum >= MAXIMUM_NUM_CONTAINERS)
1096                         return -EINVAL;
1097                 qd.instance = dev->scsi_host_ptr->host_no;
1098                 qd.bus = 0;
1099                 qd.id = CONTAINER_TO_ID(qd.cnum);
1100                 qd.lun = CONTAINER_TO_LUN(qd.cnum);
1101         }
1102         else return -EINVAL;
1103
1104         qd.valid = fsa_dev_ptr->valid[qd.cnum];
1105         qd.locked = fsa_dev_ptr->locked[qd.cnum];
1106         qd.deleted = fsa_dev_ptr->deleted[qd.cnum];
1107
1108         if (fsa_dev_ptr->devname[qd.cnum][0] == '\0')
1109                 qd.unmapped = 1;
1110         else
1111                 qd.unmapped = 0;
1112
1113         strlcpy(qd.name, fsa_dev_ptr->devname[qd.cnum], sizeof(qd.name));
1114
1115         if (copy_to_user(arg, &qd, sizeof (struct aac_query_disk)))
1116                 return -EFAULT;
1117         return 0;
1118 }
1119
1120 static int force_delete_disk(struct aac_dev *dev, void __user *arg)
1121 {
1122         struct aac_delete_disk dd;
1123         struct fsa_scsi_hba *fsa_dev_ptr;
1124
1125         fsa_dev_ptr = &(dev->fsa_dev);
1126
1127         if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk)))
1128                 return -EFAULT;
1129
1130         if (dd.cnum >= MAXIMUM_NUM_CONTAINERS)
1131                 return -EINVAL;
1132         /*
1133          *      Mark this container as being deleted.
1134          */
1135         fsa_dev_ptr->deleted[dd.cnum] = 1;
1136         /*
1137          *      Mark the container as no longer valid
1138          */
1139         fsa_dev_ptr->valid[dd.cnum] = 0;
1140         return 0;
1141 }
1142
1143 static int delete_disk(struct aac_dev *dev, void __user *arg)
1144 {
1145         struct aac_delete_disk dd;
1146         struct fsa_scsi_hba *fsa_dev_ptr;
1147
1148         fsa_dev_ptr = &(dev->fsa_dev);
1149
1150         if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk)))
1151                 return -EFAULT;
1152
1153         if (dd.cnum >= MAXIMUM_NUM_CONTAINERS)
1154                 return -EINVAL;
1155         /*
1156          *      If the container is locked, it can not be deleted by the API.
1157          */
1158         if (fsa_dev_ptr->locked[dd.cnum])
1159                 return -EBUSY;
1160         else {
1161                 /*
1162                  *      Mark the container as no longer being valid.
1163                  */
1164                 fsa_dev_ptr->valid[dd.cnum] = 0;
1165                 fsa_dev_ptr->devname[dd.cnum][0] = '\0';
1166                 return 0;
1167         }
1168 }
1169
1170 int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg)
1171 {
1172         switch (cmd) {
1173         case FSACTL_QUERY_DISK:
1174                 return query_disk(dev, arg);
1175         case FSACTL_DELETE_DISK:
1176                 return delete_disk(dev, arg);
1177         case FSACTL_FORCE_DELETE_DISK:
1178                 return force_delete_disk(dev, arg);
1179         case FSACTL_GET_CONTAINERS:
1180                 return aac_get_containers(dev);
1181         default:
1182                 return -ENOTTY;
1183         }
1184 }
1185
1186 /**
1187  *
1188  * aac_srb_callback
1189  * @context: the context set in the fib - here it is scsi cmd
1190  * @fibptr: pointer to the fib
1191  *
1192  * Handles the completion of a scsi command to a non dasd device
1193  *
1194  */
1195
1196 static void aac_srb_callback(void *context, struct fib * fibptr)
1197 {
1198         struct aac_dev *dev;
1199         struct aac_srb_reply *srbreply;
1200         struct scsi_cmnd *scsicmd;
1201
1202         scsicmd = (struct scsi_cmnd *) context;
1203         dev = (struct aac_dev *)scsicmd->device->host->hostdata;
1204
1205         if (fibptr == NULL)
1206                 BUG();
1207
1208         srbreply = (struct aac_srb_reply *) fib_data(fibptr);
1209
1210         scsicmd->sense_buffer[0] = '\0';  /* Initialize sense valid flag to false */
1211         /*
1212          *      Calculate resid for sg 
1213          */
1214          
1215         scsicmd->resid = scsicmd->request_bufflen - srbreply->data_xfer_length;
1216
1217         if(scsicmd->use_sg)
1218                 pci_unmap_sg(dev->pdev, 
1219                         (struct scatterlist *)scsicmd->buffer,
1220                         scsicmd->use_sg,
1221                         scsicmd->sc_data_direction);
1222         else if(scsicmd->request_bufflen)
1223                 pci_unmap_single(dev->pdev, (ulong)scsicmd->SCp.ptr, scsicmd->request_bufflen,
1224                         scsicmd->sc_data_direction);
1225
1226         /*
1227          * First check the fib status
1228          */
1229
1230         if (le32_to_cpu(srbreply->status) != ST_OK){
1231                 int len;
1232                 printk(KERN_WARNING "aac_srb_callback: srb failed, status = %d\n", le32_to_cpu(srbreply->status));
1233                 len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))?
1234                                 sizeof(scsicmd->sense_buffer):srbreply->sense_data_size;
1235                 scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
1236                 memcpy(scsicmd->sense_buffer, srbreply->sense_data, len);
1237         }
1238
1239         /*
1240          * Next check the srb status
1241          */
1242         switch( (le32_to_cpu(srbreply->srb_status))&0x3f){
1243         case SRB_STATUS_ERROR_RECOVERY:
1244         case SRB_STATUS_PENDING:
1245         case SRB_STATUS_SUCCESS:
1246                 if(scsicmd->cmnd[0] == INQUIRY ){
1247                         u8 b;
1248                         u8 b1;
1249                         /* We can't expose disk devices because we can't tell whether they
1250                          * are the raw container drives or stand alone drives.  If they have
1251                          * the removable bit set then we should expose them though.
1252                          */
1253                         b = (*(u8*)scsicmd->buffer)&0x1f;
1254                         b1 = ((u8*)scsicmd->buffer)[1];
1255                         if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER 
1256                                         || (b==TYPE_DISK && (b1&0x80)) ){
1257                                 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
1258                         } else {
1259                                 scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8;
1260                         }
1261                 } else {
1262                         scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
1263                 }
1264                 break;
1265         case SRB_STATUS_DATA_OVERRUN:
1266                 switch(scsicmd->cmnd[0]){
1267                 case  READ_6:
1268                 case  WRITE_6:
1269                 case  READ_10:
1270                 case  WRITE_10:
1271                 case  READ_12:
1272                 case  WRITE_12:
1273                         if(le32_to_cpu(srbreply->data_xfer_length) < scsicmd->underflow ) {
1274                                 printk(KERN_WARNING"aacraid: SCSI CMD underflow\n");
1275                         } else {
1276                                 printk(KERN_WARNING"aacraid: SCSI CMD Data Overrun\n");
1277                         }
1278                         scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
1279                         break;
1280                 case INQUIRY: {
1281                         u8 b;
1282                         u8 b1;
1283                         /* We can't expose disk devices because we can't tell whether they
1284                         * are the raw container drives or stand alone drives
1285                         */
1286                         b = (*(u8*)scsicmd->buffer)&0x0f;
1287                         b1 = ((u8*)scsicmd->buffer)[1];
1288                         if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER
1289                                         || (b==TYPE_DISK && (b1&0x80)) ){
1290                                 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
1291                         } else {
1292                                 scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8;
1293                         }
1294                         break;
1295                 }
1296                 default:
1297                         scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
1298                         break;
1299                 }
1300                 break;
1301         case SRB_STATUS_ABORTED:
1302                 scsicmd->result = DID_ABORT << 16 | ABORT << 8;
1303                 break;
1304         case SRB_STATUS_ABORT_FAILED:
1305                 // Not sure about this one - but assuming the hba was trying to abort for some reason
1306                 scsicmd->result = DID_ERROR << 16 | ABORT << 8;
1307                 break;
1308         case SRB_STATUS_PARITY_ERROR:
1309                 scsicmd->result = DID_PARITY << 16 | MSG_PARITY_ERROR << 8;
1310                 break;
1311         case SRB_STATUS_NO_DEVICE:
1312         case SRB_STATUS_INVALID_PATH_ID:
1313         case SRB_STATUS_INVALID_TARGET_ID:
1314         case SRB_STATUS_INVALID_LUN:
1315         case SRB_STATUS_SELECTION_TIMEOUT:
1316                 scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8;
1317                 break;
1318
1319         case SRB_STATUS_COMMAND_TIMEOUT:
1320         case SRB_STATUS_TIMEOUT:
1321                 scsicmd->result = DID_TIME_OUT << 16 | COMMAND_COMPLETE << 8;
1322                 break;
1323
1324         case SRB_STATUS_BUSY:
1325                 scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8;
1326                 break;
1327
1328         case SRB_STATUS_BUS_RESET:
1329                 scsicmd->result = DID_RESET << 16 | COMMAND_COMPLETE << 8;
1330                 break;
1331
1332         case SRB_STATUS_MESSAGE_REJECTED:
1333                 scsicmd->result = DID_ERROR << 16 | MESSAGE_REJECT << 8;
1334                 break;
1335         case SRB_STATUS_REQUEST_FLUSHED:
1336         case SRB_STATUS_ERROR:
1337         case SRB_STATUS_INVALID_REQUEST:
1338         case SRB_STATUS_REQUEST_SENSE_FAILED:
1339         case SRB_STATUS_NO_HBA:
1340         case SRB_STATUS_UNEXPECTED_BUS_FREE:
1341         case SRB_STATUS_PHASE_SEQUENCE_FAILURE:
1342         case SRB_STATUS_BAD_SRB_BLOCK_LENGTH:
1343         case SRB_STATUS_DELAYED_RETRY:
1344         case SRB_STATUS_BAD_FUNCTION:
1345         case SRB_STATUS_NOT_STARTED:
1346         case SRB_STATUS_NOT_IN_USE:
1347         case SRB_STATUS_FORCE_ABORT:
1348         case SRB_STATUS_DOMAIN_VALIDATION_FAIL:
1349         default:
1350 #ifdef AAC_DETAILED_STATUS_INFO
1351                 printk("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n",le32_to_cpu(srbreply->srb_status&0x3f),aac_get_status_string(le32_to_cpu(srbreply->srb_status)), scsicmd->cmnd[0], le32_to_cpu(srbreply->scsi_status) );
1352 #endif
1353                 scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
1354                 break;
1355         }
1356         if (le32_to_cpu(srbreply->scsi_status) == 0x02 ){  // Check Condition
1357                 int len;
1358                 scsicmd->result |= SAM_STAT_CHECK_CONDITION;
1359                 len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))?
1360                                 sizeof(scsicmd->sense_buffer):srbreply->sense_data_size;
1361                 dprintk((KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n", le32_to_cpu(srbreply->status), len));
1362                 memcpy(scsicmd->sense_buffer, srbreply->sense_data, len);
1363                 
1364         }
1365         /*
1366          * OR in the scsi status (already shifted up a bit)
1367          */
1368         scsicmd->result |= le32_to_cpu(srbreply->scsi_status);
1369
1370         fib_complete(fibptr);
1371         fib_free(fibptr);
1372         aac_io_done(scsicmd);
1373 }
1374
1375 /**
1376  *
1377  * aac_send_scb_fib
1378  * @scsicmd: the scsi command block
1379  *
1380  * This routine will form a FIB and fill in the aac_srb from the 
1381  * scsicmd passed in.
1382  */
1383
1384 static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
1385 {
1386         struct fib* cmd_fibcontext;
1387         struct aac_dev* dev;
1388         int status;
1389         struct aac_srb *srbcmd;
1390         u16 fibsize;
1391         u32 flag;
1392         u32 timeout;
1393
1394         if( scsicmd->device->id > 15 || scsicmd->device->lun > 7) {
1395                 scsicmd->result = DID_NO_CONNECT << 16;
1396                 __aac_io_done(scsicmd);
1397                 return 0;
1398         }
1399
1400         dev = (struct aac_dev *)scsicmd->device->host->hostdata;
1401         switch(scsicmd->sc_data_direction){
1402         case DMA_TO_DEVICE:
1403                 flag = SRB_DataOut;
1404                 break;
1405         case DMA_BIDIRECTIONAL:
1406                 flag = SRB_DataIn | SRB_DataOut;
1407                 break;
1408         case DMA_FROM_DEVICE:
1409                 flag = SRB_DataIn;
1410                 break;
1411         case DMA_NONE:
1412         default:        /* shuts up some versions of gcc */
1413                 flag = SRB_NoDataXfer;
1414                 break;
1415         }
1416
1417
1418         /*
1419          *      Allocate and initialize a Fib then setup a BlockWrite command
1420          */
1421         if (!(cmd_fibcontext = fib_alloc(dev))) {
1422                 return -1;
1423         }
1424         fib_init(cmd_fibcontext);
1425
1426         srbcmd = (struct aac_srb*) fib_data(cmd_fibcontext);
1427         srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);
1428         srbcmd->channel  = cpu_to_le32(aac_logical_to_phys(scsicmd->device->channel));
1429         srbcmd->id   = cpu_to_le32(scsicmd->device->id);
1430         srbcmd->lun      = cpu_to_le32(scsicmd->device->lun);
1431         srbcmd->flags    = cpu_to_le32(flag);
1432         timeout = (scsicmd->timeout-jiffies)/HZ;
1433         if(timeout == 0){
1434                 timeout = 1;
1435         }
1436         srbcmd->timeout  = cpu_to_le32(timeout);  // timeout in seconds
1437         srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter
1438         srbcmd->cdb_size = cpu_to_le32(scsicmd->cmd_len);
1439         
1440         if( dev->pae_support ==1 ) {
1441                 aac_build_sg64(scsicmd, (struct sgmap64*) &srbcmd->sg);
1442                 srbcmd->count = cpu_to_le32(scsicmd->request_bufflen);
1443
1444                 memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
1445                 memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len);
1446                 /*
1447                  *      Build Scatter/Gather list
1448                  */
1449                 fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry64));
1450
1451                 /*
1452                  *      Now send the Fib to the adapter
1453                  */
1454                 status = fib_send(ScsiPortCommand64, cmd_fibcontext, fibsize, FsaNormal, 0, 1,
1455                                   (fib_callback) aac_srb_callback, (void *) scsicmd);
1456         } else {
1457                 aac_build_sg(scsicmd, (struct sgmap*)&srbcmd->sg);
1458                 srbcmd->count = cpu_to_le32(scsicmd->request_bufflen);
1459
1460                 memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
1461                 memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len);
1462                 /*
1463                  *      Build Scatter/Gather list
1464                  */
1465                 fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry));
1466
1467                 /*
1468                  *      Now send the Fib to the adapter
1469                  */
1470                 status = fib_send(ScsiPortCommand, cmd_fibcontext, fibsize, FsaNormal, 0, 1,
1471                                   (fib_callback) aac_srb_callback, (void *) scsicmd);
1472         }
1473         /*
1474          *      Check that the command queued to the controller
1475          */
1476         if (status == -EINPROGRESS){
1477                 return 0;
1478         }
1479
1480         printk(KERN_WARNING "aac_srb: fib_send failed with status: %d\n", status);
1481         fib_complete(cmd_fibcontext);
1482         fib_free(cmd_fibcontext);
1483
1484         return -1;
1485 }
1486
1487 static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg)
1488 {
1489         struct aac_dev *dev;
1490         unsigned long byte_count = 0;
1491
1492         dev = (struct aac_dev *)scsicmd->device->host->hostdata;
1493         // Get rid of old data
1494         psg->count = cpu_to_le32(0);
1495         psg->sg[0].addr = cpu_to_le32(0);
1496         psg->sg[0].count = cpu_to_le32(0);  
1497         if (scsicmd->use_sg) {
1498                 struct scatterlist *sg;
1499                 int i;
1500                 int sg_count;
1501                 sg = (struct scatterlist *) scsicmd->request_buffer;
1502
1503                 sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg,
1504                         scsicmd->sc_data_direction);
1505                 psg->count = cpu_to_le32(sg_count);
1506
1507                 byte_count = 0;
1508
1509                 for (i = 0; i < sg_count; i++) {
1510                         psg->sg[i].addr = cpu_to_le32(sg_dma_address(sg));
1511                         psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));
1512                         byte_count += sg_dma_len(sg);
1513                         sg++;
1514                 }
1515                 /* hba wants the size to be exact */
1516                 if(byte_count > scsicmd->request_bufflen){
1517                         psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen);
1518                         byte_count = scsicmd->request_bufflen;
1519                 }
1520                 /* Check for command underflow */
1521                 if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
1522                         printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",
1523                                         byte_count, scsicmd->underflow);
1524                 }
1525         }
1526         else if(scsicmd->request_bufflen) {
1527                 dma_addr_t addr; 
1528                 addr = pci_map_single(dev->pdev,
1529                                 scsicmd->request_buffer,
1530                                 scsicmd->request_bufflen,
1531                                 scsicmd->sc_data_direction);
1532                 psg->count = cpu_to_le32(1);
1533                 psg->sg[0].addr = cpu_to_le32(addr);
1534                 psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);  
1535                 scsicmd->SCp.ptr = (char *)(ulong)addr;
1536                 byte_count = scsicmd->request_bufflen;
1537         }
1538         return byte_count;
1539 }
1540
1541
1542 static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg)
1543 {
1544         struct aac_dev *dev;
1545         unsigned long byte_count = 0;
1546         u64 le_addr;
1547
1548         dev = (struct aac_dev *)scsicmd->device->host->hostdata;
1549         // Get rid of old data
1550         psg->count = cpu_to_le32(0);
1551         psg->sg[0].addr[0] = cpu_to_le32(0);
1552         psg->sg[0].addr[1] = cpu_to_le32(0);
1553         psg->sg[0].count = cpu_to_le32(0);  
1554         if (scsicmd->use_sg) {
1555                 struct scatterlist *sg;
1556                 int i;
1557                 int sg_count;
1558                 sg = (struct scatterlist *) scsicmd->request_buffer;
1559
1560                 sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg,
1561                         scsicmd->sc_data_direction);
1562                 psg->count = cpu_to_le32(sg_count);
1563
1564                 byte_count = 0;
1565
1566                 for (i = 0; i < sg_count; i++) {
1567                         le_addr = cpu_to_le64(sg_dma_address(sg));
1568                         psg->sg[i].addr[1] = (u32)(le_addr>>32);
1569                         psg->sg[i].addr[0] = (u32)(le_addr & 0xffffffff);
1570                         psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));
1571                         byte_count += sg_dma_len(sg);
1572                         sg++;
1573                 }
1574                 /* hba wants the size to be exact */
1575                 if(byte_count > scsicmd->request_bufflen){
1576                         psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen);
1577                         byte_count = scsicmd->request_bufflen;
1578                 }
1579                 /* Check for command underflow */
1580                 if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
1581                         printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",
1582                                         byte_count, scsicmd->underflow);
1583                 }
1584         }
1585         else if(scsicmd->request_bufflen) {
1586                 dma_addr_t addr; 
1587                 addr = pci_map_single(dev->pdev,
1588                                 scsicmd->request_buffer,
1589                                 scsicmd->request_bufflen,
1590                                 scsicmd->sc_data_direction);
1591                 psg->count = cpu_to_le32(1);
1592                 le_addr = cpu_to_le64(addr);
1593                 psg->sg[0].addr[1] = (u32)(le_addr>>32);
1594                 psg->sg[0].addr[0] = (u32)(le_addr & 0xffffffff);
1595                 psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);  
1596                 scsicmd->SCp.ptr = (char *)(ulong)addr;
1597                 byte_count = scsicmd->request_bufflen;
1598         }
1599         return byte_count;
1600 }
1601
1602 #ifdef AAC_DETAILED_STATUS_INFO
1603
1604 struct aac_srb_status_info {
1605         u32     status;
1606         char    *str;
1607 };
1608
1609
1610 static struct aac_srb_status_info srb_status_info[] = {
1611         { SRB_STATUS_PENDING,           "Pending Status"},
1612         { SRB_STATUS_SUCCESS,           "Success"},
1613         { SRB_STATUS_ABORTED,           "Aborted Command"},
1614         { SRB_STATUS_ABORT_FAILED,      "Abort Failed"},
1615         { SRB_STATUS_ERROR,             "Error Event"}, 
1616         { SRB_STATUS_BUSY,              "Device Busy"},
1617         { SRB_STATUS_INVALID_REQUEST,   "Invalid Request"},
1618         { SRB_STATUS_INVALID_PATH_ID,   "Invalid Path ID"},
1619         { SRB_STATUS_NO_DEVICE,         "No Device"},
1620         { SRB_STATUS_TIMEOUT,           "Timeout"},
1621         { SRB_STATUS_SELECTION_TIMEOUT, "Selection Timeout"},
1622         { SRB_STATUS_COMMAND_TIMEOUT,   "Command Timeout"},
1623         { SRB_STATUS_MESSAGE_REJECTED,  "Message Rejected"},
1624         { SRB_STATUS_BUS_RESET,         "Bus Reset"},
1625         { SRB_STATUS_PARITY_ERROR,      "Parity Error"},
1626         { SRB_STATUS_REQUEST_SENSE_FAILED,"Request Sense Failed"},
1627         { SRB_STATUS_NO_HBA,            "No HBA"},
1628         { SRB_STATUS_DATA_OVERRUN,      "Data Overrun/Data Underrun"},
1629         { SRB_STATUS_UNEXPECTED_BUS_FREE,"Unexpected Bus Free"},
1630         { SRB_STATUS_PHASE_SEQUENCE_FAILURE,"Phase Error"},
1631         { SRB_STATUS_BAD_SRB_BLOCK_LENGTH,"Bad Srb Block Length"},
1632         { SRB_STATUS_REQUEST_FLUSHED,   "Request Flushed"},
1633         { SRB_STATUS_DELAYED_RETRY,     "Delayed Retry"},
1634         { SRB_STATUS_INVALID_LUN,       "Invalid LUN"}, 
1635         { SRB_STATUS_INVALID_TARGET_ID, "Invalid TARGET ID"},
1636         { SRB_STATUS_BAD_FUNCTION,      "Bad Function"},
1637         { SRB_STATUS_ERROR_RECOVERY,    "Error Recovery"},
1638         { SRB_STATUS_NOT_STARTED,       "Not Started"},
1639         { SRB_STATUS_NOT_IN_USE,        "Not In Use"},
1640         { SRB_STATUS_FORCE_ABORT,       "Force Abort"},
1641         { SRB_STATUS_DOMAIN_VALIDATION_FAIL,"Domain Validation Failure"},
1642         { 0xff,                         "Unknown Error"}
1643 };
1644
1645 char *aac_get_status_string(u32 status)
1646 {
1647         int i;
1648
1649         for(i=0; i < (sizeof(srb_status_info)/sizeof(struct aac_srb_status_info)); i++ ){
1650                 if(srb_status_info[i].status == status){
1651                         return srb_status_info[i].str;
1652                 }
1653         }
1654
1655         return "Bad Status Code";
1656 }
1657
1658 #endif