Annotation of Gnu-Mach/i386/i386at/gpl/linux/scsi/scsi_debug.c, revision 1.1

1.1     ! root        1: /* $Id: scsi_debug.c,v 1.1.1.1 1997/02/25 21:27:51 thomas 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 cant 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:  */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.