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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [scsi/] [scsi_debug.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/* $Id: scsi_debug.c,v 1.1 2005-12-20 10:17:45 jcastillo Exp $
2
 *  linux/kernel/scsi_debug.c
3
 *
4
 *  Copyright (C) 1992  Eric Youngdale
5
 *  Simulate a host adapter with 2 disks attached.  Do a lot of checking
6
 *  to make sure that we are not getting blocks mixed up, and panic if
7
 *  anything out of the ordinary is seen.
8
 */
9
 
10
#include <linux/module.h>
11
 
12
#include <linux/kernel.h>
13
#include <linux/sched.h>
14
#include <linux/errno.h>
15
#include <linux/timer.h>
16
#include <linux/head.h>
17
#include <linux/types.h>
18
#include <linux/string.h>
19
#include <linux/genhd.h>
20
#include <linux/fs.h>
21
#include <linux/proc_fs.h>
22
 
23
#include <asm/system.h>
24
#include <asm/io.h>
25
 
26
#ifdef MODULE
27
#include <linux/module.h>
28
#endif
29
 
30
#include <linux/blk.h>
31
#include "scsi.h"
32
#include "hosts.h"
33
 
34
#include "sd.h"
35
 
36
#include<linux/stat.h>
37
 
38
struct proc_dir_entry proc_scsi_scsi_debug = {
39
    PROC_SCSI_SCSI_DEBUG, 10, "scsi_debug",
40
    S_IFDIR | S_IRUGO | S_IXUGO, 2
41
};
42
 
43
 
44
/* A few options that we want selected */
45
 
46
/* Do not attempt to use a timer to simulate a real disk with latency */
47
/* Only use this in the actual kernel, not in the simulator. */
48
#define IMMEDIATE
49
 
50
/* Skip some consistency checking.  Good for benchmarking */
51
#define SPEEDY
52
 
53
/* Number of real scsi disks that will be detected ahead of time */
54
static int NR_REAL=-1;
55
 
56
#define NR_BLK_DEV  12
57
#ifndef MAJOR_NR
58
#define MAJOR_NR 8
59
#endif
60
#define START_PARTITION 4
61
#define SCSI_DEBUG_TIMER 20
62
/* Number of jiffies to wait before completing a command */
63
#define DISK_SPEED     10
64
#define CAPACITY (0x80000)
65
 
66
static int starts[] = {4, 1000, 50000, CAPACITY, 0};
67
static int npart = 0;
68
 
69
#include "scsi_debug.h"
70
#ifdef DEBUG
71
#define DEB(x) x
72
#else
73
#define DEB(x)
74
#endif
75
 
76
#ifdef SPEEDY
77
#define VERIFY1_DEBUG(RW) 1
78
#define VERIFY_DEBUG(RW) 1
79
#else
80
 
81
#define VERIFY1_DEBUG(RW)                           \
82
    if (bufflen != 1024) {printk("%d", bufflen); panic("(1)Bad bufflen");};         \
83
    start = 0;                          \
84
    if ((MINOR(SCpnt->request.rq_dev) & 0xf) != 0) start = starts[(MINOR(SCpnt->request.rq_dev) & 0xf) - 1];        \
85
    if (bh){                            \
86
        if (bh->b_size != 1024) panic ("Wrong bh size");    \
87
        if ((bh->b_blocknr << 1) + start != block)          \
88
        {   printk("Wrong bh block# %d %d ",bh->b_blocknr, block);  \
89
            panic ("Wrong bh block#"); \
90
        };  \
91
        if (bh->b_dev != SCpnt->request.rq_dev)  \
92
            panic ("Bad bh target"); \
93
    };
94
 
95
#define VERIFY_DEBUG(RW)                            \
96
    if (bufflen != 1024 && (!SCpnt->use_sg)) {printk("%x %d\n ",bufflen, SCpnt->use_sg); panic("Bad bufflen");};    \
97
    start = 0;                          \
98
    if ((MINOR(SCpnt->request.rq_dev) & 0xf) > npart) panic ("Bad partition");    \
99
    if ((MINOR(SCpnt->request.rq_dev) & 0xf) != 0) start = starts[(MINOR(SCpnt->request.rq_dev) & 0xf) - 1];        \
100
    if (SCpnt->request.cmd != RW) panic ("Wrong  operation");       \
101
    if (SCpnt->request.sector + start != block) panic("Wrong block.");  \
102
    if (SCpnt->request.current_nr_sectors != 2 && (!SCpnt->use_sg)) panic ("Wrong # blocks");   \
103
    if (SCpnt->request.bh){                         \
104
        if (SCpnt->request.bh->b_size != 1024) panic ("Wrong bh size"); \
105
        if ((SCpnt->request.bh->b_blocknr << 1) + start != block)           \
106
        {   printk("Wrong bh block# %d %d ",SCpnt->request.bh->b_blocknr, block);  \
107
            panic ("Wrong bh block#"); \
108
        };  \
109
        if (SCpnt->request.bh->b_dev != SCpnt->request.rq_dev) \
110
            panic ("Bad bh target");\
111
    };
112
#endif
113
 
114
static volatile void (*do_done[SCSI_DEBUG_MAILBOXES])(Scsi_Cmnd *) = {NULL, };
115
extern void scsi_debug_interrupt();
116
 
117
volatile Scsi_Cmnd * SCint[SCSI_DEBUG_MAILBOXES] = {NULL,};
118
static char SCrst[SCSI_DEBUG_MAILBOXES] = {0,};
119
static volatile unsigned int timeout[8] ={0,};
120
 
121
/*
122
 * Semaphore used to simulate bus lockups.
123
 */
124
static int scsi_debug_lockup = 0;
125
 
126
static char sense_buffer[128] = {0,};
127
 
128
static void scsi_dump(Scsi_Cmnd * SCpnt, int flag){
129
    int i;
130
#if 0
131
    unsigned char * pnt;
132
#endif
133
    unsigned int * lpnt;
134
    struct scatterlist * sgpnt = NULL;
135
    printk("use_sg: %d",SCpnt->use_sg);
136
    if (SCpnt->use_sg){
137
        sgpnt = (struct scatterlist *) SCpnt->buffer;
138
        for(i=0; i<SCpnt->use_sg; i++) {
139
            lpnt = (int *) sgpnt[i].alt_address;
140
            printk(":%x %x %d\n",sgpnt[i].alt_address, sgpnt[i].address, sgpnt[i].length);
141
            if (lpnt) printk(" (Alt %x) ",lpnt[15]);
142
        };
143
    } else {
144
        printk("nosg: %x %x %d\n",SCpnt->request.buffer, SCpnt->buffer,
145
               SCpnt->bufflen);
146
        lpnt = (int *) SCpnt->request.buffer;
147
        if (lpnt) printk(" (Alt %x) ",lpnt[15]);
148
    };
149
    lpnt = (unsigned int *) SCpnt;
150
    for (i=0;i<sizeof(Scsi_Cmnd)/4+1; i++) {
151
        if ((i & 7) == 0) printk("\n");
152
        printk("%x ",*lpnt++);
153
    };
154
    printk("\n");
155
    if (flag == 0) return;
156
    lpnt = (unsigned int *) sgpnt[0].alt_address;
157
    for (i=0;i<sizeof(Scsi_Cmnd)/4+1; i++) {
158
        if ((i & 7) == 0) printk("\n");
159
        printk("%x ",*lpnt++);
160
    };
161
#if 0
162
    printk("\n");
163
    lpnt = (unsigned int *) sgpnt[0].address;
164
    for (i=0;i<sizeof(Scsi_Cmnd)/4+1; i++) {
165
        if ((i & 7) == 0) printk("\n");
166
        printk("%x ",*lpnt++);
167
    };
168
    printk("\n");
169
#endif
170
    printk("DMA free %d sectors.\n", dma_free_sectors);
171
}
172
 
173
int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
174
{
175
    unchar *cmd = (unchar *) SCpnt->cmnd;
176
    struct partition * p;
177
    int block, start;
178
    struct buffer_head * bh = NULL;
179
    unsigned char * buff;
180
    int nbytes, sgcount;
181
    int scsi_debug_errsts;
182
    struct scatterlist * sgpnt;
183
    int target = SCpnt->target;
184
    int bufflen = SCpnt->request_bufflen;
185
    unsigned long flags;
186
    int i;
187
    sgcount = 0;
188
    sgpnt = NULL;
189
 
190
    DEB(if (target > 1) { SCpnt->result = DID_TIME_OUT << 16;done(SCpnt);return 0;});
191
 
192
    buff = (unsigned char *) SCpnt->request_buffer;
193
 
194
    if(target>=1 || SCpnt->lun != 0) {
195
        SCpnt->result =  DID_NO_CONNECT << 16;
196
        done(SCpnt);
197
        return 0;
198
    };
199
 
200
    if( SCrst[target] != 0 && !scsi_debug_lockup )
201
    {
202
        SCrst[target] = 0;
203
        memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
204
        SCpnt->sense_buffer[0] = 0x70;
205
        SCpnt->sense_buffer[2] = UNIT_ATTENTION;
206
        SCpnt->result = (CHECK_CONDITION << 1);
207
        done(SCpnt);
208
    }
209
    switch(*cmd){
210
    case REQUEST_SENSE:
211
        printk("Request sense...\n");
212
#ifndef DEBUG
213
        {
214
            int i;
215
            printk("scsi_debug: Requesting sense buffer (%x %x %x %d):", SCpnt, buff, done, bufflen);
216
            for(i=0;i<12;i++) printk("%d ",sense_buffer[i]);
217
            printk("\n");
218
        };
219
#endif
220
        memset(buff, 0, bufflen);
221
        memcpy(buff, sense_buffer, bufflen);
222
        memset(sense_buffer, 0, sizeof(sense_buffer));
223
        SCpnt->result = 0;
224
        done(SCpnt);
225
        return 0;
226
    case ALLOW_MEDIUM_REMOVAL:
227
        if(cmd[4]) printk("Medium removal inhibited...");
228
        else printk("Medium removal enabled...");
229
        scsi_debug_errsts = 0;
230
        break;
231
    case INQUIRY:
232
        printk("Inquiry...(%x %d)\n", buff, bufflen);
233
        memset(buff, 0, bufflen);
234
        buff[0] = TYPE_DISK;
235
        buff[1] = 0x80;  /* Removable disk */
236
        buff[2] = 1;
237
        buff[4] = 33 - 5;
238
        memcpy(&buff[8],"Foo Inc",7);
239
        memcpy(&buff[16],"XYZZY",5);
240
        memcpy(&buff[32],"1",1);
241
        scsi_debug_errsts = 0;
242
        break;
243
    case TEST_UNIT_READY:
244
        printk("Test unit ready(%x %d)\n", buff, bufflen);
245
        if (buff)
246
            memset(buff, 0, bufflen);
247
        scsi_debug_errsts = 0;
248
        break;
249
    case READ_CAPACITY:
250
        printk("Read Capacity\n");
251
        if(NR_REAL < 0) NR_REAL = (MINOR(SCpnt->request.rq_dev) >> 4) & 0x0f;
252
        memset(buff, 0, bufflen);
253
        buff[0] = (CAPACITY >> 24);
254
        buff[1] = (CAPACITY >> 16) & 0xff;
255
        buff[2] = (CAPACITY >> 8) & 0xff;
256
        buff[3] = CAPACITY & 0xff;
257
        buff[6] = 2; /* 512 byte sectors */
258
        scsi_debug_errsts = 0;
259
        break;
260
    case READ_10:
261
    case READ_6:
262
#ifdef DEBUG
263
        printk("Read...");
264
#endif
265
        if ((*cmd) == READ_10)
266
            block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24);
267
        else
268
            block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);
269
        VERIFY_DEBUG(READ);
270
#if defined(SCSI_SETUP_LATENCY) || defined(SCSI_DATARATE)
271
    {
272
        int delay = SCSI_SETUP_LATENCY;
273
        double usec;
274
 
275
        usec = 0.0;
276
        usec = (SCpnt->request.nr_sectors << 9) * 1.0e6 / SCSI_DATARATE;
277
        delay += usec;
278
        if(delay) usleep(delay);
279
    };
280
#endif
281
 
282
#ifdef DEBUG
283
        printk("(r%d)",SCpnt->request.nr_sectors);
284
#endif
285
        nbytes = bufflen;
286
        if(SCpnt->use_sg){
287
            sgcount = 0;
288
            sgpnt = (struct scatterlist *) buff;
289
            buff = sgpnt[sgcount].address;
290
            bufflen = sgpnt[sgcount].length;
291
            bh = SCpnt->request.bh;
292
        };
293
        scsi_debug_errsts = 0;
294
        do{
295
            VERIFY1_DEBUG(READ);
296
            /* For the speedy test, we do not even want to fill the buffer with anything */
297
#ifndef SPEEDY
298
            memset(buff, 0, bufflen);
299
#endif
300
            /* If this is block 0, then we want to read the partition table for this
301
             * device.  Let's make one up */
302
            if(block == 0 && target == 0) {
303
                memset(buff, 0, bufflen);
304
                *((unsigned short *) (buff+510)) = 0xAA55;
305
                p = (struct partition* ) (buff + 0x1be);
306
                npart = 0;
307
                while(starts[npart+1]){
308
                    p->start_sect = starts[npart];
309
                    p->nr_sects = starts[npart+1] - starts [npart];
310
                    p->sys_ind = 0x81;  /* Linux partition */
311
                    p++;
312
                    npart++;
313
                };
314
                scsi_debug_errsts = 0;
315
                break;
316
            };
317
#ifdef DEBUG
318
            if (SCpnt->use_sg) printk("Block %x (%d %d)\n",block, SCpnt->request.nr_sectors,
319
                                      SCpnt->request.current_nr_sectors);
320
#endif
321
 
322
#if 0
323
            /* Simulate a disk change */
324
            if(block == 0xfff0) {
325
                sense_buffer[0] = 0x70;
326
                sense_buffer[2] = UNIT_ATTENTION;
327
                starts[0] += 10;
328
                starts[1] += 10;
329
                starts[2] += 10;
330
 
331
#ifdef DEBUG
332
                {
333
                    int i;
334
                    printk("scsi_debug: Filling sense buffer:");
335
                    for(i=0;i<12;i++) printk("%d ",sense_buffer[i]);
336
                    printk("\n");
337
                };
338
#endif
339
                scsi_debug_errsts = (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1);
340
                break;
341
            } /* End phony disk change code */
342
#endif
343
 
344
#ifndef SPEEDY
345
            memcpy(buff, &target, sizeof(target));
346
            memcpy(buff+sizeof(target), cmd, 24);
347
            memcpy(buff+60, &block, sizeof(block));
348
            memcpy(buff+64, SCpnt, sizeof(Scsi_Cmnd));
349
#endif
350
            nbytes -= bufflen;
351
            if(SCpnt->use_sg){
352
#ifndef SPEEDY
353
                memcpy(buff+128, bh, sizeof(struct buffer_head));
354
#endif
355
                block += bufflen >> 9;
356
                bh = bh->b_reqnext;
357
                sgcount++;
358
                if (nbytes) {
359
                    if(!bh) panic("Too few blocks for linked request.");
360
                    buff = sgpnt[sgcount].address;
361
                    bufflen = sgpnt[sgcount].length;
362
                };
363
            }
364
        } while(nbytes);
365
 
366
        SCpnt->result = 0;
367
        (done)(SCpnt);
368
        return;
369
 
370
        if (SCpnt->use_sg && !scsi_debug_errsts)
371
            if(bh) scsi_dump(SCpnt, 0);
372
        break;
373
    case WRITE_10:
374
    case WRITE_6:
375
#ifdef DEBUG
376
        printk("Write\n");
377
#endif
378
        if ((*cmd) == WRITE_10)
379
            block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24);
