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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [scsi/] [sg.c] - Blame information for rev 199

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 *  History:
3
 *  Started: Aug 9 by Lawrence Foard (entropy@world.std.com),
4
 *           to allow user process control of SCSI devices.
5
 *  Development Sponsored by Killy Corp. NY NY
6
 *
7
 *  Borrows code from st driver.
8
 */
9
#include <linux/module.h>
10
 
11
#include <linux/fs.h>
12
#include <linux/kernel.h>
13
#include <linux/sched.h>
14
#include <linux/string.h>
15
#include <linux/mm.h>
16
#include <linux/errno.h>
17
#include <linux/mtio.h>
18
#include <linux/ioctl.h>
19
#include <linux/fcntl.h>
20
#include <asm/io.h>
21
#include <asm/segment.h>
22
#include <asm/system.h>
23
 
24
#include <linux/blk.h>
25
#include "scsi.h"
26
#include "hosts.h"
27
#include <scsi/scsi_ioctl.h>
28
#include <scsi/sg.h>
29
 
30
static int sg_init(void);
31
static int sg_attach(Scsi_Device *);
32
static int sg_detect(Scsi_Device *);
33
static void sg_detach(Scsi_Device *);
34
 
35
 
36
struct Scsi_Device_Template sg_template = {NULL, NULL, "sg", NULL, 0xff,
37
                                               SCSI_GENERIC_MAJOR, 0, 0, 0, 0,
38
                                               sg_detect, sg_init,
39
                                               NULL, sg_attach, sg_detach};
40
 
41
#ifdef SG_BIG_BUFF
42
static char *big_buff = NULL;
43
static struct wait_queue *big_wait;   /* wait for buffer available */
44
static int big_inuse=0;
45
#endif
46
 
47
struct scsi_generic
48
{
49
    Scsi_Device *device;
50
    int users;   /* how many people have it open? */
51
    struct wait_queue *generic_wait; /* wait for device to be available */
52
    struct wait_queue *read_wait;    /* wait for response */
53
    struct wait_queue *write_wait;   /* wait for free buffer */
54
    int timeout; /* current default value for device */
55
    int buff_len; /* length of current buffer */
56
    char *buff;   /* the buffer */
57
    struct sg_header header; /* header of pending command */
58
    char exclude; /* opened for exclusive access */
59
    char pending;  /* don't accept writes now */
60
    char complete; /* command complete allow a read */
61
};
62
 
63
static struct scsi_generic *scsi_generics=NULL;
64
static void sg_free(char *buff,int size);
65
 
66
static int sg_ioctl(struct inode * inode,struct file * file,
67
                    unsigned int cmd_in, unsigned long arg)
68
{
69
    int result;
70
    int dev = MINOR(inode->i_rdev);
71
    if ((dev<0) || (dev>=sg_template.dev_max))
72
        return -ENXIO;
73
    switch(cmd_in)
74
    {
75
    case SG_SET_TIMEOUT:
76
        result = verify_area(VERIFY_READ, (const void *)arg, sizeof(int));
77
        if (result) return result;
78
 
79
        scsi_generics[dev].timeout=get_user((int *) arg);
80
        return 0;
81
    case SG_GET_TIMEOUT:
82
        return scsi_generics[dev].timeout;
83
    case SCSI_IOCTL_SEND_COMMAND:
84
        /*
85
          Allow SCSI_IOCTL_SEND_COMMAND without checking suser() since the
86
          user already has read/write access to the generic device and so
87
          can execute arbitrary SCSI commands.
88
        */
89
        return scsi_ioctl_send_command(scsi_generics[dev].device, (void *) arg);
90
    default:
91
        return scsi_ioctl(scsi_generics[dev].device, cmd_in, (void *) arg);
92
    }
93
}
94
 
