Pull sim-fixes into release branch
[linux-2.6] / drivers / scsi / aacraid / commctrl.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  * Module Name:
25  *  commctrl.c
26  *
27  * Abstract: Contains all routines for control of the AFA comm layer
28  *
29  */
30
31 #include <linux/kernel.h>
32 #include <linux/init.h>
33 #include <linux/types.h>
34 #include <linux/sched.h>
35 #include <linux/pci.h>
36 #include <linux/spinlock.h>
37 #include <linux/slab.h>
38 #include <linux/completion.h>
39 #include <linux/dma-mapping.h>
40 #include <linux/blkdev.h>
41 #include <asm/semaphore.h>
42 #include <asm/uaccess.h>
43
44 #include "aacraid.h"
45
46 /**
47  *      ioctl_send_fib  -       send a FIB from userspace
48  *      @dev:   adapter is being processed
49  *      @arg:   arguments to the ioctl call
50  *      
51  *      This routine sends a fib to the adapter on behalf of a user level
52  *      program.
53  */
54 # define AAC_DEBUG_PREAMBLE     KERN_INFO
55 # define AAC_DEBUG_POSTAMBLE
56  
57 static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
58 {
59         struct hw_fib * kfib;
60         struct fib *fibptr;
61         struct hw_fib * hw_fib = (struct hw_fib *)0;
62         dma_addr_t hw_fib_pa = (dma_addr_t)0LL;
63         unsigned size;
64         int retval;
65
66         fibptr = fib_alloc(dev);
67         if(fibptr == NULL) {
68                 return -ENOMEM;
69         }
70                 
71         kfib = fibptr->hw_fib;
72         /*
73          *      First copy in the header so that we can check the size field.
74          */
75         if (copy_from_user((void *)kfib, arg, sizeof(struct aac_fibhdr))) {
76                 fib_free(fibptr);
77                 return -EFAULT;
78         }
79         /*
80          *      Since we copy based on the fib header size, make sure that we
81          *      will not overrun the buffer when we copy the memory. Return
82          *      an error if we would.
83          */
84         size = le16_to_cpu(kfib->header.Size) + sizeof(struct aac_fibhdr);
85         if (size < le16_to_cpu(kfib->header.SenderSize))
86                 size = le16_to_cpu(kfib->header.SenderSize);
87         if (size > dev->max_fib_size) {
88                 /* Highjack the hw_fib */
89                 hw_fib = fibptr->hw_fib;
90                 hw_fib_pa = fibptr->hw_fib_pa;
91                 fibptr->hw_fib = kfib = pci_alloc_consistent(dev->pdev, size, &fibptr->hw_fib_pa);
92                 memset(((char *)kfib) + dev->max_fib_size, 0, size - dev->max_fib_size);
93                 memcpy(kfib, hw_fib, dev->max_fib_size);
94         }
95
96         if (copy_from_user(kfib, arg, size)) {
97                 retval = -EFAULT;
98                 goto cleanup;
99         }
100
101         if (kfib->header.Command == cpu_to_le16(TakeABreakPt)) {
102                 aac_adapter_interrupt(dev);
103                 /*
104                  * Since we didn't really send a fib, zero out the state to allow 
105                  * cleanup code not to assert.
106                  */
107                 kfib->header.XferState = 0;
108         } else {
109                 retval = fib_send(le16_to_cpu(kfib->header.Command), fibptr,
110                                 le16_to_cpu(kfib->header.Size) , FsaNormal,
111                                 1, 1, NULL, NULL);
112                 if (retval) {
113                         goto cleanup;
114                 }
115                 if (fib_complete(fibptr) != 0) {
116                         retval = -EINVAL;
117                         goto cleanup;
118                 }
119         }
120         /*
121          *      Make sure that the size returned by the adapter (which includes
122          *      the header) is less than or equal to the size of a fib, so we
123          *      don't corrupt application data. Then copy that size to the user
124          *      buffer. (Don't try to add the header information again, since it
125          *      was already included by the adapter.)
126          */
127
128         retval = 0;
129         if (copy_to_user(arg, (void *)kfib, size))
130                 retval = -EFAULT;
131 cleanup:
132         if (hw_fib) {
133                 pci_free_consistent(dev->pdev, size, kfib, fibptr->hw_fib_pa);
134                 fibptr->hw_fib_pa = hw_fib_pa;
135                 fibptr->hw_fib = hw_fib;
136         }
137         fib_free(fibptr);
138         return retval;
139 }
140
141 /**
142  *      open_getadapter_fib     -       Get the next fib
143  *
144  *      This routine will get the next Fib, if available, from the AdapterFibContext
145  *      passed in from the user.
146  */
147
148 static int open_getadapter_fib(struct aac_dev * dev, void __user *arg)
149 {
150         struct aac_fib_context * fibctx;
151         int status;
152
153         fibctx = kmalloc(sizeof(struct aac_fib_context), GFP_KERNEL);
154         if (fibctx == NULL) {
155                 status = -ENOMEM;
156         } else {
157                 unsigned long flags;
158                 struct list_head * entry;
159                 struct aac_fib_context * context;
160
161                 fibctx->type = FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT;
162                 fibctx->size = sizeof(struct aac_fib_context);
163                 /*
164                  *      Yes yes, I know this could be an index, but we have a
165                  * better guarantee of uniqueness for the locked loop below.
166                  * Without the aid of a persistent history, this also helps
167                  * reduce the chance that the opaque context would be reused.
168                  */
169                 fibctx->unique = (u32)((ulong)fibctx & 0xFFFFFFFF);
170                 /*
171                  *      Initialize the mutex used to wait for the next AIF.
172                  */
173                 init_MUTEX_LOCKED(&fibctx->wait_sem);
174                 fibctx->wait = 0;
175                 /*
176                  *      Initialize the fibs and set the count of fibs on
177                  *      the list to 0.
178                  */
179                 fibctx->count = 0;
180                 INIT_LIST_HEAD(&fibctx->fib_list);
181                 fibctx->jiffies = jiffies/HZ;
182                 /*
183                  *      Now add this context onto the adapter's 
184                  *      AdapterFibContext list.
185                  */
186                 spin_lock_irqsave(&dev->fib_lock, flags);
187                 /* Ensure that we have a unique identifier */
188                 entry = dev->fib_list.next;
189                 while (entry != &dev->fib_list) {
190                         context = list_entry(entry, struct aac_fib_context, next);
191                         if (context->unique == fibctx->unique) {
192                                 /* Not unique (32 bits) */
193                                 fibctx->unique++;
194                                 entry = dev->fib_list.next;
195                         } else {
196                                 entry = entry->next;
197                         }
198                 }
199                 list_add_tail(&fibctx->next, &dev->fib_list);
200                 spin_unlock_irqrestore(&dev->fib_lock, flags);
201                 if (copy_to_user(arg,  &fibctx->unique, 
202                                                 sizeof(fibctx->unique))) {
203                         status = -EFAULT;
204                 } else {
205                         status = 0;
206                 }       
207         }
208         return status;
209 }
210
211 /**
212  *      next_getadapter_fib     -       get the next fib
213  *      @dev: adapter to use
214  *      @arg: ioctl argument
215  *      
216  *      This routine will get the next Fib, if available, from the AdapterFibContext
217  *      passed in from the user.
218  */
219
220 static int next_getadapter_fib(struct aac_dev * dev, void __user *arg)
221 {
222         struct fib_ioctl f;
223         struct fib *fib;
224         struct aac_fib_context *fibctx;
225         int status;
226         struct list_head * entry;
227         unsigned long flags;
228         
229         if(copy_from_user((void *)&f, arg, sizeof(struct fib_ioctl)))
230                 return -EFAULT;
231         /*
232          *      Verify that the HANDLE passed in was a valid AdapterFibContext
233          *
234          *      Search the list of AdapterFibContext addresses on the adapter
235          *      to be sure this is a valid address
236          */
237         entry = dev->fib_list.next;
238         fibctx = NULL;
239
240         while (entry != &dev->fib_list) {
241                 fibctx = list_entry(entry, struct aac_fib_context, next);
242                 /*
243                  *      Extract the AdapterFibContext from the Input parameters.
244                  */
245                 if (fibctx->unique == f.fibctx) {   /* We found a winner */
246                         break;
247                 }
248                 entry = entry->next;
249                 fibctx = NULL;
250         }
251         if (!fibctx) {
252                 dprintk ((KERN_INFO "Fib Context not found\n"));
253                 return -EINVAL;
254         }
255
256         if((fibctx->type != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) ||
257                  (fibctx->size != sizeof(struct aac_fib_context))) {
258                 dprintk ((KERN_INFO "Fib Context corrupt?\n"));
259                 return -EINVAL;
260         }
261         status = 0;
262         spin_lock_irqsave(&dev->fib_lock, flags);
263         /*
264          *      If there are no fibs to send back, then either wait or return
265          *      -EAGAIN
266          */
267 return_fib:
268         if (!list_empty(&fibctx->fib_list)) {
269                 struct list_head * entry;
270                 /*
271                  *      Pull the next fib from the fibs
272                  */
273                 entry = fibctx->fib_list.next;
274                 list_del(entry);
275                 
276                 fib = list_entry(entry, struct fib, fiblink);
277                 fibctx->count--;
278                 spin_unlock_irqrestore(&dev->fib_lock, flags);
279                 if (copy_to_user(f.fib, fib->hw_fib, sizeof(struct hw_fib))) {
280                         kfree(fib->hw_fib);
281                         kfree(fib);
282                         return -EFAULT;
283                 }       
284                 /*
285                  *      Free the space occupied by this copy of the fib.
286                  */
287                 kfree(fib->hw_fib);
288                 kfree(fib);
289                 status = 0;
290         } else {
291                 spin_unlock_irqrestore(&dev->fib_lock, flags);
292                 if (f.wait) {
293                         if(down_interruptible(&fibctx->wait_sem) < 0) {
294                                 status = -EINTR;
295                         } else {
296                                 /* Lock again and retry */
297                                 spin_lock_irqsave(&dev->fib_lock, flags);
298                                 goto return_fib;
299                         }
300                 } else {
301                         status = -EAGAIN;
302                 }       
303         }
304         fibctx->jiffies = jiffies/HZ;
305         return status;
306 }
307
308 int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context * fibctx)
309 {
310         struct fib *fib;
311
312         /*
313          *      First free any FIBs that have not been consumed.
314          */
315         while (!list_empty(&fibctx->fib_list)) {
316                 struct list_head * entry;
317                 /*
318                  *      Pull the next fib from the fibs
319                  */
320                 entry = fibctx->fib_list.next;
321                 list_del(entry);
322                 fib = list_entry(entry, struct fib, fiblink);
323                 fibctx->count--;
324                 /*
325                  *      Free the space occupied by this copy of the fib.
326                  */
327                 kfree(fib->hw_fib);
328                 kfree(fib);
329         }
330         /*
331          *      Remove the Context from the AdapterFibContext List
332          */
333         list_del(&fibctx->next);
334         /*
335          *      Invalidate context
336          */
337         fibctx->type = 0;
338         /*
339          *      Free the space occupied by the Context
340          */
341         kfree(fibctx);
342         return 0;
343 }
344
345 /**
346  *      close_getadapter_fib    -       close down user fib context
347  *      @dev: adapter
348  *      @arg: ioctl arguments
349  *
350  *      This routine will close down the fibctx passed in from the user.
351  */
352  
353 static int close_getadapter_fib(struct aac_dev * dev, void __user *arg)
354 {
355         struct aac_fib_context *fibctx;
356         int status;
357         unsigned long flags;
358         struct list_head * entry;
359
360         /*
361          *      Verify that the HANDLE passed in was a valid AdapterFibContext
362          *
363          *      Search the list of AdapterFibContext addresses on the adapter
364          *      to be sure this is a valid address
365          */
366
367         entry = dev->fib_list.next;
368         fibctx = NULL;
369
370         while(entry != &dev->fib_list) {
371                 fibctx = list_entry(entry, struct aac_fib_context, next);
372                 /*
373                  *      Extract the fibctx from the input parameters
374                  */
375                 if (fibctx->unique == (u32)(unsigned long)arg) {   
376                         /* We found a winner */
377                         break;
378                 }
379                 entry = entry->next;
380                 fibctx = NULL;
381         }
382
383         if (!fibctx)
384                 return 0; /* Already gone */
385
386         if((fibctx->type != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) ||
387                  (fibctx->size != sizeof(struct aac_fib_context)))
388                 return -EINVAL;
389         spin_lock_irqsave(&dev->fib_lock, flags);
390         status = aac_close_fib_context(dev, fibctx);
391         spin_unlock_irqrestore(&dev->fib_lock, flags);
392         return status;
393 }
394
395 /**
396  *      check_revision  -       close down user fib context
397  *      @dev: adapter
398  *      @arg: ioctl arguments
399  *
400  *      This routine returns the driver version.
401  *      Under Linux, there have been no version incompatibilities, so this is 
402  *      simple!
403  */
404
405 static int check_revision(struct aac_dev *dev, void __user *arg)
406 {
407         struct revision response;
408         char *driver_version = aac_driver_version;
409         u32 version;
410
411         response.compat = cpu_to_le32(1);
412         version = (simple_strtol(driver_version, 
413                                 &driver_version, 10) << 24) | 0x00000400;
414         version += simple_strtol(driver_version + 1, &driver_version, 10) << 16;
415         version += simple_strtol(driver_version + 1, NULL, 10);
416         response.version = cpu_to_le32(version);
417 #       if (defined(AAC_DRIVER_BUILD))
418                 response.build = cpu_to_le32(AAC_DRIVER_BUILD);
419 #       else
420                 response.build = cpu_to_le32(9999);
421 #       endif
422
423         if (copy_to_user(arg, &response, sizeof(response)))
424                 return -EFAULT;
425         return 0;
426 }
427
428
429 /**
430  *
431  * aac_send_raw_scb
432  *
433  */
434
435 static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
436 {
437         struct fib* srbfib;
438         int status;
439         struct aac_srb *srbcmd = NULL;
440         struct user_aac_srb *user_srbcmd = NULL;
441         struct user_aac_srb __user *user_srb = arg;
442         struct aac_srb_reply __user *user_reply;
443         struct aac_srb_reply* reply;
444         u32 fibsize = 0;
445         u32 flags = 0;
446         s32 rcode = 0;
447         u32 data_dir;
448         void __user *sg_user[32];
449         void *sg_list[32];
450         u32   sg_indx = 0;
451         u32 byte_count = 0;
452         u32 actual_fibsize = 0;
453         int i;
454
455
456         if (!capable(CAP_SYS_ADMIN)){
457                 dprintk((KERN_DEBUG"aacraid: No permission to send raw srb\n")); 
458                 return -EPERM;
459         }
460         /*
461          *      Allocate and initialize a Fib then setup a BlockWrite command
462          */
463         if (!(srbfib = fib_alloc(dev))) {
464                 return -ENOMEM;
465         }
466         fib_init(srbfib);
467
468         srbcmd = (struct aac_srb*) fib_data(srbfib);
469
470         memset(sg_list, 0, sizeof(sg_list)); /* cleanup may take issue */
471         if(copy_from_user(&fibsize, &user_srb->count,sizeof(u32))){
472                 dprintk((KERN_DEBUG"aacraid: Could not copy data size from user\n")); 
473                 rcode = -EFAULT;
474                 goto cleanup;
475         }
476
477         if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))) {
478                 rcode = -EINVAL;
479                 goto cleanup;
480         }
481
482         user_srbcmd = kmalloc(fibsize, GFP_KERNEL);
483         if (!user_srbcmd) {
484                 dprintk((KERN_DEBUG"aacraid: Could not make a copy of the srb\n"));
485                 rcode = -ENOMEM;
486                 goto cleanup;
487         }
488         if(copy_from_user(user_srbcmd, user_srb,fibsize)){
489                 dprintk((KERN_DEBUG"aacraid: Could not copy srb from user\n")); 
490                 rcode = -EFAULT;
491                 goto cleanup;
492         }
493
494         user_reply = arg+fibsize;
495
496         flags = user_srbcmd->flags; /* from user in cpu order */
497         // Fix up srb for endian and force some values
498
499         srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);       // Force this
500         srbcmd->channel  = cpu_to_le32(user_srbcmd->channel);
501         srbcmd->id       = cpu_to_le32(user_srbcmd->id);
502         srbcmd->lun      = cpu_to_le32(user_srbcmd->lun);
503         srbcmd->timeout  = cpu_to_le32(user_srbcmd->timeout);
504         srbcmd->flags    = cpu_to_le32(flags);
505         srbcmd->retry_limit = 0; // Obsolete parameter
506         srbcmd->cdb_size = cpu_to_le32(user_srbcmd->cdb_size);
507         memcpy(srbcmd->cdb, user_srbcmd->cdb, sizeof(srbcmd->cdb));
508         
509         switch (flags & (SRB_DataIn | SRB_DataOut)) {
510         case SRB_DataOut:
511                 data_dir = DMA_TO_DEVICE;
512                 break;
513         case (SRB_DataIn | SRB_DataOut):
514                 data_dir = DMA_BIDIRECTIONAL;
515                 break;
516         case SRB_DataIn:
517                 data_dir = DMA_FROM_DEVICE;
518                 break;
519         default:
520                 data_dir = DMA_NONE;
521         }
522         if (user_srbcmd->sg.count > (sizeof(sg_list)/sizeof(sg_list[0]))) {
523                 dprintk((KERN_DEBUG"aacraid: too many sg entries %d\n",
524                   le32_to_cpu(srbcmd->sg.count)));
525                 rcode = -EINVAL;
526                 goto cleanup;
527         }
528         if (dev->dac_support == 1) {
529                 struct user_sgmap64* upsg = (struct user_sgmap64*)&user_srbcmd->sg;
530                 struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg;
531                 struct user_sgmap* usg;
532                 byte_count = 0;
533
534                 /*
535                  * This should also catch if user used the 32 bit sgmap
536                  */
537                 actual_fibsize = sizeof(struct aac_srb) - 
538                         sizeof(struct sgentry) +
539                         ((upsg->count & 0xff) * 
540                         sizeof(struct sgentry));
541                 if(actual_fibsize != fibsize){ // User made a mistake - should not continue
542                         dprintk((KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"));
543                         rcode = -EINVAL;
544                         goto cleanup;
545                 }
546                 usg = kmalloc(actual_fibsize - sizeof(struct aac_srb)
547                   + sizeof(struct sgmap), GFP_KERNEL);
548                 if (!usg) {
549                         dprintk((KERN_DEBUG"aacraid: Allocation error in Raw SRB command\n"));
550                         rcode = -ENOMEM;
551                         goto cleanup;
552                 }
553                 memcpy (usg, upsg, actual_fibsize - sizeof(struct aac_srb)
554                   + sizeof(struct sgmap));
555                 actual_fibsize = sizeof(struct aac_srb) - 
556                         sizeof(struct sgentry) + ((usg->count & 0xff) * 
557                                 sizeof(struct sgentry64));
558                 if ((data_dir == DMA_NONE) && upsg->count) {
559                         kfree (usg);
560                         dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
561                         rcode = -EINVAL;
562                         goto cleanup;
563                 }
564
565                 for (i = 0; i < usg->count; i++) {
566                         u64 addr;
567                         void* p;
568                         /* Does this really need to be GFP_DMA? */
569                         p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
570                         if(p == 0) {
571                                 kfree (usg);
572                                 dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
573                                   usg->sg[i].count,i,usg->count));
574                                 rcode = -ENOMEM;
575                                 goto cleanup;
576                         }
577                         sg_user[i] = (void __user *)usg->sg[i].addr;
578                         sg_list[i] = p; // save so we can clean up later
579                         sg_indx = i;
580
581                         if( flags & SRB_DataOut ){
582                                 if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){
583                                         kfree (usg);
584                                         dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); 
585                                         rcode = -EFAULT;
586                                         goto cleanup;
587                                 }
588                         }
589                         addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir);
590
591                         psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
592                         psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
593                         psg->sg[i].count = cpu_to_le32(usg->sg[i].count);  
594                         byte_count += usg->sg[i].count;
595                 }
596                 kfree (usg);
597
598                 srbcmd->count = cpu_to_le32(byte_count);
599                 psg->count = cpu_to_le32(sg_indx+1);
600                 status = fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL);
601         } else {
602                 struct user_sgmap* upsg = &user_srbcmd->sg;
603                 struct sgmap* psg = &srbcmd->sg;
604                 byte_count = 0;
605
606                 actual_fibsize = sizeof (struct aac_srb) + (((user_srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry));
607                 if(actual_fibsize != fibsize){ // User made a mistake - should not continue
608                         dprintk((KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"));
609                         rcode = -EINVAL;
610                         goto cleanup;
611                 }
612                 if ((data_dir == DMA_NONE) && upsg->count) {
613                         dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
614                         rcode = -EINVAL;
615                         goto cleanup;
616                 }
617                 for (i = 0; i < upsg->count; i++) {
618                         dma_addr_t addr; 
619                         void* p;
620                         p = kmalloc(upsg->sg[i].count, GFP_KERNEL);
621                         if(p == 0) {
622                                 dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
623                                   upsg->sg[i].count, i, upsg->count));
624                                 rcode = -ENOMEM;
625                                 goto cleanup;
626                         }
627                         sg_user[i] = (void __user *)upsg->sg[i].addr;
628                         sg_list[i] = p; // save so we can clean up later
629                         sg_indx = i;
630
631                         if( flags & SRB_DataOut ){
632                                 if(copy_from_user(p, sg_user[i],
633                                                 upsg->sg[i].count)) {
634                                         dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); 
635                                         rcode = -EFAULT;
636                                         goto cleanup;
637                                 }
638                         }
639                         addr = pci_map_single(dev->pdev, p,
640                                 upsg->sg[i].count, data_dir);
641
642                         psg->sg[i].addr = cpu_to_le32(addr);
643                         psg->sg[i].count = cpu_to_le32(upsg->sg[i].count);  
644                         byte_count += upsg->sg[i].count;
645                 }
646                 srbcmd->count = cpu_to_le32(byte_count);
647                 psg->count = cpu_to_le32(sg_indx+1);
648                 status = fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL);
649         }
650
651         if (status != 0){
652                 dprintk((KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n")); 
653                 rcode = -ENXIO;
654                 goto cleanup;
655         }
656
657         if( flags & SRB_DataIn ) {
658                 for(i = 0 ; i <= sg_indx; i++){
659                         byte_count = le32_to_cpu((dev->dac_support == 1)
660                               ? ((struct sgmap64*)&srbcmd->sg)->sg[i].count
661                               : srbcmd->sg.sg[i].count);
662                         if(copy_to_user(sg_user[i], sg_list[i], byte_count)){
663                                 dprintk((KERN_DEBUG"aacraid: Could not copy sg data to user\n")); 
664                                 rcode = -EFAULT;
665                                 goto cleanup;
666
667                         }
668                 }
669         }
670
671         reply = (struct aac_srb_reply *) fib_data(srbfib);
672         if(copy_to_user(user_reply,reply,sizeof(struct aac_srb_reply))){
673                 dprintk((KERN_DEBUG"aacraid: Could not copy reply to user\n")); 
674                 rcode = -EFAULT;
675                 goto cleanup;
676         }
677
678 cleanup:
679         kfree(user_srbcmd);
680         for(i=0; i <= sg_indx; i++){
681                 kfree(sg_list[i]);
682         }
683         fib_complete(srbfib);
684         fib_free(srbfib);
685
686         return rcode;
687 }
688
689 struct aac_pci_info {
690         u32 bus;
691         u32 slot;
692 };
693
694
695 static int aac_get_pci_info(struct aac_dev* dev, void __user *arg)
696 {
697         struct aac_pci_info pci_info;
698
699         pci_info.bus = dev->pdev->bus->number;
700         pci_info.slot = PCI_SLOT(dev->pdev->devfn);
701
702        if (copy_to_user(arg, &pci_info, sizeof(struct aac_pci_info))) {
703                dprintk((KERN_DEBUG "aacraid: Could not copy pci info\n"));
704                return -EFAULT;
705         }
706         return 0;
707 }
708  
709
710 int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg)
711 {
712         int status;
713         
714         /*
715          *      HBA gets first crack
716          */
717          
718         status = aac_dev_ioctl(dev, cmd, arg);
719         if(status != -ENOTTY)
720                 return status;
721
722         switch (cmd) {
723         case FSACTL_MINIPORT_REV_CHECK:
724                 status = check_revision(dev, arg);
725                 break;
726         case FSACTL_SEND_LARGE_FIB:
727         case FSACTL_SENDFIB:
728                 status = ioctl_send_fib(dev, arg);
729                 break;
730         case FSACTL_OPEN_GET_ADAPTER_FIB:
731                 status = open_getadapter_fib(dev, arg);
732                 break;
733         case FSACTL_GET_NEXT_ADAPTER_FIB:
734                 status = next_getadapter_fib(dev, arg);
735                 break;
736         case FSACTL_CLOSE_GET_ADAPTER_FIB:
737                 status = close_getadapter_fib(dev, arg);
738                 break;
739         case FSACTL_SEND_RAW_SRB:
740                 status = aac_send_raw_srb(dev,arg);
741                 break;
742         case FSACTL_GET_PCI_INFO:
743                 status = aac_get_pci_info(dev,arg);
744                 break;
745         default:
746                 status = -ENOTTY;
747                 break;  
748         }
749         return status;
750 }
751