380
        else
381
            block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);
382
        VERIFY_DEBUG(WRITE);
383
        /*      printk("(w%d)",SCpnt->request.nr_sectors); */
384
        if (SCpnt->use_sg){
385
            if ((bufflen >> 9) != SCpnt->request.nr_sectors)
386
                panic ("Trying to write wrong number of blocks\n");
387
            sgpnt = (struct scatterlist *) buff;
388
            buff = sgpnt[sgcount].address;
389
        };
390
#if 0
391
        if (block != *((unsigned long *) (buff+60))) {
392
            printk("%x %x :",block,  *((unsigned long *) (buff+60)));
393
            scsi_dump(SCpnt,1);
394
            panic("Bad block written.\n");
395
        };
396
#endif
397
        scsi_debug_errsts = 0;
398
        break;
399
    default:
400
        printk("Unknown command %d\n",*cmd);
401
        SCpnt->result =  DID_NO_CONNECT << 16;
402
        done(SCpnt);
403
        return 0;
404
    };
405
 
406
    save_flags(flags);
407
    cli();
408
    for(i=0;i<SCSI_DEBUG_MAILBOXES; i++){
409
        if (SCint[i] == 0) break;
410
    };
411
 
412
    if (i >= SCSI_DEBUG_MAILBOXES || SCint[i] != 0)