95
static int sg_open(struct inode * inode, struct file * filp)
96
{
97
    int dev=MINOR(inode->i_rdev);
98
    int flags=filp->f_flags;
99
    if (dev>=sg_template.dev_max || !scsi_generics[dev].device)
100
        return -ENXIO;
101
    if (O_RDWR!=(flags & O_ACCMODE))
102
        return -EACCES;
103
 
104
  /*
105
   * If we want exclusive access, then wait until the device is not
106
   * busy, and then set the flag to prevent anyone else from using it.
107
   */
108
    if (flags & O_EXCL)
109
    {
110
        while(scsi_generics[dev].users)
111
        {
112
            if (flags & O_NONBLOCK)
113
                return -EBUSY;
114
            interruptible_sleep_on(&scsi_generics[dev].generic_wait);
115
            if (current->signal & ~current->blocked)
116
                return -ERESTARTSYS;
117
        }
118
        scsi_generics[dev].exclude=1;
119
    }
120
    else
121
        /*
122
         * Wait until nobody has an exclusive open on
123
         * this device.
124
         */
125
        while(scsi_generics[dev].exclude)
126
        {
127
            if (flags & O_NONBLOCK)
128
                return -EBUSY;
129
            interruptible_sleep_on(&scsi_generics[dev].generic_wait);
130
            if (current->signal & ~current->blocked)
131
                return -ERESTARTSYS;
132
        }
133
 
134
    /*
135
     * OK, we should have grabbed the device.  Mark the thing so
136
     * that other processes know that we have it, and initialize the
137
     * state variables to known values.
138
     */
139
    if (!scsi_generics[dev].users
140
        && scsi_generics[dev].pending
141
        && scsi_generics[dev].complete)
142
    {
143
        if (scsi_generics[dev].buff != NULL)
144
            sg_free(scsi_generics[dev].buff,scsi_generics[dev].buff_len);
145
        scsi_generics[dev].buff=NULL;
146
        scsi_generics[dev].pending=0;
147
    }
148
    if (!scsi_generics[dev].users)
149
        scsi_generics[dev].timeout=SG_DEFAULT_TIMEOUT;
150
    if (scsi_generics[dev].device->host->hostt->usage_count)
151
        (*scsi_generics[dev].device->host->hostt->usage_count)++;
152
    if(sg_template.usage_count) (*sg_template.usage_count)++;
153
    scsi_generics[dev].users++;
154
    return 0;
155
}
156
 
157
static void sg_close(struct inode * inode, struct file * filp)
158
{
159
    int dev=MINOR(inode->i_rdev);
160
    scsi_generics[dev].users--;
161
    if (scsi_generics[dev].device->host->hostt->usage_count)
162
        (*scsi_generics[dev].device->host->hostt->usage_count)--;
163
    if(sg_template.usage_count) (*sg_template.usage_count)--;
164
    scsi_generics[dev].exclude=0;
165
    wake_up(&scsi_generics[dev].generic_wait);
166
}
167
 
168
static char *sg_malloc(int size)
169
{
170
    if (size<=4096)
171
        return (char *) scsi_malloc(size);
172
#ifdef SG_BIG_BUFF
173
    if (size<=SG_BIG_BUFF)
174
    {
175
        while(big_inuse)
176
        {
177
            interruptible_sleep_on(&big_wait);
178
            if (current->signal & ~current->blocked)
179
                return NULL;
180
        }
181
        big_inuse=1;
182
        return big_buff;
183
    }
184
#endif   
185
    return NULL;
186
}
187
 
188
static void sg_free(char *buff,int size)
189
{
190
#ifdef SG_BIG_BUFF
191
    if (buff==big_buff)
192
    {
193
        big_inuse=0;
194
        wake_up(&big_wait);
195
        return;
196
    }
197
#endif
198
    scsi_free(buff,size);
199
}
200
 
201
/*
202
 * Read back the results of a previous command.  We use the pending and
203
 * complete semaphores to tell us whether the buffer is available for us
204
 * and whether the command is actually done.
205
 */
