root/drivers/scsi/scsi_debug.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. scsi_dump
  2. scsi_debug_queuecommand
  3. internal_done
  4. scsi_debug_command
  5. scsi_debug_intr_handle
  6. scsi_debug_detect
  7. scsi_debug_abort
  8. scsi_debug_biosparam
  9. scsi_debug_reset
  10. scsi_debug_info
  11. scsi_debug_proc_info

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

/* [previous][next][first][last][top][bottom][index][help] */