413
        panic("Unable to find empty SCSI_DEBUG command slot.\n");
414
 
415
    SCint[i] = SCpnt;
416
 
417
    if (done) {
418
        DEB(printk("scsi_debug_queuecommand: now waiting for interrupt "););
419
        if (do_done[i])
420
            printk("scsi_debug_queuecommand: Two concurrent queuecommand?\n");
421
        else
422
            do_done[i] = done;
423
    }
424
    else
425
        printk("scsi_debug_queuecommand: done can't be NULL\n");
426
 
427
#ifdef IMMEDIATE
428
    if( !scsi_debug_lockup )
429
    {
430
        SCpnt->result = scsi_debug_errsts;
431
        scsi_debug_intr_handle();  /* No timer - do this one right away */
432
    }
433
    restore_flags(flags);
434
#else
435
    timeout[i] = jiffies+DISK_SPEED;
436
 
437
    /* If no timers active, then set this one */
438
    if ((timer_active & (1 << SCSI_DEBUG_TIMER)) == 0) {
439
        timer_table[SCSI_DEBUG_TIMER].expires = timeout[i];
440
        timer_active |= 1 << SCSI_DEBUG_TIMER;
441
    };
442
 
443
    SCpnt->result = scsi_debug_errsts;
444
    restore_flags(flags);