206
static int sg_read(struct inode *inode,struct file *filp,char *buf,int count)
207
{
208
    int dev=MINOR(inode->i_rdev);
209
    int i;
210
    unsigned long flags;
211
    struct scsi_generic *device=&scsi_generics[dev];
212
    if ((i=verify_area(VERIFY_WRITE,buf,count)))
213
        return i;
214
 
215
    /*
216
     * Wait until the command is actually done.
217
     */
218
    save_flags(flags);
219
    cli();
220
    while(!device->pending || !device->complete)
221
    {
222
        if (filp->f_flags & O_NONBLOCK)
223
        {
224
            restore_flags(flags);
225
            return -EAGAIN;
226
        }
227
        interruptible_sleep_on(&device->read_wait);
228
        if (current->signal & ~current->blocked)
229
        {
230
            restore_flags(flags);
231
            return -ERESTARTSYS;
232
        }
233
    }
234
    restore_flags(flags);
235
 
236
    /*
237
     * Now copy the result back to the user buffer.
238
     */
239
    device->header.pack_len=device->header.reply_len;
240
 
241
    if (count>=sizeof(struct sg_header))
242
    {
243
        memcpy_tofs(buf,&device->header,sizeof(struct sg_header));
244
        buf+=sizeof(struct sg_header);
245
        if (count>device->header.pack_len)
246
            count=device->header.pack_len;
247
        if (count > sizeof(struct sg_header)) {
248
            memcpy_tofs(buf,device->buff,count-sizeof(struct sg_header));
249
        }
250
    }
251
    else
252
        count= device->header.result==0 ? 0 : -EIO;
253
 
254
    /*
255
     * Clean up, and release the device so that we can send another
256
     * command.
257
     */
258
    sg_free(device->buff,device->buff_len);
259
    device->buff = NULL;
260
    device->pending=0;
261
    wake_up(&device->write_wait);
262
    return count;
263
}
264
 
265
/*
266
 * This function is called by the interrupt handler when we
267
 * actually have a command that is complete.  Change the
268
 * flags to indicate that we have a result.
269
 */
270
static void sg_command_done(Scsi_Cmnd * SCpnt)
271
{
272
    int dev = MINOR(SCpnt->request.rq_dev);
273
    struct scsi_generic *device = &scsi_generics[dev];
274
    if (!device->pending)
275
    {
276
        printk("unexpected done for sg %d\n",dev);
277
        SCpnt->request.rq_status = RQ_INACTIVE;
278
        return;
279
    }
280
 
281
    /*
282
     * See if the command completed normally, or whether something went
283
     * wrong.
284
     */
285
    memcpy(device->header.sense_buffer, SCpnt->sense_buffer,
286
           sizeof(SCpnt->sense_buffer));
287
    switch (host_byte(SCpnt->result)) {
288
    case DID_OK:
289
      device->header.result = 0;
290
      break;
291
    case DID_NO_CONNECT:
292
    case DID_BUS_BUSY:
293
    case DID_TIME_OUT:
294
      device->header.result = EBUSY;
295
      break;
296
    case DID_BAD_TARGET:
297
    case DID_ABORT:
298
    case DID_PARITY:
299
    case DID_RESET:
300
    case DID_BAD_INTR:
301
      device->header.result = EIO;
302
      break;
303
    case DID_ERROR:
304
      /*
305
       * There really should be DID_UNDERRUN and DID_OVERRUN error values,
306
       * and a means for callers of scsi_do_cmd to indicate whether an
307
       * underrun or overrun should signal an error.  Until that can be
308
       * implemented, this kludge allows for returning useful error values
309
       * except in cases that return DID_ERROR that might be due to an
310
       * underrun.
311
       */
312
      if (SCpnt->sense_buffer[0] == 0 &&
313
          status_byte(SCpnt->result) == GOOD)
314
        device->header.result = 0;
315
      else device->header.result = EIO;
316
      break;
317
    }
318
 
319
    /*
320
     * Now wake up the process that is waiting for the
321
     * result.
322
     */
323
    device->complete=1;
324
    SCpnt->request.rq_status = RQ_INACTIVE;
325
    wake_up(&scsi_generics[dev].read_wait);
326
}
327
 
