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

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