445
 
446
#if 0
447
    printk("Sending command (%d %x %d %d)...", i, done, timeout[i],jiffies);
448
#endif
449
#endif
450
 
451
    return 0;
452
}
453
 
454
volatile static int internal_done_flag = 0;
455
volatile static int internal_done_errcode = 0;
456
static void internal_done(Scsi_Cmnd * SCpnt)
457
{
458
    internal_done_errcode = SCpnt->result;
459
    ++internal_done_flag;
460
}
461
 
462
int scsi_debug_command(Scsi_Cmnd * SCpnt)
463
{
464
    DEB(printk("scsi_debug_command: ..calling scsi_debug_queuecommand\n"));
465
    scsi_debug_queuecommand(SCpnt, internal_done);
466
 
467
    while (!internal_done_flag);
468
    internal_done_flag = 0;
469
    return internal_done_errcode;
470
}
471
 
472
/* A "high" level interrupt handler.  This should be called once per jiffy
473
 * to simulate a regular scsi disk.  We use a timer to do this. */
474
 
475
static void scsi_debug_intr_handle(void)
476
{
477
    Scsi_Cmnd * SCtmp;
478
    int i, pending;
479
    void (*my_done)(Scsi_Cmnd *);
480
    unsigned long flags;
481
    int to;
482
 
483
#ifndef IMMEDIATE
484
    timer_table[SCSI_DEBUG_TIMER].expires = 0;
485
    timer_active &= ~(1 << SCSI_DEBUG_TIMER);
486
#endif
487
 
488
 repeat:
489
    save_flags(flags);
490
    cli();
491
    for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
492
        if (SCint[i] == 0) continue;
493
#ifndef IMMEDIATE
494
        if (timeout[i] == 0) continue;
495
        if (timeout[i] <= jiffies) break;
496
#else
497
        break;
498
#endif
499
    };