328
static int sg_write(struct inode *inode,struct file *filp,const char *buf,int count)
329
{
330
    int                   bsize,size,amt,i;
331
    unsigned char         cmnd[MAX_COMMAND_SIZE];
332
    kdev_t                devt = inode->i_rdev;
333
    int                   dev = MINOR(devt);
334
    struct scsi_generic   * device=&scsi_generics[dev];
335
    int                   input_size;
336
    unsigned char         opcode;
337
    Scsi_Cmnd           * SCpnt;
338
 
339
    if ((i=verify_area(VERIFY_READ,buf,count)))
340
        return i;
341
    /*
342
     * The minimum scsi command length is 6 bytes.  If we get anything
343
     * less than this, it is clearly bogus.
344
     */
345
    if (count<(sizeof(struct sg_header) + 6))
346
        return -EIO;
347
 
348
    /*
349
     * If we still have a result pending from a previous command,
350
     * wait until the result has been read by the user before sending
351
     * another command.
352
     */
353
    while(device->pending)
354
    {
355
        if (filp->f_flags & O_NONBLOCK)
356
            return -EAGAIN;
357
#ifdef DEBUG
358
        printk("sg_write: sleeping on pending request\n");
359
#endif     
360
        interruptible_sleep_on(&device->write_wait);
361
        if (current->signal & ~current->blocked)
362
            return -ERESTARTSYS;
363
    }
364
 
365
    /*
366
     * Mark the device flags for the new state.
367
     */
368
    device->pending=1;
369
    device->complete=0;
370
    memcpy_fromfs(&device->header,buf,sizeof(struct sg_header));
371
 
372
    device->header.pack_len=count;
373
    buf+=sizeof(struct sg_header);
374
 
375
    /*
376
     * Now we need to grab the command itself from the user's buffer.
377
     */
378
    opcode = get_user(buf);
379
    size=COMMAND_SIZE(opcode);
380
    if (opcode >= 0xc0 && device->header.twelve_byte) size = 12;
381
 
382
    /*
383
     * Determine buffer size.
384
     */
385
    input_size = device->header.pack_len - size;
386
    if( input_size > device->header.reply_len)
387
    {
388
        bsize = input_size;
389
    } else {
390
        bsize = device->header.reply_len;
391
    }
392
 
393
    /*
394
     * Don't include the command header itself in the size.
395
     */
396
    bsize-=sizeof(struct sg_header);
397
    input_size-=sizeof(struct sg_header);
398
 
399
    /*
400
     * Verify that the user has actually passed enough bytes for this command.
401
     */
402
    if( input_size < 0 )
403
    {
404
        device->pending=0;
405
        wake_up( &device->write_wait );
406
        return -EIO;
407
    }
408
 
409
    /*
410
     * Allocate a buffer that is large enough to hold the data
411
     * that has been requested.  Round up to an even number of sectors,
412
     * since scsi_malloc allocates in chunks of 512 bytes.
413
     */
414
    amt=bsize;
415
    if (!bsize)
416
        bsize++;
417
    bsize=(bsize+511) & ~511;
418
 
419
    /*
420
     * If we cannot allocate the buffer, report an error.
421
     */
422
    if ((bsize<0) || !(device->buff=sg_malloc(device->buff_len=bsize)))
423
    {
424
        device->pending=0;
425
        wake_up(&device->write_wait);
426
        return -ENOMEM;
427
    }
428
 
429
#ifdef DEBUG
430
    printk("allocating device\n");
431
#endif
432
 
433
    /*
434
     * Grab a device pointer for the device we want to talk to.  If we
435
     * don't want to block, just return with the appropriate message.
436
     */
437
    if (!(SCpnt=allocate_device(NULL,device->device, !(filp->f_flags & O_NONBLOCK))))
438
    {
439
        device->pending=0;
440
        wake_up(&device->write_wait);
441
        sg_free(device->buff,device->buff_len);
442
        device->buff = NULL;
443
        return -EAGAIN;
444
    }
445
#ifdef DEBUG
446
    printk("device allocated\n");
447
#endif    
448
 
449
    SCpnt->request.rq_dev = devt;
450
    SCpnt->request.rq_status = RQ_ACTIVE;
451
    SCpnt->sense_buffer[0]=0;
452
    SCpnt->cmd_len = size;
453
 
454
    /*
455
     * Now copy the SCSI command from the user's address space.
456
     */
457
    memcpy_fromfs(cmnd,buf,size);
458
    buf+=size;
459
 
460
    /*
461
     * If we are writing data, copy the data we are writing.  The pack_len
462
     * field also includes the length of the header and the command,
463
     * so we need to subtract these off.
464
     */
465
    if (input_size > 0) memcpy_fromfs(device->buff, buf, input_size);
466
 
467
    /*
468
     * Set the LUN field in the command structure.
469
     */
470
    cmnd[1]= (cmnd[1] & 0x1f) | (device->device->lun<<5);
471
 
472
#ifdef DEBUG
473
    printk("do cmd\n");
474
#endif
475
 
476
    /*
477
     * Now pass the actual command down to the low-level driver.  We
478
     * do not do any more here - when the interrupt arrives, we will
479
     * then do the post-processing.
480
     */
481
    scsi_do_cmd (SCpnt,(void *) cmnd,
482
                 (void *) device->buff,amt,
483
                 sg_command_done,device->timeout,SG_DEFAULT_RETRIES);
484
 
485
#ifdef DEBUG
486
    printk("done cmd\n");
487
#endif               
488
 
489
    return count;
490
}
491
 
