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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [scsi/] [aacraid/] [commctrl.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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