500
 
501
    if(i == SCSI_DEBUG_MAILBOXES){
502
#ifndef IMMEDIATE
503
        pending = INT_MAX;
504
        for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
505
            if (SCint[i] == 0) continue;
506
            if (timeout[i] == 0) continue;
507
            if (timeout[i] <= jiffies) {restore_flags(flags); goto repeat;};
508
            if (timeout[i] > jiffies) {
509
                if (pending > timeout[i]) pending = timeout[i];
510
                continue;
511
            };
512
        };
513
        if (pending && pending != INT_MAX) {
514
            timer_table[SCSI_DEBUG_TIMER].expires =
515
                (pending <= jiffies ? jiffies+1 : pending);
516
            timer_active |= 1 << SCSI_DEBUG_TIMER;
517
        };
518
        restore_flags(flags);
519
#endif
520
        return;
521
    };
522
 
523
    if(i < SCSI_DEBUG_MAILBOXES){
524
        timeout[i] = 0;
525
        my_done = do_done[i];
526
        do_done[i] = NULL;
527
        to = timeout[i];
528
        timeout[i] = 0;
529
        SCtmp = (Scsi_Cmnd *) SCint[i];
530
        SCint[i] = NULL;
531
        restore_flags(flags);
532
 
533
        if (!my_done) {
534
            printk("scsi_debug_intr_handle: Unexpected interrupt\n");
535
            return;
536
        }
537
 
538
#ifdef DEBUG
539
        printk("In intr_handle...");
540
        printk("...done %d %x %d %d\n",i , my_done, to, jiffies);
541
        printk("In intr_handle: %d %x %x\n",i, SCtmp, my_done);
542
#endif
543
 
544
        my_done(SCtmp);
545
#ifdef DEBUG
546
        printk("Called done.\n");
547
#endif
548
    };