492
static int sg_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
493
{
494
    int dev=MINOR(inode->i_rdev);
495
    int r = 0;
496
    struct scsi_generic *device=&scsi_generics[dev];
497
 
498
    if (sel_type == SEL_IN) {
499
        if(device->pending && device->complete)
500
        {
501
            r = 1;
502
        } else {
503
            select_wait(&scsi_generics[dev].read_wait, wait);
504
        }
505
    }
506
    if (sel_type == SEL_OUT) {
507
        if(!device->pending){
508
            r = 1;
509
        }
510
        else
511
        {
512
            select_wait(&scsi_generics[dev].write_wait, wait);
513
        }
514
    }
515
 
516
    return(r);
517
}
518
 
519
static struct file_operations sg_fops = {
520
    NULL,            /* lseek */
521
    sg_read,         /* read */
522
    sg_write,        /* write */
523
    NULL,            /* readdir */
524
    sg_select,       /* select */
525
    sg_ioctl,        /* ioctl */
526
    NULL,            /* mmap */
527
    sg_open,         /* open */
528
    sg_close,        /* release */
529
    NULL             /* fsync */
530
};
531
 
532
 
533
static int sg_detect(Scsi_Device * SDp){
534
 
535
    switch (SDp->type) {
536
        case TYPE_DISK:
537
        case TYPE_MOD:
538
        case TYPE_ROM:
539
        case TYPE_WORM:
540
        case TYPE_TAPE: break;
541
        default:
542
        printk("Detected scsi generic sg%c at scsi%d, channel %d, id %d, lun %d\n",
543
           'a'+sg_template.dev_noticed,
544
           SDp->host->host_no, SDp->channel, SDp->id, SDp->lun);
545
    }
546
    sg_template.dev_noticed++;
547
    return 1;
548
}
549
 
550
/* Driver initialization */
551
static int sg_init()
552
{
553
    static int sg_registered = 0;
554
 
555
    if (sg_template.dev_noticed == 0) return 0;
556
 
557
    if(!sg_registered) {
558
        if (register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops))
559
        {
560
            printk("Unable to get major %d for generic SCSI device\n",
561
                   SCSI_GENERIC_MAJOR);
562
            return 1;
563
        }
564
        sg_registered++;
565
    }
566
 
567
    /* If we have already been through here, return */
568
    if(scsi_generics) return 0;
569
 
570
#ifdef DEBUG
571
    printk("sg: Init generic device.\n");
572
#endif
573
 
574
#ifdef SG_BIG_BUFF
575
    big_buff= (char *) scsi_init_malloc(SG_BIG_BUFF, GFP_ATOMIC | GFP_DMA);
576
#endif
577
 
578
    scsi_generics = (struct scsi_generic *)
