~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/block/cpqarray.c

Version: ~ [ 2.2.5 ] ~ [ 2.4.1 ] ~ [ 2.4.9 ] ~ [ 2.6.17.10 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *    Disk Array driver for Compaq SMART2 Controllers
  3  *    Copyright 1998 Compaq Computer Corporation
  4  *
  5  *    This program is free software; you can redistribute it and/or modify
  6  *    it under the terms of the GNU General Public License as published by
  7  *    the Free Software Foundation; either version 2 of the License, or
  8  *    (at your option) any later version.
  9  *
 10  *    This program is distributed in the hope that it will be useful,
 11  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  *    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
 13  *    NON INFRINGEMENT.  See the GNU General Public License for more details.
 14  *
 15  *    You should have received a copy of the GNU General Public License
 16  *    along with this program; if not, write to the Free Software
 17  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 18  *
 19  *    Questions/Comments/Bugfixes to arrays@compaq.com
 20  *
 21  *    If you want to make changes, improve or add functionality to this
 22  *    driver, you'll probably need the Compaq Array Controller Interface
 23  *    Specificiation (Document number ECG086/1198)
 24  */
 25 #include <linux/config.h>       /* CONFIG_PROC_FS */
 26 #include <linux/module.h>
 27 #include <linux/version.h>
 28 #include <linux/types.h>
 29 #include <linux/pci.h>
 30 #include <linux/kernel.h>
 31 #include <linux/malloc.h>
 32 #include <linux/delay.h>
 33 #include <linux/major.h>
 34 #include <linux/fs.h>
 35 #include <linux/blkpg.h>
 36 #include <linux/timer.h>
 37 #include <linux/proc_fs.h>
 38 #include <linux/init.h>
 39 #include <linux/hdreg.h>
 40 #include <linux/spinlock.h>
 41 #include <asm/uaccess.h>
 42 #include <asm/io.h>
 43 
 44 
 45 #define SMART2_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
 46 
 47 #define DRIVER_NAME "Compaq SMART2 Driver (v 2.4.1)"
 48 #define DRIVER_VERSION SMART2_DRIVER_VERSION(2,4,1)
 49 
 50 /* Embedded module documentation macros - see modules.h */
 51 /* Original author Chris Frantz - Compaq Computer Corporation */
 52 MODULE_AUTHOR("Compaq Computer Corporation");
 53 MODULE_DESCRIPTION("Driver for Compaq Smart2 Array Controllers");
 54 
 55 #define MAJOR_NR COMPAQ_SMART2_MAJOR
 56 #include <linux/blk.h>
 57 #include <linux/blkdev.h>
 58 #include <linux/genhd.h>
 59 
 60 #include "cpqarray.h"
 61 #include "ida_cmd.h"
 62 #include "smart1,2.h"
 63 #include "ida_ioctl.h"
 64 
 65 #define READ_AHEAD      128
 66 #define NR_CMDS         128 /* This could probably go as high as ~400 */
 67 
 68 #define MAX_CTLR        8
 69 #define CTLR_SHIFT      8
 70 
 71 static int nr_ctlr;
 72 static ctlr_info_t *hba[MAX_CTLR];
 73 
 74 static int eisa[8];
 75 
 76 #define NR_PRODUCTS (sizeof(products)/sizeof(struct board_type))
 77 
 78 /*  board_id = Subsystem Device ID & Vendor ID
 79  *  product = Marketing Name for the board
 80  *  access = Address of the struct of function pointers 
 81  */
 82 static struct board_type products[] = {
 83         { 0x0040110E, "IDA",                    &smart1_access },
 84         { 0x0140110E, "IDA-2",                  &smart1_access },
 85         { 0x1040110E, "IAES",                   &smart1_access },
 86         { 0x2040110E, "SMART",                  &smart1_access },
 87         { 0x3040110E, "SMART-2/E",              &smart2e_access },
 88         { 0x40300E11, "SMART-2/P",              &smart2_access },
 89         { 0x40310E11, "SMART-2SL",              &smart2_access },
 90         { 0x40320E11, "Smart Array 3200",       &smart2_access },
 91         { 0x40330E11, "Smart Array 3100ES",     &smart2_access },
 92         { 0x40340E11, "Smart Array 221",        &smart2_access },
 93         { 0x40400E11, "Integrated Array",       &smart4_access },
 94         { 0x40480E11, "Compaq Raid LC2",        &smart4_access },
 95         { 0x40500E11, "Smart Array 4200",       &smart4_access },
 96         { 0x40510E11, "Smart Array 4250ES",     &smart4_access },
 97         { 0x40580E11, "Smart Array 431",        &smart4_access },
 98 };
 99 
100 static struct hd_struct * ida;
101 static int * ida_sizes;
102 static int * ida_blocksizes;
103 static int * ida_hardsizes;
104 static struct gendisk ida_gendisk[MAX_CTLR];
105 
106 static struct proc_dir_entry *proc_array;
107 
108 /* Debug... */
109 #define DBG(s)  do { s } while(0)
110 /* Debug (general info)... */
111 #define DBGINFO(s) do { } while(0)
112 /* Debug Paranoid... */
113 #define DBGP(s)  do { } while(0)
114 /* Debug Extra Paranoid... */
115 #define DBGPX(s) do { } while(0)
116 
117 int cpqarray_init(void);
118 static int cpqarray_pci_detect(void);
119 static int cpqarray_pci_init(ctlr_info_t *c, struct pci_dev *pdev);
120 static void *remap_pci_mem(ulong base, ulong size);
121 static int cpqarray_eisa_detect(void);
122 static int pollcomplete(int ctlr);
123 static void getgeometry(int ctlr);
124 static void start_fwbk(int ctlr);
125 
126 static cmdlist_t * cmd_alloc(ctlr_info_t *h);
127 static void cmd_free(ctlr_info_t *h, cmdlist_t *c);
128 
129 static int sendcmd(
130         __u8    cmd,
131         int     ctlr,
132         void    *buff,
133         size_t  size,
134         unsigned int blk,
135         unsigned int blkcnt,
136         unsigned int log_unit );
137 
138 static int ida_open(struct inode *inode, struct file *filep);
139 static int ida_release(struct inode *inode, struct file *filep);
140 static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg);
141 static int ida_ctlr_ioctl(int ctlr, int dsk, ida_ioctl_t *io);
142 
143 static void do_ida_request(request_queue_t *q);
144 static void start_io(ctlr_info_t *h);
145 
146 static inline void addQ(cmdlist_t **Qptr, cmdlist_t *c);
147 static inline cmdlist_t *removeQ(cmdlist_t **Qptr, cmdlist_t *c);
148 static inline void complete_buffers(struct buffer_head *bh, int ok);
149 static inline void complete_command(cmdlist_t *cmd, int timeout);
150 
151 static void do_ida_intr(int irq, void *dev_id, struct pt_regs * regs);
152 static void ida_timer(unsigned long tdata);
153 static int frevalidate_logvol(kdev_t dev);
154 static int revalidate_logvol(kdev_t dev, int maxusage);
155 static int revalidate_allvol(kdev_t dev);
156 
157 #ifdef CONFIG_PROC_FS
158 static void ida_procinit(int i);
159 static int ida_proc_get_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
160 #else
161 static void ida_procinit(int i) {}
162 static int ida_proc_get_info(char *buffer, char **start, off_t offset,
163                              int length, int *eof, void *data) { return 0;}
164 #endif
165 
166 static void ida_geninit(int ctlr)
167 {
168         int i,j;
169         drv_info_t *drv;
170 
171         for(i=0; i<NWD; i++) {
172                 drv = &hba[ctlr]->drv[i];
173                 if (!drv->nr_blks)
174                         continue;
175                 ida[(ctlr<<CTLR_SHIFT) + (i<<NWD_SHIFT)].nr_sects =
176                 ida_sizes[(ctlr<<CTLR_SHIFT) + (i<<NWD_SHIFT)] =
177                                 drv->nr_blks;
178 
179                 for(j=0; j<16; j++) {
180                         ida_blocksizes[(ctlr<<CTLR_SHIFT) + (i<<NWD_SHIFT)+j] =
181                                 1024;
182                         ida_hardsizes[(ctlr<<CTLR_SHIFT) + (i<<NWD_SHIFT)+j] =
183                                 drv->blk_size;
184                 }
185                 ida_gendisk[ctlr].nr_real++;
186         }
187 
188 }
189 
190 static struct block_device_operations ida_fops  = {
191         open:           ida_open,
192         release:        ida_release,
193         ioctl:          ida_ioctl,
194         revalidate:     frevalidate_logvol,
195 };
196 
197 
198 #ifdef CONFIG_PROC_FS
199 
200 /*
201  * Get us a file in /proc/array that says something about each controller.
202  * Create /proc/array if it doesn't exist yet.
203  */
204 static void __init ida_procinit(int i)
205 {
206         if (proc_array == NULL) {
207                 proc_array = proc_mkdir("driver/array", NULL);
208                 if (!proc_array) return;
209         }
210 
211         create_proc_read_entry(hba[i]->devname, 0, proc_array,
212                                ida_proc_get_info, hba[i]);
213 }
214 
215 /*
216  * Report information about this controller.
217  */
218 static int ida_proc_get_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
219 {
220         off_t pos = 0;
221         off_t len = 0;
222         int size, i, ctlr;
223         ctlr_info_t *h = (ctlr_info_t*)data;
224         drv_info_t *drv;
225 #ifdef CPQ_PROC_PRINT_QUEUES
226         cmdlist_t *c;
227 #endif
228 
229         ctlr = h->ctlr;
230         size = sprintf(buffer, "%s:  Compaq %s Controller\n"
231                 "       Board ID: %08lx\n"
232                 "       Firmware Revision: %c%c%c%c\n"
233                 "       Controller Sig: %08lx\n"
234                 "       Memory Address: %08lx\n"
235                 "       I/O Port: %04x\n"
236                 "       IRQ: %x\n"
237                 "       Logical drives: %d\n"
238                 "       Physical drives: %d\n\n"
239                 "       Current Q depth: %d\n"
240                 "       Max Q depth since init: %d\n\n",
241                 h->devname, 
242                 h->product_name,
243                 (unsigned long)h->board_id,
244                 h->firm_rev[0], h->firm_rev[1], h->firm_rev[2], h->firm_rev[3],
245                 (unsigned long)h->ctlr_sig, (unsigned long)h->vaddr,
246                 (unsigned int) h->ioaddr, (unsigned int)h->intr,
247                 h->log_drives, h->phys_drives,
248                 h->Qdepth, h->maxQsinceinit);
249 
250         pos += size; len += size;
251         
252         size = sprintf(buffer+len, "Logical Drive Info:\n");
253         pos += size; len += size;
254 
255         for(i=0; i<h->log_drives; i++) {
256                 drv = &h->drv[i];
257                 size = sprintf(buffer+len, "ida/c%dd%d: blksz=%d nr_blks=%d\n",
258                                 ctlr, i, drv->blk_size, drv->nr_blks);
259                 pos += size; len += size;
260         }
261 
262 #ifdef CPQ_PROC_PRINT_QUEUES
263         size = sprintf(buffer+len, "\nCurrent Queues:\n");
264         pos += size; len += size;
265 
266         c = h->reqQ;
267         size = sprintf(buffer+len, "reqQ = %p", c); pos += size; len += size;
268         if (c) c=c->next;
269         while(c && c != h->reqQ) {
270                 size = sprintf(buffer+len, "->%p", c);
271                 pos += size; len += size;
272                 c=c->next;
273         }
274 
275         c = h->cmpQ;
276         size = sprintf(buffer+len, "\ncmpQ = %p", c); pos += size; len += size;
277         if (c) c=c->next;
278         while(c && c != h->cmpQ) {
279                 size = sprintf(buffer+len, "->%p", c);
280                 pos += size; len += size;
281                 c=c->next;
282         }
283 
284         size = sprintf(buffer+len, "\n"); pos += size; len += size;
285 #endif
286         size = sprintf(buffer+len, "nr_allocs = %d\nnr_frees = %d\n",
287                         h->nr_allocs, h->nr_frees);
288         pos += size; len += size;
289 
290         *eof = 1;
291         *start = buffer+offset;
292         len -= offset;
293         if (len>length)
294                 len = length;
295         return len;
296 }
297 #endif /* CONFIG_PROC_FS */
298 
299 #ifdef MODULE
300 
301 MODULE_PARM(eisa, "1-8i");
302 EXPORT_NO_SYMBOLS;
303 
304 /* This is a bit of a hack... */
305 int __init init_module(void)
306 {
307         if (cpqarray_init() == 0) /* all the block dev numbers already used */
308                 return -EIO;      /* or no controllers were found */
309         return 0;
310 }
311 
312 void cleanup_module(void)
313 {
314         int i;
315         struct gendisk *g;
316 
317         remove_proc_entry("driver/array", NULL);
318 
319         for(i=0; i<nr_ctlr; i++) {
320                 hba[i]->access.set_intr_mask(hba[i], 0);
321                 free_irq(hba[i]->intr, hba[i]);
322                 iounmap(hba[i]->vaddr);
323                 unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
324                 del_timer(&hba[i]->timer);
325                 blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR + i));
326                 remove_proc_entry(hba[i]->devname, proc_array);
327                 kfree(hba[i]->cmd_pool);
328                 kfree(hba[i]->cmd_pool_bits);
329 
330                 if (gendisk_head == &ida_gendisk[i]) {
331                         gendisk_head = ida_gendisk[i].next;
332                 } else {
333                         for(g=gendisk_head; g; g=g->next) {
334                                 if (g->next == &ida_gendisk[i]) {
335                                         g->next = ida_gendisk[i].next;
336                                         break;
337                                 }
338                         }
339                 }
340         }
341 
342         kfree(ida);
343         kfree(ida_sizes);
344         kfree(ida_hardsizes);
345         kfree(ida_blocksizes);
346 }
347 #endif /* MODULE */
348 
349 static inline int cpq_new_segment(request_queue_t *q, struct request *rq,
350                                   int max_segments)
351 {
352         if (rq->nr_segments < SG_MAX) {
353                 rq->nr_segments++;
354                 return 1;
355         }
356         return 0;
357 }
358 
359 static int cpq_back_merge_fn(request_queue_t *q, struct request *rq,
360                              struct buffer_head *bh, int max_segments)
361 {
362         if (rq->bhtail->b_data + rq->bhtail->b_size == bh->b_data)
363                 return 1;
364         return cpq_new_segment(q, rq, max_segments);
365 }
366 
367 static int cpq_front_merge_fn(request_queue_t *q, struct request *rq,
368                              struct buffer_head *bh, int max_segments)
369 {
370         if (bh->b_data + bh->b_size == rq->bh->b_data)
371                 return 1;
372         return cpq_new_segment(q, rq, max_segments);
373 }
374 
375 static int cpq_merge_requests_fn(request_queue_t *q, struct request *rq,
376                                  struct request *nxt, int max_segments)
377 {
378         int total_segments = rq->nr_segments + nxt->nr_segments;
379 
380         if (rq->bhtail->b_data + rq->bhtail->b_size == nxt->bh->b_data)
381                 total_segments--;
382 
383         if (total_segments > SG_MAX)
384                 return 0;
385 
386         rq->nr_segments = total_segments;
387         return 1;
388 }
389 
390 /*
391  *  This is it.  Find all the controllers and register them.  I really hate
392  *  stealing all these major device numbers.
393  *  returns the number of block devices registered.
394  */
395 int __init cpqarray_init(void)
396 {
397         request_queue_t *q;
398         int i,j;
399         int num_cntlrs_reg = 0;
400 
401         /* detect controllers */
402         cpqarray_pci_detect();
403         cpqarray_eisa_detect();
404         
405         if (nr_ctlr == 0)
406                 return(num_cntlrs_reg);
407 
408         printk(DRIVER_NAME "\n");
409         printk("Found %d controller(s)\n", nr_ctlr);
410 
411         /* allocate space for disk structs */
412         ida = kmalloc(sizeof(struct hd_struct)*nr_ctlr*NWD*16, GFP_KERNEL);
413         if(ida==NULL)
414         {
415                 printk( KERN_ERR "cpqarray: out of memory");
416                 return(num_cntlrs_reg);
417         }
418         
419         ida_sizes = kmalloc(sizeof(int)*nr_ctlr*NWD*16, GFP_KERNEL);
420         if(ida_sizes==NULL)
421         {
422                 kfree(ida); 
423                 printk( KERN_ERR "cpqarray: out of memory");
424                 return(num_cntlrs_reg);
425         }
426 
427         ida_blocksizes = kmalloc(sizeof(int)*nr_ctlr*NWD*16, GFP_KERNEL);
428         if(ida_blocksizes==NULL)
429         {
430                 kfree(ida);
431                 kfree(ida_sizes); 
432                 printk( KERN_ERR "cpqarray: out of memory");
433                 return(num_cntlrs_reg);
434         }
435 
436         ida_hardsizes = kmalloc(sizeof(int)*nr_ctlr*NWD*16, GFP_KERNEL);
437         if(ida_hardsizes==NULL)
438         {
439                 kfree(ida);
440                 kfree(ida_sizes); 
441                 kfree(ida_blocksizes);
442                 printk( KERN_ERR "cpqarray: out of memory");
443                 return(num_cntlrs_reg);
444         }
445 
446         memset(ida, 0, sizeof(struct hd_struct)*nr_ctlr*NWD*16);
447         memset(ida_sizes, 0, sizeof(int)*nr_ctlr*NWD*16);
448         memset(ida_blocksizes, 0, sizeof(int)*nr_ctlr*NWD*16);
449         memset(ida_hardsizes, 0, sizeof(int)*nr_ctlr*NWD*16);
450         memset(ida_gendisk, 0, sizeof(struct gendisk)*MAX_CTLR);
451 
452                 /* 
453          * register block devices
454          * Find disks and fill in structs
455          * Get an interrupt, set the Q depth and get into /proc
456          */
457         for(i=0; i< nr_ctlr; i++) {
458                 /* If this successful it should insure that we are the only */
459                 /* instance of the driver */    
460                 if (register_blkdev(MAJOR_NR+i, hba[i]->devname, &ida_fops)) {
461                         printk(KERN_ERR "cpqarray: Unable to get major number %d for ida\n",
462                                 MAJOR_NR+i);
463                         continue;
464                 }
465 
466         
467                 hba[i]->access.set_intr_mask(hba[i], 0);
468                 if (request_irq(hba[i]->intr, do_ida_intr,
469                         SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i])) {
470 
471                         printk(KERN_ERR "cpqarray: Unable to get irq %d for %s\n", 
472                                 hba[i]->intr, hba[i]->devname);
473                         unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
474                         continue;
475                 }
476                 num_cntlrs_reg++;
477                 hba[i]->cmd_pool = (cmdlist_t *)kmalloc(
478                                 NR_CMDS * sizeof(cmdlist_t), GFP_KERNEL);
479                 hba[i]->cmd_pool_bits = (__u32*)kmalloc(
480                                 ((NR_CMDS+31)/32)*sizeof(__u32), GFP_KERNEL);
481                 
482         if(hba[i]->cmd_pool_bits == NULL || hba[i]->cmd_pool == NULL)
483                 {
484                         nr_ctlr = i; 
485                         if(hba[i]->cmd_pool_bits)
486                                 kfree(hba[i]->cmd_pool_bits);
487                         if(hba[i]->cmd_pool)
488                                 kfree(hba[i]->cmd_pool);
489                         free_irq(hba[i]->intr, hba[i]);
490                         unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
491                         num_cntlrs_reg--;
492                         printk( KERN_ERR "cpqarray: out of memory");
493 
494                         /* If num_cntlrs_reg == 0, no controllers worked. 
495                          *      init_module will fail, so clean up global 
496                          *      memory that clean_module would do.
497                         */      
498         
499                         if (num_cntlrs_reg == 0) 
500                         {
501                                 kfree(ida);
502                                 kfree(ida_sizes);
503                                 kfree(ida_hardsizes);
504                                 kfree(ida_blocksizes);
505                         }
506                         return(num_cntlrs_reg);
507         
508                 }
509                 memset(hba[i]->cmd_pool, 0, NR_CMDS * sizeof(cmdlist_t));
510                 memset(hba[i]->cmd_pool_bits, 0, ((NR_CMDS+31)/32)*sizeof(__u32));
511                 printk(KERN_INFO "cpqarray: Finding drives on %s", 
512                         hba[i]->devname);
513                 getgeometry(i);
514                 start_fwbk(i); 
515 
516                 hba[i]->access.set_intr_mask(hba[i], FIFO_NOT_EMPTY);
517 
518                 ida_procinit(i);
519 
520                 q = BLK_DEFAULT_QUEUE(MAJOR_NR + i);
521                 q->queuedata = hba[i];
522                 blk_init_queue(q, do_ida_request);
523                 blk_queue_headactive(q, 0);
524                 blksize_size[MAJOR_NR+i] = ida_blocksizes + (i*256);
525                 hardsect_size[MAJOR_NR+i] = ida_hardsizes + (i*256);
526                 read_ahead[MAJOR_NR+i] = READ_AHEAD;
527 
528                 q->back_merge_fn = cpq_back_merge_fn;
529                 q->front_merge_fn = cpq_front_merge_fn;
530                 q->merge_requests_fn = cpq_merge_requests_fn;
531 
532                 ida_gendisk[i].major = MAJOR_NR + i;
533                 ida_gendisk[i].major_name = "ida";
534                 ida_gendisk[i].minor_shift = NWD_SHIFT;
535                 ida_gendisk[i].max_p = 16;
536                 ida_gendisk[i].part = ida + (i*256);
537                 ida_gendisk[i].sizes = ida_sizes + (i*256);
538                 ida_gendisk[i].nr_real = 0; 
539         
540                 /* Get on the disk list */
541                 ida_gendisk[i].next = gendisk_head;
542                 gendisk_head = &ida_gendisk[i];
543 
544                 init_timer(&hba[i]->timer);
545                 hba[i]->timer.expires = jiffies + IDA_TIMER;
546                 hba[i]->timer.data = (unsigned long)hba[i];
547                 hba[i]->timer.function = ida_timer;
548                 add_timer(&hba[i]->timer);
549 
550                 ida_geninit(i);
551                 for(j=0; j<NWD; j++)    
552                         register_disk(&ida_gendisk[i], 
553                                 MKDEV(MAJOR_NR+i,j<<4),
554                                 16, &ida_fops, hba[i]->drv[j].nr_blks);
555 
556         }
557         /* done ! */
558         return(num_cntlrs_reg);
559 }
560 
561 /*
562  * Find the controller and initialize it
563  *  Cannot use the class code to search, because older array controllers use
564  *    0x018000 and new ones use 0x010400.  So I might as well search for each
565  *    each device IDs, being there are only going to be three of them. 
566  */
567 static int cpqarray_pci_detect(void)
568 {
569         struct pci_dev *pdev;
570 
571 #define IDA_BOARD_TYPES 3
572         static int ida_vendor_id[IDA_BOARD_TYPES] = { PCI_VENDOR_ID_DEC, 
573                 PCI_VENDOR_ID_NCR, PCI_VENDOR_ID_COMPAQ };
574         static int ida_device_id[IDA_BOARD_TYPES] = { PCI_DEVICE_ID_COMPAQ_42XX,                PCI_DEVICE_ID_NCR_53C1510, PCI_DEVICE_ID_COMPAQ_SMART2P };
575         int brdtype;
576         
577         /* search for all PCI board types that could be for this driver */
578         for(brdtype=0; brdtype<IDA_BOARD_TYPES; brdtype++)
579         {
580                 pdev = pci_find_device(ida_vendor_id[brdtype],
581                                        ida_device_id[brdtype], NULL);
582                 while (pdev) {
583                         printk(KERN_DEBUG "cpqarray: Device %x has been found at %x %x\n",
584                                 ida_vendor_id[brdtype],
585                                 pdev->bus->number, pdev->devfn);
586                         if (nr_ctlr == 8) {
587                                 printk(KERN_WARNING "cpqarray: This driver"
588                                 " supports a maximum of 8 controllers.\n");
589                                 break;
590                         }
591                         
592 /* if it is a PCI_DEVICE_ID_NCR_53C1510, make sure it's                                 the Compaq version of the chip */ 
593 
594                         if (ida_device_id[brdtype] == PCI_DEVICE_ID_NCR_53C1510)                        {       
595                                 unsigned short subvendor=pdev->subsystem_vendor;
596                                 if(subvendor !=  PCI_VENDOR_ID_COMPAQ)
597                                 {
598                                         printk(KERN_DEBUG 
599                                                 "cpqarray: not a Compaq integrated array controller\n");
600                                         continue;
601                                 }
602                         }
603 
604                         hba[nr_ctlr] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);                        if(hba[nr_ctlr]==NULL)
605                         {
606                                 printk(KERN_ERR "cpqarray: out of memory.\n");
607                                 continue;
608                         }
609                         memset(hba[nr_ctlr], 0, sizeof(ctlr_info_t));
610                         if (cpqarray_pci_init(hba[nr_ctlr], pdev) != 0)
611                         {
612                                 kfree(hba[nr_ctlr]);
613                                 continue;
614                         }
615                         sprintf(hba[nr_ctlr]->devname, "ida%d", nr_ctlr);
616                         hba[nr_ctlr]->ctlr = nr_ctlr;
617                         nr_ctlr++;
618 
619                         pdev = pci_find_device(ida_vendor_id[brdtype],
620                                                ida_device_id[brdtype], pdev);
621                 }
622         }
623 
624         return nr_ctlr;
625 }
626 
627 /*
628  * Find the IO address of the controller, its IRQ and so forth.  Fill
629  * in some basic stuff into the ctlr_info_t structure.
630  */
631 static int cpqarray_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
632 {
633         ushort vendor_id, device_id, command;
634         unchar cache_line_size, latency_timer;
635         unchar irq, revision;
636         unsigned long addr[6];
637         __u32 board_id;
638 
639         int i;
640 
641         c->pci_dev = pdev;
642         vendor_id = pdev->vendor;
643         device_id = pdev->device;
644         irq = pdev->irq;
645 
646         for(i=0; i<6; i++)
647                 addr[i] = pci_resource_start(pdev, i);
648 
649         if (pci_enable_device(pdev))
650                 return -1;
651 
652         pci_read_config_word(pdev, PCI_COMMAND, &command);
653         pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
654         pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line_size);
655         pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency_timer);
656 
657         pci_read_config_dword(pdev, 0x2c, &board_id);
658 
659 DBGINFO(
660         printk("vendor_id = %x\n", vendor_id);
661         printk("device_id = %x\n", device_id);
662         printk("command = %x\n", command);
663         for(i=0; i<6; i++)
664                 printk("addr[%d] = %lx\n", i, addr[i]);
665         printk("revision = %x\n", revision);
666         printk("irq = %x\n", irq);
667         printk("cache_line_size = %x\n", cache_line_size);
668         printk("latency_timer = %x\n", latency_timer);
669         printk("board_id = %x\n", board_id);
670 );
671 
672         c->intr = irq;
673         c->ioaddr = addr[0];
674 
675         c->paddr = 0;
676         for(i=0; i<6; i++)
677                 if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) {
678                         c->paddr = pci_resource_start (pdev, i);
679                         break;
680                 }
681         if (!c->paddr)
682                 return -1;
683         c->vaddr = remap_pci_mem(c->paddr, 128);
684         if (!c->vaddr)
685                 return -1;
686         c->board_id = board_id;
687 
688         for(i=0; i<NR_PRODUCTS; i++) {
689                 if (board_id == products[i].board_id) {
690                         c->product_name = products[i].product_name;
691                         c->access = *(products[i].access);
692                         break;
693                 }
694         }
695         if (i == NR_PRODUCTS) {
696                 printk(KERN_WARNING "cpqarray: Sorry, I don't know how"
697                         " to access the SMART Array controller %08lx\n", 
698                                 (unsigned long)board_id);
699                 return -1;
700         }
701 
702         return 0;
703 }
704 
705 /*
706  * Map (physical) PCI mem into (virtual) kernel space
707  */
708 static void *remap_pci_mem(ulong base, ulong size)
709 {
710         ulong page_base        = ((ulong) base) & PAGE_MASK;
711         ulong page_offs        = ((ulong) base) - page_base;
712         void *page_remapped    = ioremap(page_base, page_offs+size);
713 
714         return (page_remapped ? (page_remapped + page_offs) : NULL);
715 }
716 
717 #ifndef MODULE
718 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,13)
719 /*
720  * Config string is a comma seperated set of i/o addresses of EISA cards.
721  */
722 static int cpqarray_setup(char *str)
723 {
724         int i, ints[9];
725 
726         (void)get_options(str, ARRAY_SIZE(ints), ints);
727 
728         for(i=0; i<ints[0] && i<8; i++)
729                 eisa[i] = ints[i+1];
730         return 1;
731 }
732 
733 __setup("smart2=", cpqarray_setup);
734 
735 #else
736 
737 /*
738  * Copy the contents of the ints[] array passed to us by init.
739  */
740 void cpqarray_setup(char *str, int *ints)
741 {
742         int i;
743         for(i=0; i<ints[0] && i<8; i++)
744                 eisa[i] = ints[i+1];
745 }
746 #endif
747 #endif
748 
749 /*
750  * Find an EISA controller's signature.  Set up an hba if we find it.
751  */
752 static int cpqarray_eisa_detect(void)
753 {
754         int i=0, j;
755         __u32 board_id;
756         int intr;
757 
758         while(i<8 && eisa[i]) {
759                 if (nr_ctlr == 8) {
760                         printk(KERN_WARNING "cpqarray: This driver supports"
761                                 " a maximum of 8 controllers.\n");
762                         break;
763                 }
764                 board_id = inl(eisa[i]+0xC80);
765                 for(j=0; j < NR_PRODUCTS; j++)
766                         if (board_id == products[j].board_id) 
767                                 break;
768 
769                 if (j == NR_PRODUCTS) {
770                         printk(KERN_WARNING "cpqarray: Sorry, I don't know how"
771                                 " to access the SMART Array controller %08lx\n",                                 (unsigned long)board_id);
772                         continue;
773                 }
774                 hba[nr_ctlr] = (ctlr_info_t *) kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);
775                 if(hba[nr_ctlr]==NULL)
776                 {
777                         printk(KERN_ERR "cpqarray: out of memory.\n");
778                         continue;
779                 }
780                 memset(hba[nr_ctlr], 0, sizeof(ctlr_info_t));
781                 hba[nr_ctlr]->ioaddr = eisa[i];
782 
783                 /*
784                  * Read the config register to find our interrupt
785                  */
786                 intr = inb(eisa[i]+0xCC0) >> 4;
787                 if (intr & 1) intr = 11;
788                 else if (intr & 2) intr = 10;
789                 else if (intr & 4) intr = 14;
790                 else if (intr & 8) intr = 15;
791                 
792                 hba[nr_ctlr]->intr = intr;
793                 sprintf(hba[nr_ctlr]->devname, "ida%d", nr_ctlr);
794                 hba[nr_ctlr]->product_name = products[j].product_name;
795                 hba[nr_ctlr]->access = *(products[j].access);
796                 hba[nr_ctlr]->ctlr = nr_ctlr;
797                 hba[nr_ctlr]->board_id = board_id;
798                 hba[nr_ctlr]->pci_dev = NULL; /* not PCI */
799 
800 DBGINFO(
801         printk("i = %d, j = %d\n", i, j);
802         printk("irq = %x\n", intr);
803         printk("product name = %s\n", products[j].product_name);
804         printk("board_id = %x\n", board_id);
805 );
806 
807                 nr_ctlr++;
808                 i++;
809         }
810 
811         return nr_ctlr;
812 }
813 
814 
815 /*
816  * Open.  Make sure the device is really there.
817  */
818 static int ida_open(struct inode *inode, struct file *filep)
819 {
820         int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
821         int dsk  = MINOR(inode->i_rdev) >> NWD_SHIFT;
822 
823         DBGINFO(printk("ida_open %x (%x:%x)\n", inode->i_rdev, ctlr, dsk) );
824         if (ctlr > MAX_CTLR || hba[ctlr] == NULL)
825                 return -ENXIO;
826 
827         if (!suser() && ida_sizes[(ctlr << CTLR_SHIFT) +
828                                                 MINOR(inode->i_rdev)] == 0)
829                 return -ENXIO;
830 
831         /*
832          * Root is allowed to open raw volume zero even if its not configured
833          * so array config can still work.  I don't think I really like this,
834          * but I'm already using way to many device nodes to claim another one
835          * for "raw controller".
836          */
837         if (suser()
838                 && ida_sizes[(ctlr << CTLR_SHIFT) + MINOR(inode->i_rdev)] == 0 
839                 && MINOR(inode->i_rdev) != 0)
840                 return -ENXIO;
841 
842         hba[ctlr]->drv[dsk].usage_count++;
843         hba[ctlr]->usage_count++;
844         MOD_INC_USE_COUNT;
845         return 0;
846 }
847 
848 /*
849  * Close.  Sync first.
850  */
851 static int ida_release(struct inode *inode, struct file *filep)
852 {
853         int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
854         int dsk  = MINOR(inode->i_rdev) >> NWD_SHIFT;
855 
856         DBGINFO(printk("ida_release %x (%x:%x)\n", inode->i_rdev, ctlr, dsk) );
857 
858         hba[ctlr]->drv[dsk].usage_count--;
859         hba[ctlr]->usage_count--;
860         MOD_DEC_USE_COUNT;
861         return 0;
862 }
863 
864 /*
865  * Enqueuing and dequeuing functions for cmdlists.
866  */
867 static inline void addQ(cmdlist_t **Qptr, cmdlist_t *c)
868 {
869         if (*Qptr == NULL) {
870                 *Qptr = c;
871                 c->next = c->prev = c;
872         } else {
873                 c->prev = (*Qptr)->prev;
874                 c->next = (*Qptr);
875                 (*Qptr)->prev->next = c;
876                 (*Qptr)->prev = c;
877         }
878 }
879 
880 static inline cmdlist_t *removeQ(cmdlist_t **Qptr, cmdlist_t *c)
881 {
882         if (c && c->next != c) {
883                 if (*Qptr == c) *Qptr = c->next;
884                 c->prev->next = c->next;
885                 c->next->prev = c->prev;
886         } else {
887                 *Qptr = NULL;
888         }
889         return c;
890 }
891 
892 /*
893  * Get a request and submit it to the controller.
894  * This routine needs to grab all the requests it possibly can from the
895  * req Q and submit them.  Interrupts are off (and need to be off) when you
896  * are in here (either via the dummy do_ida_request functions or by being
897  * called from the interrupt handler
898  */
899 static void do_ida_request(request_queue_t *q)
900 {
901         ctlr_info_t *h = q->queuedata;
902         cmdlist_t *c;
903         int seg, sect;
904         char *lastdataend;
905         struct list_head * queue_head = &q->queue_head;
906         struct buffer_head *bh;
907         struct request *creq;
908 
909         if (q->plugged || list_empty(queue_head)) {
910                 start_io(h);
911                 return;
912         }
913 
914         creq = blkdev_entry_next_request(queue_head);
915         if (creq->nr_segments > SG_MAX)
916                 BUG();
917 
918         if (h->ctlr != MAJOR(creq->rq_dev)-MAJOR_NR || h->ctlr > nr_ctlr)
919         {
920                 printk(KERN_WARNING "doreq cmd for %d, %x at %p\n",
921                                 h->ctlr, creq->rq_dev, creq);
922                 blkdev_dequeue_request(creq);
923                 complete_buffers(creq->bh, 0);
924                 start_io(h);
925                 return;
926         }
927 
928         if ((c = cmd_alloc(h)) == NULL)
929         {
930                 start_io(h);
931                 return;
932         }
933 
934         bh = creq->bh;
935 
936         c->ctlr = h->ctlr;
937         c->hdr.unit = MINOR(creq->rq_dev) >> NWD_SHIFT;
938         c->hdr.size = sizeof(rblk_t) >> 2;
939         c->size += sizeof(rblk_t);
940 
941         c->req.hdr.blk = ida[(h->ctlr<<CTLR_SHIFT) + MINOR(creq->rq_dev)].start_sect + creq->sector;
942         c->bh = bh;
943 DBGPX(
944         if (bh == NULL)
945                 panic("bh == NULL?");
946         
947         printk("sector=%d, nr_sectors=%d\n", creq->sector, creq->nr_sectors);
948 );
949         seg = 0; lastdataend = NULL;
950         sect = 0;
951         while(bh) {
952                 sect += bh->b_size/512;
953                 if (bh->b_data == lastdataend) {
954                         c->req.sg[seg-1].size += bh->b_size;
955                         lastdataend += bh->b_size;
956                 } else {
957                         if (seg == SG_MAX)
958                                 BUG();
959                         c->req.sg[seg].size = bh->b_size;
960                         c->req.sg[seg].addr = (__u32)virt_to_bus(bh->b_data);
961                         lastdataend = bh->b_data + bh->b_size;
962                         seg++;
963                 }
964                 bh = bh->b_reqnext;
965         }
966 DBGPX(  printk("Submitting %d sectors in %d segments\n", sect, seg); );
967         c->req.hdr.sg_cnt = seg;
968         c->req.hdr.blk_cnt = sect;
969 
970         /*
971          * Since we control our own merging, we know that this request
972          * is now fully setup and there's nothing left.
973          */
974         if (creq->nr_sectors != sect) {
975                 printk("ida: %ld != %d sectors\n", creq->nr_sectors, sect);
976                 BUG();
977         }
978 
979         blkdev_dequeue_request(creq);
980 
981         /*
982          * ehh, we can't really end the request here since it's not
983          * even started yet. for now it shouldn't hurt though
984          */
985 DBGPX(  printk("Done with %p\n", creq); );
986         end_that_request_last(creq);
987 
988         c->req.hdr.cmd = (creq->cmd == READ) ? IDA_READ : IDA_WRITE;
989         c->type = CMD_RWREQ;
990 
991         /* Put the request on the tail of the request queue */
992         addQ(&h->reqQ, c);
993         h->Qdepth++;
994         if (h->Qdepth > h->maxQsinceinit) 
995                 h->maxQsinceinit = h->Qdepth;
996 
997         start_io(h);
998 }
999 
1000 /* 
1001  * start_io submits everything on a controller's request queue
1002  * and moves it to the completion queue.
1003  *
1004  * Interrupts had better be off if you're in here
1005  */
1006 static void start_io(ctlr_info_t *h)
1007 {
1008         cmdlist_t *c;
1009 
1010         while((c = h->reqQ) != NULL) {
1011                 /* Can't do anything if we're busy */
1012                 if (h->access.fifo_full(h) == 0)
1013                         return;
1014 
1015                 /* Get the first entry from the request Q */
1016                 removeQ(&h->reqQ, c);
1017                 h->Qdepth--;
1018         
1019                 /* Tell the controller to do our bidding */
1020                 h->access.submit_command(h, c);
1021 
1022                 /* Get onto the completion Q */
1023                 addQ(&h->cmpQ, c);
1024         }
1025 }
1026 
1027 static inline void complete_buffers(struct buffer_head *bh, int ok)
1028 {
1029         struct buffer_head *xbh;
1030         while(bh) {
1031                 xbh = bh->b_reqnext;
1032                 bh->b_reqnext = NULL;
1033                 
1034                 blk_finished_io(bh->b_size >> 9);
1035                 bh->b_end_io(bh, ok);
1036 
1037                 bh = xbh;
1038         }
1039 }
1040 /*
1041  * Mark all buffers that cmd was responsible for
1042  */
1043 static inline void complete_command(cmdlist_t *cmd, int timeout)
1044 {
1045         int ok=1;
1046 
1047         if (cmd->req.hdr.rcode & RCODE_NONFATAL &&
1048            (hba[cmd->ctlr]->misc_tflags & MISC_NONFATAL_WARN) == 0) {
1049                 printk(KERN_WARNING "Non Fatal error on ida/c%dd%d\n",
1050                                 cmd->ctlr, cmd->hdr.unit);
1051                 hba[cmd->ctlr]->misc_tflags |= MISC_NONFATAL_WARN;
1052         }
1053         if (cmd->req.hdr.rcode & RCODE_FATAL) {
1054                 printk(KERN_WARNING "Fatal error on ida/c%dd%d\n",
1055                                 cmd->ctlr, cmd->hdr.unit);
1056                 ok = 0;
1057         }
1058         if (cmd->req.hdr.rcode & RCODE_INVREQ) {
1059                                 printk(KERN_WARNING "Invalid request on ida/c%dd%d = (cmd=%x sect=%d cnt=%d sg=%d ret=%x)\n",
1060                                 cmd->ctlr, cmd->hdr.unit, cmd->req.hdr.cmd,
1061                                 cmd->req.hdr.blk, cmd->req.hdr.blk_cnt,
1062                                 cmd->req.hdr.sg_cnt, cmd->req.hdr.rcode);
1063                 ok = 0; 
1064         }
1065         if (timeout) ok = 0;
1066         complete_buffers(cmd->bh, ok);
1067 }
1068 
1069 /*
1070  *  The controller will interrupt us upon completion of commands.
1071  *  Find the command on the completion queue, remove it, tell the OS and
1072  *  try to queue up more IO
1073  */
1074 static void do_ida_intr(int irq, void *dev_id, struct pt_regs *regs)
1075 {
1076         ctlr_info_t *h = dev_id;
1077         cmdlist_t *c;
1078         unsigned long istat;
1079         unsigned long flags;
1080         __u32 a,a1;
1081 
1082         istat = h->access.intr_pending(h);
1083         /* Is this interrupt for us? */
1084         if (istat == 0)
1085                 return;
1086 
1087         /*
1088          * If there are completed commands in the completion queue,
1089          * we had better do something about it.
1090          */
1091         spin_lock_irqsave(&io_request_lock, flags);
1092         if (istat & FIFO_NOT_EMPTY) {
1093                 while((a = h->access.command_completed(h))) {
1094                         a1 = a; a &= ~3;
1095                         if ((c = h->cmpQ) == NULL)
1096                         {  
1097                                 printk(KERN_WARNING "cpqarray: Completion of %08lx ignored\n", (unsigned long)a1);
1098                                 continue;       
1099                         } 
1100                         while(c->busaddr != a) {
1101                                 c = c->next;
1102                                 if (c == h->cmpQ) 
1103                                         break;
1104                         }
1105                         /*
1106                          * If we've found the command, take it off the
1107                          * completion Q and free it
1108                          */
1109                         if (c->busaddr == a) {
1110                                 removeQ(&h->cmpQ, c);
1111                                 if (c->type == CMD_RWREQ) {
1112                                         complete_command(c, 0);
1113                                         cmd_free(h, c);
1114                                 } else if (c->type == CMD_IOCTL_PEND) {
1115                                         c->type = CMD_IOCTL_DONE;
1116                                 }
1117                                 continue;
1118                         }
1119                 }
1120         }
1121 
1122         /*
1123          * See if we can queue up some more IO
1124          */
1125         do_ida_request(BLK_DEFAULT_QUEUE(MAJOR_NR + h->ctlr));
1126         spin_unlock_irqrestore(&io_request_lock, flags);
1127 }
1128 
1129 /*
1130  * This timer was for timing out requests that haven't happened after
1131  * IDA_TIMEOUT.  That wasn't such a good idea.  This timer is used to
1132  * reset a flags structure so we don't flood the user with
1133  * "Non-Fatal error" messages.
1134  */
1135 static void ida_timer(unsigned long tdata)
1136 {
1137         ctlr_info_t *h = (ctlr_info_t*)tdata;
1138 
1139         h->timer.expires = jiffies + IDA_TIMER;
1140         add_timer(&h->timer);
1141         h->misc_tflags = 0;
1142 }
1143 
1144 /*
1145  *  ida_ioctl does some miscellaneous stuff like reporting drive geometry,
1146  *  setting readahead and submitting commands from userspace to the controller.
1147  */
1148 static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg)
1149 {
1150         int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
1151         int dsk  = MINOR(inode->i_rdev) >> NWD_SHIFT;
1152         int error;
1153         int diskinfo[4];
1154         struct hd_geometry *geo = (struct hd_geometry *)arg;
1155         ida_ioctl_t *io = (ida_ioctl_t*)arg;
1156         ida_ioctl_t my_io;
1157 
1158         switch(cmd) {
1159         case HDIO_GETGEO:
1160                 if (hba[ctlr]->drv[dsk].cylinders) {
1161                         diskinfo[0] = hba[ctlr]->drv[dsk].heads;
1162                         diskinfo[1] = hba[ctlr]->drv[dsk].sectors;
1163                         diskinfo[2] = hba[ctlr]->drv[dsk].cylinders;
1164                 } else {
1165                         diskinfo[0] = 0xff;
1166                         diskinfo[1] = 0x3f;
1167                         diskinfo[2] = hba[ctlr]->drv[dsk].nr_blks / (0xff*0x3f);
1168                 }
1169                 put_user(diskinfo[0], &geo->heads);
1170                 put_user(diskinfo[1], &geo->sectors);
1171                 put_user(diskinfo[2], &geo->cylinders);
1172                 put_user(ida[(ctlr<<CTLR_SHIFT)+MINOR(inode->i_rdev)].start_sect, &geo->start);
1173                 return 0;
1174         case IDAGETDRVINFO:
1175                 return copy_to_user(&io->c.drv,&hba[ctlr]->drv[dsk],sizeof(drv_info_t));
1176         case BLKGETSIZE:
1177                 if (!arg) return -EINVAL;
1178                 put_user(ida[(ctlr<<CTLR_SHIFT)+MINOR(inode->i_rdev)].nr_sects, (long*)arg);
1179                 return 0;
1180         case BLKRRPART:
1181                 return revalidate_logvol(inode->i_rdev, 1);
1182         case IDAPASSTHRU:
1183                 if (!suser()) return -EPERM;
1184                 error = copy_from_user(&my_io, io, sizeof(my_io));
1185                 if (error) return error;
1186                 error = ida_ctlr_ioctl(ctlr, dsk, &my_io);
1187                 if (error) return error;
1188                 error = copy_to_user(io, &my_io, sizeof(my_io));
1189                 return error;
1190         case IDAGETCTLRSIG:
1191                 if (!arg) return -EINVAL;
1192                 put_user(hba[ctlr]->ctlr_sig, (int*)arg);
1193                 return 0;
1194         case IDAREVALIDATEVOLS:
1195                 return revalidate_allvol(inode->i_rdev);
1196         case IDADRIVERVERSION:
1197                 if (!arg) return -EINVAL;
1198                 put_user(DRIVER_VERSION, (unsigned long*)arg);
1199                 return 0;
1200         case IDAGETPCIINFO:
1201         {
1202                 
1203                 ida_pci_info_struct pciinfo;
1204 
1205                 if (!arg) return -EINVAL;
1206                 pciinfo.bus = hba[ctlr]->pci_dev->bus->number;
1207                 pciinfo.dev_fn = hba[ctlr]->pci_dev->devfn;
1208                 pciinfo.board_id = hba[ctlr]->board_id;
1209                 if(copy_to_user((void *) arg, &pciinfo,  
1210                         sizeof( ida_pci_info_struct)))
1211                                 return -EFAULT;
1212                 return(0);
1213         }       
1214 
1215         case BLKFLSBUF:
1216         case BLKROSET:
1217         case BLKROGET:
1218         case BLKRASET:
1219         case BLKRAGET:
1220         case BLKPG:
1221                 return blk_ioctl(inode->i_rdev, cmd, arg);
1222 
1223         default:
1224                 return -EINVAL;
1225         }
1226                 
1227 }
1228 /*
1229  * ida_ctlr_ioctl is for passing commands to the controller from userspace.
1230  * The command block (io) has already been copied to kernel space for us,
1231  * however, any elements in the sglist need to be copied to kernel space
1232  * or copied back to userspace.
1233  *
1234  * Only root may perform a controller passthru command, however I'm not doing
1235  * any serious sanity checking on the arguments.  Doing an IDA_WRITE_MEDIA and
1236  * putting a 64M buffer in the sglist is probably a *bad* idea.
1237  */
1238 static int ida_ctlr_ioctl(int ctlr, int dsk, ida_ioctl_t *io)
1239 {
1240         ctlr_info_t *h = hba[ctlr];
1241         cmdlist_t *c;
1242         void *p = NULL;
1243         unsigned long flags;
1244         int error;
1245 
1246         if ((c = cmd_alloc(NULL)) == NULL)
1247                 return -ENOMEM;
1248         c->ctlr = ctlr;
1249         c->hdr.unit = (io->unit & UNITVALID) ? (io->unit & ~UNITVALID) : dsk;
1250         c->hdr.size = sizeof(rblk_t) >> 2;
1251         c->size += sizeof(rblk_t);
1252 
1253         c->req.hdr.cmd = io->cmd;
1254         c->req.hdr.blk = io->blk;
1255         c->req.hdr.blk_cnt = io->blk_cnt;
1256         c->type = CMD_IOCTL_PEND;
1257 
1258         /* Pre submit processing */
1259         switch(io->cmd) {
1260         case PASSTHRU_A:
1261                 p = kmalloc(io->sg[0].size, GFP_KERNEL);
1262                 if (!p) 
1263                 { 
1264                         error = -ENOMEM; 
1265                         cmd_free(NULL, c); 
1266                         return(error);
1267                 }
1268                 copy_from_user(p, (void*)io->sg[0].addr, io->sg[0].size);
1269                 c->req.hdr.blk = virt_to_bus(&(io->c));
1270                 c->req.sg[0].size = io->sg[0].size;
1271                 c->req.sg[0].addr = virt_to_bus(p);
1272                 c->req.hdr.sg_cnt = 1;
1273                 break;
1274         case IDA_READ:
1275                 p = kmalloc(io->sg[0].size, GFP_KERNEL);
1276                 if (!p) 
1277                 { 
1278                         error = -ENOMEM; 
1279                         cmd_free(NULL, c);
1280                         return(error);
1281                 }
1282 
1283                 c->req.sg[0].size = io->sg[0].size;
1284                 c->req.sg[0].addr = virt_to_bus(p);
1285                 c->req.hdr.sg_cnt = 1;
1286                 break;
1287         case IDA_WRITE:
1288         case IDA_WRITE_MEDIA:
1289         case DIAG_PASS_THRU:
1290                 p = kmalloc(io->sg[0].size, GFP_KERNEL);
1291                 if (!p) 
1292                 { 
1293                         error = -ENOMEM; 
1294                         cmd_free(NULL, c);
1295                         return(error);
1296                 }
1297                 copy_from_user(p, (void*)io->sg[0].addr, io->sg[0].size);
1298                 c->req.sg[0].size = io->sg[0].size;
1299                 c->req.sg[0].addr = virt_to_bus(p);
1300                 c->req.hdr.sg_cnt = 1;
1301                 break;
1302         default:
1303                 c->req.sg[0].size = sizeof(io->c);
1304                 c->req.sg[0].addr = virt_to_bus(&io->c);
1305                 c->req.hdr.sg_cnt = 1;
1306         }
1307 
1308         /* Put the request on the tail of the request queue */
1309         spin_lock_irqsave(&io_request_lock, flags);
1310         addQ(&h->reqQ, c);
1311         h->Qdepth++;
1312         start_io(h);
1313         spin_unlock_irqrestore(&io_request_lock, flags);
1314 
1315         /* Wait for completion */
1316         while(c->type != CMD_IOCTL_DONE)
1317                 schedule();
1318 
1319         /* Post submit processing */
1320         switch(io->cmd) {
1321         case PASSTHRU_A:
1322         case IDA_READ:
1323         case DIAG_PASS_THRU:
1324                 copy_to_user((void*)io->sg[0].addr, p, io->sg[0].size);
1325                 /* fall through and free p */
1326         case IDA_WRITE:
1327         case IDA_WRITE_MEDIA:
1328                 kfree(p);
1329                 break;
1330         default:
1331                 /* Nothing to do */
1332         }
1333 
1334         io->rcode = c->req.hdr.rcode;
1335         cmd_free(NULL, c);
1336         return(0);
1337 }
1338 
1339 /*
1340  * Commands are pre-allocated in a large block.  Here we use a simple bitmap
1341  * scheme to suballocte them to the driver.  Operations that are not time
1342  * critical (and can wait for kmalloc and possibly sleep) can pass in NULL
1343  * as the first argument to get a new command.
1344  */
1345 static cmdlist_t * cmd_alloc(ctlr_info_t *h)
1346 {
1347         cmdlist_t * c;
1348         int i;
1349 
1350         if (h == NULL) {
1351                 c = (cmdlist_t*)kmalloc(sizeof(cmdlist_t), GFP_KERNEL);
1352                 if(c==NULL)
1353                         return NULL;
1354         } else {
1355                 do {
1356                         i = find_first_zero_bit(h->cmd_pool_bits, NR_CMDS);
1357                         if (i == NR_CMDS)
1358                                 return NULL;
1359                 } while(test_and_set_bit(i%32, h->cmd_pool_bits+(i/32)) != 0);
1360                 c = h->cmd_pool + i;
1361                 h->nr_allocs++;
1362         }
1363 
1364         memset(c, 0, sizeof(cmdlist_t));
1365         c->busaddr = virt_to_bus(c);
1366         return c;
1367 }
1368 
1369 static void cmd_free(ctlr_info_t *h, cmdlist_t *c)
1370 {
1371         int i;
1372 
1373         if (h == NULL) {
1374                 kfree(c);
1375         } else {
1376                 i = c - h->cmd_pool;
1377                 clear_bit(i%32, h->cmd_pool_bits+(i/32));
1378                 h->nr_frees++;
1379         }
1380 }
1381 
1382 /***********************************************************************
1383     name:        sendcmd
1384     Send a command to an IDA using the memory mapped FIFO interface
1385     and wait for it to complete.  
1386     This routine should only be called at init time.
1387 ***********************************************************************/
1388 static int sendcmd(
1389         __u8    cmd,
1390         int     ctlr,
1391         void    *buff,
1392         size_t  size,
1393         unsigned int blk,
1394         unsigned int blkcnt,
1395         unsigned int log_unit )
1396 {
1397         cmdlist_t *c;
1398         int complete;
1399         unsigned long temp;
1400         unsigned long i;
1401         ctlr_info_t *info_p = hba[ctlr];
1402 
1403         c = cmd_alloc(info_p);
1404         if(!c)
1405                 return IO_ERROR;
1406         c->ctlr = ctlr;
1407         c->hdr.unit = log_unit;
1408         c->hdr.prio = 0;
1409         c->hdr.size = sizeof(rblk_t) >> 2;
1410         c->size += sizeof(rblk_t);
1411 
1412         /* The request information. */
1413         c->req.hdr.next = 0;
1414         c->req.hdr.rcode = 0;
1415         c->req.bp = 0;
1416         c->req.hdr.sg_cnt = 1;
1417         c->req.hdr.reserved = 0;
1418         
1419         if (size == 0)
1420                 c->req.sg[0].size = 512;
1421         else
1422                 c->req.sg[0].size = size;
1423 
1424         c->req.hdr.blk = blk;
1425         c->req.hdr.blk_cnt = blkcnt;
1426         c->req.hdr.cmd = (unsigned char) cmd;
1427         c->req.sg[0].addr = (__u32) virt_to_bus(buff);
1428         /*
1429          * Disable interrupt
1430          */
1431         info_p->access.set_intr_mask(info_p, 0);
1432         /* Make sure there is room in the command FIFO */
1433         /* Actually it should be completely empty at this time. */
1434         for (i = 200000; i > 0; i--) {
1435                 temp = info_p->access.fifo_full(info_p);
1436                 if (temp != 0) {
1437                         break;
1438                 }
1439                 udelay(10);
1440 DBG(
1441                 printk(KERN_WARNING "cpqarray ida%d: idaSendPciCmd FIFO full,"
1442                         " waiting!\n", ctlr);
1443 );
1444         } 
1445         /*
1446          * Send the cmd
1447          */
1448         info_p->access.submit_command(info_p, c);
1449         complete = pollcomplete(ctlr);
1450         if (complete != 1) {
1451                 if (complete != c->busaddr) {
1452                         printk( KERN_WARNING
1453                         "cpqarray ida%d: idaSendPciCmd "
1454                       "Invalid command list address returned! (%08lx)\n",
1455                                 ctlr, (unsigned long)complete);
1456                         cmd_free(info_p, c);
1457                         return (IO_ERROR);
1458                 }
1459         } else {
1460                 printk( KERN_WARNING
1461                         "cpqarray ida%d: idaSendPciCmd Timeout out, "
1462                         "No command list address returned!\n",
1463                         ctlr);
1464                 cmd_free(info_p, c);
1465                 return (IO_ERROR);
1466         }
1467 
1468         if (c->req.hdr.rcode & 0x00FE) {
1469                 if (!(c->req.hdr.rcode & BIG_PROBLEM)) {
1470                         printk( KERN_WARNING
1471                         "cpqarray ida%d: idaSendPciCmd, error: "
1472                                 "Controller failed at init time "
1473                                 "cmd: 0x%x, return code = 0x%x\n",
1474                                 ctlr, c->req.hdr.cmd, c->req.hdr.rcode);
1475 
1476                         cmd_free(info_p, c);
1477                         return (IO_ERROR);
1478                 }
1479         }
1480         cmd_free(info_p, c);
1481         return (IO_OK);
1482 }
1483 
1484 static int frevalidate_logvol(kdev_t dev)
1485 {
1486         return revalidate_logvol(dev, 0);
1487 }
1488 
1489 /*
1490  * revalidate_allvol is for online array config utilities.  After a
1491  * utility reconfigures the drives in the array, it can use this function
1492  * (through an ioctl) to make the driver zap any previous disk structs for
1493  * that controller and get new ones.
1494  *
1495  * Right now I'm using the getgeometry() function to do this, but this
1496  * function should probably be finer grained and allow you to revalidate one
1497  * particualar logical volume (instead of all of them on a particular
1498  * controller).
1499  */
1500 static int revalidate_allvol(kdev_t dev)
1501 {
1502         int ctlr, i;
1503         unsigned long flags;
1504 
1505         ctlr = MAJOR(dev) - MAJOR_NR;
1506         if (MINOR(dev) != 0)
1507                 return -ENXIO;
1508 
1509         spin_lock_irqsave(&io_request_lock, flags);
1510         if (hba[ctlr]->usage_count > 1) {
1511                 spin_unlock_irqrestore(&io_request_lock, flags);
1512                 printk(KERN_WARNING "cpqarray: Device busy for volume"
1513                         " revalidation (usage=%d)\n", hba[ctlr]->usage_count);
1514                 return -EBUSY;
1515         }
1516         spin_unlock_irqrestore(&io_request_lock, flags);
1517         hba[ctlr]->usage_count++;
1518 
1519         /*
1520          * Set the partition and block size structures for all volumes
1521          * on this controller to zero.  We will reread all of this data
1522          */
1523         memset(ida+(ctlr*256),            0, sizeof(struct hd_struct)*NWD*16);
1524         memset(ida_sizes+(ctlr*256),      0, sizeof(int)*NWD*16);
1525         memset(ida_blocksizes+(ctlr*256), 0, sizeof(int)*NWD*16);
1526         memset(ida_hardsizes+(ctlr*256),  0, sizeof(int)*NWD*16);
1527         memset(hba[ctlr]->drv,            0, sizeof(drv_info_t)*NWD);
1528         ida_gendisk[ctlr].nr_real = 0;
1529 
1530         /*
1531          * Tell the array controller not to give us any interupts while
1532          * we check the new geometry.  Then turn interrupts back on when
1533          * we're done.
1534          */
1535         hba[ctlr]->access.set_intr_mask(hba[ctlr], 0);
1536         getgeometry(ctlr);
1537         hba[ctlr]->access.set_intr_mask(hba[ctlr], FIFO_NOT_EMPTY);
1538 
1539         ida_geninit(ctlr);
1540         for(i=0; i<NWD; i++)
1541                 if (ida_sizes[(ctlr<<CTLR_SHIFT) + (i<<NWD_SHIFT)])
1542                         revalidate_logvol(dev+(i<<NWD_SHIFT), 2);
1543 
1544         hba[ctlr]->usage_count--;
1545         return 0;
1546 }
1547 
1548 /* Borrowed and adapted from sd.c */
1549 static int revalidate_logvol(kdev_t dev, int maxusage)
1550 {
1551         int ctlr, target;
1552         struct gendisk *gdev;
1553         unsigned long flags;
1554         int max_p;
1555         int start;
1556         int i;
1557 
1558         target = DEVICE_NR(dev);
1559         ctlr = MAJOR(dev) - MAJOR_NR;
1560         gdev = &ida_gendisk[ctlr];
1561         
1562         spin_lock_irqsave(&io_request_lock, flags);
1563         if (hba[ctlr]->drv[target].usage_count > maxusage) {
1564                 spin_unlock_irqrestore(&io_request_lock, flags);
1565                 printk(KERN_WARNING "cpqarray: Device busy for "
1566                         "revalidation (usage=%d)\n",
1567                         hba[ctlr]->drv[target].usage_count);
1568                 return -EBUSY;
1569         }
1570 
1571         hba[ctlr]->drv[target].usage_count++;
1572         spin_unlock_irqrestore(&io_request_lock, flags);
1573 
1574         max_p = gdev->max_p;
1575         start = target << gdev->minor_shift;
1576 
1577         for(i=max_p; i>=0; i--) {
1578                 int minor = start+i;
1579                 kdev_t devi = MKDEV(MAJOR_NR + ctlr, minor);
1580                 struct super_block *sb = get_super(devi);
1581                 sync_dev(devi);
1582                 if (sb) invalidate_inodes(sb);
1583                 invalidate_buffers(devi);
1584                 gdev->part[minor].start_sect = 0;       
1585                 gdev->part[minor].nr_sects = 0; 
1586 
1587                 /* reset the blocksize so we can read the partition table */
1588                 blksize_size[MAJOR_NR+ctlr][minor] = 1024;
1589         }
1590 
1591         /* 16 minors per disk... */
1592         grok_partitions(gdev, target, 16, hba[ctlr]->drv[target].nr_blks);
1593         hba[ctlr]->drv[target].usage_count--;
1594         return 0;
1595 }
1596 
1597 
1598 /********************************************************************
1599     name: pollcomplete
1600     Wait polling for a command to complete.
1601     The memory mapped FIFO is polled for the completion.
1602     Used only at init time, interrupts disabled.
1603  ********************************************************************/
1604 static int pollcomplete(int ctlr)
1605 {
1606         int done;
1607         int i;
1608 
1609         /* Wait (up to 2 seconds) for a command to complete */
1610 
1611         for (i = 200000; i > 0; i--) {
1612                 done = hba[ctlr]->access.command_completed(hba[ctlr]);
1613                 if (done == 0) {
1614                         udelay(10);     /* a short fixed delay */
1615                 } else
1616                         return (done);
1617         }
1618         /* Invalid address to tell caller we ran out of time */
1619         return 1;
1620 }
1621 /*****************************************************************
1622     start_fwbk
1623     Starts controller firmwares background processing. 
1624     Currently only the Integrated Raid controller needs this done.
1625     If the PCI mem address registers are written to after this, 
1626          data corruption may occur
1627 *****************************************************************/
1628 static void start_fwbk(int ctlr)
1629 {
1630                 id_ctlr_t *id_ctlr_buf; 
1631         int ret_code;
1632 
1633         if(     (hba[ctlr]->board_id != 0x40400E11)
1634                 && (hba[ctlr]->board_id != 0x40480E11) )
1635 
1636         /* Not a Integrated Raid, so there is nothing for us to do */
1637                 return;
1638         printk(KERN_DEBUG "cpqarray: Starting firmware's background"
1639                 " processing\n");
1640         /* Command does not return anything, but idasend command needs a 
1641                 buffer */
1642         id_ctlr_buf = (id_ctlr_t *)kmalloc(sizeof(id_ctlr_t), GFP_KERNEL);
1643         if(id_ctlr_buf==NULL)
1644         {
1645                 printk(KERN_WARNING "cpqarray: Out of memory. "
1646                         "Unable to start background processing.\n");
1647                 return;
1648         }               
1649         ret_code = sendcmd(RESUME_BACKGROUND_ACTIVITY, ctlr, 
1650                 id_ctlr_buf, 0, 0, 0, 0);
1651         if(ret_code != IO_OK)
1652                 printk(KERN_WARNING "cpqarray: Unable to start"
1653                         " background processing\n");
1654 
1655         kfree(id_ctlr_buf);
1656 }
1657 /*****************************************************************
1658     getgeometry
1659     Get ida logical volume geometry from the controller 
1660     This is a large bit of code which once existed in two flavors,
1661     It is used only at init time.
1662 *****************************************************************/
1663 static void getgeometry(int ctlr)
1664 {                               
1665         id_log_drv_t *id_ldrive;
1666         id_ctlr_t *id_ctlr_buf;
1667         sense_log_drv_stat_t *id_lstatus_buf;
1668         config_t *sense_config_buf;
1669         unsigned int log_unit, log_index;
1670         int ret_code, size;
1671         drv_info_t *drv;
1672         ctlr_info_t *info_p = hba[ctlr];
1673         int i;
1674 
1675         info_p->log_drv_map = 0;        
1676         
1677         id_ldrive = (id_log_drv_t *)kmalloc(sizeof(id_log_drv_t), GFP_KERNEL);
1678         if(id_ldrive == NULL)
1679         {
1680                 printk( KERN_ERR "cpqarray:  out of memory.\n");
1681                 return;
1682         }
1683 
1684         id_ctlr_buf = (id_ctlr_t *)kmalloc(sizeof(id_ctlr_t), GFP_KERNEL);
1685         if(id_ctlr_buf == NULL)
1686         {
1687                 kfree(id_ldrive);
1688                 printk( KERN_ERR "cpqarray:  out of memory.\n");
1689                 return;
1690         }
1691 
1692         id_lstatus_buf = (sense_log_drv_stat_t *)kmalloc(sizeof(sense_log_drv_stat_t), GFP_KERNEL);
1693         if(id_lstatus_buf == NULL)
1694         {
1695                 kfree(id_ctlr_buf);
1696                 kfree(id_ldrive);
1697                 printk( KERN_ERR "cpqarray:  out of memory.\n");
1698                 return;
1699         }
1700 
1701         sense_config_buf = (config_t *)kmalloc(sizeof(config_t), GFP_KERNEL);
1702         if(sense_config_buf == NULL)
1703         {
1704                 kfree(id_lstatus_buf);
1705                 kfree(id_ctlr_buf);
1706                 kfree(id_ldrive);
1707                 printk( KERN_ERR "cpqarray:  out of memory.\n");
1708                 return;
1709         }
1710 
1711         memset(id_ldrive, 0, sizeof(id_log_drv_t));
1712         memset(id_ctlr_buf, 0, sizeof(id_ctlr_t));
1713         memset(id_lstatus_buf, 0, sizeof(sense_log_drv_stat_t));
1714         memset(sense_config_buf, 0, sizeof(config_t));
1715 
1716         info_p->phys_drives = 0;
1717         info_p->log_drv_map = 0;
1718         info_p->drv_assign_map = 0;
1719         info_p->drv_spare_map = 0;
1720         info_p->mp_failed_drv_map = 0;  /* only initialized here */
1721         /* Get controllers info for this logical drive */
1722         ret_code = sendcmd(ID_CTLR, ctlr, id_ctlr_buf, 0, 0, 0, 0);
1723         if (ret_code == IO_ERROR) {
1724                 /*
1725                  * If can't get controller info, set the logical drive map to 0,
1726                  * so the idastubopen will fail on all logical drives
1727                  * on the controller.
1728                  */
1729                  /* Free all the buffers and return */ 
1730                 printk(KERN_ERR "cpqarray: error sending ID controller\n");
1731                 kfree(sense_config_buf);
1732                 kfree(id_lstatus_buf);
1733                 kfree(id_ctlr_buf);
1734                 kfree(id_ldrive);
1735                 return;
1736         }
1737 
1738         info_p->log_drives = id_ctlr_buf->nr_drvs;;
1739         for(i=0;i<4;i++)
1740                 info_p->firm_rev[i] = id_ctlr_buf->firm_rev[i];
1741         info_p->ctlr_sig = id_ctlr_buf->cfg_sig;
1742 
1743         printk(" (%s)\n", info_p->product_name);
1744         /*
1745          * Initialize logical drive map to zero
1746          */
1747         log_index = 0;
1748         /*
1749          * Get drive geometry for all logical drives
1750          */
1751         if (id_ctlr_buf->nr_drvs > 16)
1752                 printk(KERN_WARNING "cpqarray ida%d:  This driver supports "
1753                         "16 logical drives per controller.\n.  "
1754                         " Additional drives will not be "
1755                         "detected\n", ctlr);
1756 
1757         for (log_unit = 0;
1758              (log_index < id_ctlr_buf->nr_drvs)
1759              && (log_unit < NWD);
1760              log_unit++) {
1761 
1762                 size = sizeof(sense_log_drv_stat_t);
1763 
1764                 /*
1765                    Send "Identify logical drive status" cmd
1766                  */
1767                 ret_code = sendcmd(SENSE_LOG_DRV_STAT,
1768                              ctlr, id_lstatus_buf, size, 0, 0, log_unit);
1769                 if (ret_code == IO_ERROR) {
1770                         /*
1771                            If can't get logical drive status, set
1772                            the logical drive map to 0, so the
1773                            idastubopen will fail for all logical drives
1774                            on the controller. 
1775                          */
1776                         info_p->log_drv_map = 0;        
1777                         printk( KERN_WARNING
1778                              "cpqarray ida%d: idaGetGeometry - Controller"
1779                                 " failed to report status of logical drive %d\n"
1780                          "Access to this controller has been disabled\n",
1781                                 ctlr, log_unit);
1782                         /* Free all the buffers and return */
1783                         kfree(sense_config_buf);
1784                         kfree(id_lstatus_buf);
1785                         kfree(id_ctlr_buf);
1786                         kfree(id_ldrive);
1787                         return;
1788                 }
1789                 /*
1790                    Make sure the logical drive is configured
1791                  */
1792                 if (id_lstatus_buf->status != LOG_NOT_CONF) {
1793                         ret_code = sendcmd(ID_LOG_DRV, ctlr, id_ldrive,
1794                                sizeof(id_log_drv_t), 0, 0, log_unit);
1795                         /*
1796                            If error, the bit for this
1797                            logical drive won't be set and
1798                            idastubopen will return error. 
1799                          */
1800                         if (ret_code != IO_ERROR) {
1801                                 drv = &info_p->drv[log_unit];
1802                                 drv->blk_size = id_ldrive->blk_size;
1803                                 drv->nr_blks = id_ldrive->nr_blks;
1804                                 drv->cylinders = id_ldrive->drv.cyl;
1805                                 drv->heads = id_ldrive->drv.heads;
1806                                 drv->sectors = id_ldrive->drv.sect_per_track;
1807                                 info_p->log_drv_map |=  (1 << log_unit);
1808 
1809         printk(KERN_INFO "cpqarray ida/c%dd%d: blksz=%d nr_blks=%d\n",
1810                 ctlr, log_unit, drv->blk_size, drv->nr_blks);
1811                                 ret_code = sendcmd(SENSE_CONFIG,
1812                                                   ctlr, sense_config_buf,
1813                                  sizeof(config_t), 0, 0, log_unit);
1814                                 if (ret_code == IO_ERROR) {
1815                                         info_p->log_drv_map = 0;
1816                                         /* Free all the buffers and return */
1817                                         printk(KERN_ERR "cpqarray: error sending sense config\n");
1818                                         kfree(sense_config_buf);
1819                                         kfree(id_lstatus_buf);
1820                                         kfree(id_ctlr_buf);
1821                                         kfree(id_ldrive);
1822                                         return;
1823 
1824                                 }
1825                                 info_p->phys_drives =
1826                                     sense_config_buf->ctlr_phys_drv;
1827                                 info_p->drv_assign_map
1828                                     |= sense_config_buf->drv_asgn_map;
1829                                 info_p->drv_assign_map
1830                                     |= sense_config_buf->spare_asgn_map;
1831                                 info_p->drv_spare_map
1832                                     |= sense_config_buf->spare_asgn_map;
1833                         }       /* end of if no error on id_ldrive */
1834                         log_index = log_index + 1;
1835                 }               /* end of if logical drive configured */
1836         }                       /* end of for log_unit */
1837         kfree(sense_config_buf);
1838         kfree(id_ldrive);
1839         kfree(id_lstatus_buf);
1840         kfree(id_ctlr_buf);
1841         return;
1842 
1843 }
1844 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.