549
    goto repeat;
550
}
551
 
552
 
553
int scsi_debug_detect(Scsi_Host_Template * tpnt)
554
{
555
    tpnt->proc_dir = &proc_scsi_scsi_debug;
556
#ifndef IMMEDIATE
557
    timer_table[SCSI_DEBUG_TIMER].fn = scsi_debug_intr_handle;
558
    timer_table[SCSI_DEBUG_TIMER].expires = 0;
559
#endif
560
    return 1;
561
}
562
 
563
int scsi_debug_abort(Scsi_Cmnd * SCpnt)
564
{
565
    int j;
566
    void (*my_done)(Scsi_Cmnd *);
567
    unsigned long flags;
568
 
569
    DEB(printk("scsi_debug_abort\n"));
570
#if 0
571
    SCpnt->result = SCpnt->abort_reason << 16;
572
    for(j=0;j<SCSI_DEBUG_MAILBOXES; j++) {
573
        if(SCpnt == SCint[j]) {
574
            my_done = do_done[j];
575
            my_done(SCpnt);
576
            save_flags(flags);
577
            cli();
578
            timeout[j] = 0;
579
            SCint[j] = NULL;
580
            do_done[j] = NULL;
581
            restore_flags(flags);
582
        };
583
    };
584
#endif
585
    return SCSI_ABORT_SNOOZE;
586
}
587
 
588
int scsi_debug_biosparam(Disk * disk, kdev_t dev, int* info){
589
    int size = disk->capacity;
590
    info[0] = 32;
591
    info[1] = 64;
592
    info[2] = (size + 2047) >> 11;
593
    if (info[2] >= 1024) info[2] = 1024;
594
    return 0;
595
}
596
 