579
        scsi_init_malloc((sg_template.dev_noticed + SG_EXTRA_DEVS)
580
                         * sizeof(struct scsi_generic), GFP_ATOMIC);
581
    memset(scsi_generics, 0, (sg_template.dev_noticed + SG_EXTRA_DEVS)
582
           * sizeof(struct scsi_generic));
583
 
584
    sg_template.dev_max = sg_template.dev_noticed + SG_EXTRA_DEVS;
585
    return 0;
586
}
587
 
588
static int sg_attach(Scsi_Device * SDp)
589
{
590
    struct scsi_generic * gpnt;
591
    int i;
592
 
593
    if(sg_template.nr_dev >= sg_template.dev_max)
594
    {
595
        SDp->attached--;
596
        return 1;
597
    }
598
 
599
    for(gpnt = scsi_generics, i=0; i<sg_template.dev_max; i++, gpnt++)
600
        if(!gpnt->device) break;
601
 
602
    if(i >= sg_template.dev_max) panic ("scsi_devices corrupt (sg)");
603
 
604
    scsi_generics[i].device=SDp;
605
    scsi_generics[i].users=0;
606
    scsi_generics[i].generic_wait=NULL;
607
    scsi_generics[i].read_wait=NULL;
608
    scsi_generics[i].write_wait=NULL;
609
    scsi_generics[i].buff=NULL;
610
    scsi_generics[i].exclude=0;
611
    scsi_generics[i].pending=0;
612
    scsi_generics[i].timeout=SG_DEFAULT_TIMEOUT;
613
    sg_template.nr_dev++;
614
    return 0;
615
};
616
 
617
 
618
 
619
static void sg_detach(Scsi_Device * SDp)
620
{
621
    struct scsi_generic * gpnt;
622
    int i;
623
 
624
    for(gpnt = scsi_generics, i=0; i<sg_template.dev_max; i++, gpnt++)
625
        if(gpnt->device == SDp) {
626
            gpnt->device = NULL;
627
            SDp->attached--;
628
            sg_template.nr_dev--;
629
            /*
630
             * avoid associated device /dev/sg? bying incremented
631
             * each time module is inserted/removed , <dan@lectra.fr>
632
             */
633
            sg_template.dev_noticed--;
634
            return;
635
        }
636
    return;
637
}
638
 
639
#ifdef MODULE
640
 
641
int init_module(void) {
642
    sg_template.usage_count = &mod_use_count_;
643
    return scsi_register_module(MODULE_SCSI_DEV, &sg_template);
644
}
645
 
646
void cleanup_module( void)
647
{
648
    scsi_unregister_module(MODULE_SCSI_DEV, &sg_template);
649
    unregister_chrdev(SCSI_GENERIC_MAJOR, "sg");
650
 
651
    if(scsi_generics != NULL) {
652
        scsi_init_free((char *) scsi_generics,
653
                       (sg_template.dev_noticed + SG_EXTRA_DEVS)
654
                       * sizeof(struct scsi_generic));
655
    }
656
    sg_template.dev_max = 0;
657
#ifdef SG_BIG_BUFF
658
    if(big_buff != NULL)
659
        scsi_init_free(big_buff, SG_BIG_BUFF);
660
#endif
661
}
662
#endif /* MODULE */
663
 
664
/*
665
 * Overrides for Emacs so that we almost follow Linus's tabbing style.
666
 * Emacs will notice this stuff at the end of the file and automatically
667
 * adjust the settings for this buffer only.  This must remain at the end
668
 * of the file.
669
 * ---------------------------------------------------------------------------
670
 * Local variables:
671
 * c-indent-level: 4
672
 * c-brace-imaginary-offset: 0
673
 * c-brace-offset: -4
674
 * c-argdecl-indent: 4
675
 * c-label-offset: -4
676
 * c-continued-statement-offset: 4
677
 * c-continued-brace-offset: 0
678
 * indent-tabs-mode: nil
679
 * tab-width: 8
680
 * End:
681
 */

powered by: WebSVN 2.1.0

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