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

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

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