597
int scsi_debug_reset(Scsi_Cmnd * SCpnt)
598
{
599
    int i;
600
    unsigned long flags;
601
 
602
    void (*my_done)(Scsi_Cmnd *);
603
    printk("Bus unlocked by reset(%d)\n", SCpnt->host->suggest_bus_reset);
604
    scsi_debug_lockup = 0;
605
    DEB(printk("scsi_debug_reset called\n"));
606
    for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
607
        if (SCint[i] == NULL) continue;
608
        SCint[i]->result = DID_RESET << 16;
609
        my_done = do_done[i];
610
        my_done(SCint[i]);
611
        save_flags(flags);
612
        cli();
613
        SCint[i] = NULL;
614
        do_done[i] = NULL;
615
        timeout[i] = 0;
616
        restore_flags(flags);
617
    }
618
    return SCSI_RESET_SUCCESS;
619
}
620
 
621
const char *scsi_debug_info(void)
622
{
623
    static char buffer[] = " ";         /* looks nicer without anything here */
624
    return buffer;
625
}
626
 
627
/* scsi_debug_proc_info
628
 * Used if the driver currently has no own support for /proc/scsi
629
 */
630
int scsi_debug_proc_info(char *buffer, char **start, off_t offset,
631
                     int length, int inode, int inout)
632
{
633
    int len, pos, begin;
634
    int orig_length;
635
 
636
    if(inout == 1)
637
    {
638
        /* First check for the Signature */
639
        if (length >= 10 && strncmp(buffer, "scsi_debug", 10) == 0) {
640
            buffer += 11;
641
            length -= 11;
642
            /*
643
             * OK, we are getting some kind of command.  Figure out
644
             * what we are supposed to do here.  Simulate bus lockups
645
             * to test our reset capability.
646
             */
647
            if( length == 6 && strncmp(buffer, "lockup", length) == 0 )
648
            {
649
                scsi_debug_lockup = 1;
650
                return length;
651
            }
652
 
653
            if( length == 6 && strncmp(buffer, "unlock", length) == 0 )
654
            {
655
                scsi_debug_lockup = 0;
656
                return length;
657
            }
658
 
659
            printk("Unknown command:%s\n", buffer);
660
        } else
661
            printk("Wrong Signature:%10s\n", (char *) ((ulong)buffer-11));
662
 
663
        return -EINVAL;
664
 
665
    }
666
 
667
    begin = 0;
668
    pos = len = sprintf(buffer,
669
                        "This driver is not a real scsi driver, but it plays one on TV.\n"
670
                        "It is very handy for debugging specific problems because you\n"
671
                        "can simulate a variety of error conditions\n");
672
    if(pos < offset)
673
    {
674
        len = 0;
675
        begin = pos;
676
    }
677
 
678
    *start = buffer + (offset - begin);   /* Start of wanted data */
679
    len -= (offset - begin);
680
    if(len > length)
681
        len = length;
682
 
683
    return(len);
684
}
685
 
686
#ifdef MODULE
687
/* Eventually this will go into an include file, but this will be later */
688
Scsi_Host_Template driver_template = SCSI_DEBUG;
689
 
690
#include "scsi_module.c"
691
#endif
692
 
693
/*
694
 * Overrides for Emacs so that we almost follow Linus's tabbing style.
695
 * Emacs will notice this stuff at the end of the file and automatically
696
 * adjust the settings for this buffer only.  This must remain at the end
697
 * of the file.
698
 * ---------------------------------------------------------------------------
699
 * Local variables:
700
 * c-indent-level: 4
701
 * c-brace-imaginary-offset: 0
702
 * c-brace-offset: -4
703
 * c-argdecl-indent: 4
704
 * c-label-offset: -4
705
 * c-continued-statement-offset: 4
706
 * c-continued-brace-offset: 0
707
 * indent-tabs-mode: nil
708
 * tab-width: 8
709
 * End:
710
 */

powered by: WebSVN 2.1.0

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