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 #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){
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *))
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 457 {
 458     internal_done_errcode = SCpnt->result;
 459     ++internal_done_flag;
 460 }
 461 
 462 int scsi_debug_command(Scsi_Cmnd * SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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){
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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, 
     /* [previous][next][first][last][top][bottom][index][help] */
 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  */

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