diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-10-09 00:00:47 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-10-09 00:00:47 +0000 |
commit | d6434e1042f3b0a6dfe1b1f615af369486f9b1fa (patch) | |
tree | e2be02f33984c48ec019c654051d27964e42c441 /drivers/scsi/scsi_debug.c | |
parent | 609d1e803baf519487233b765eb487f9ec227a18 (diff) |
Merge with 2.3.19.
Diffstat (limited to 'drivers/scsi/scsi_debug.c')
-rw-r--r-- | drivers/scsi/scsi_debug.c | 956 |
1 files changed, 477 insertions, 479 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 2eac00ff4..ac5c09043 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -30,9 +30,10 @@ #include<linux/stat.h> -struct proc_dir_entry proc_scsi_scsi_debug = { - PROC_SCSI_SCSI_DEBUG, 10, "scsi_debug", - S_IFDIR | S_IRUGO | S_IXUGO, 2 +struct proc_dir_entry proc_scsi_scsi_debug = +{ + PROC_SCSI_SCSI_DEBUG, 10, "scsi_debug", + S_IFDIR | S_IRUGO | S_IXUGO, 2 }; @@ -55,7 +56,7 @@ struct proc_dir_entry proc_scsi_scsi_debug = { #define CLEAR /* Number of real scsi disks that will be detected ahead of time */ -static int NR_REAL=-1; +static int NR_REAL = -1; #define NR_BLK_DEV 12 #ifndef MAJOR_NR @@ -63,11 +64,12 @@ static int NR_REAL=-1; #endif #define START_PARTITION 4 -/* Number of jiffies to wait before completing a command */ -#define DISK_SPEED 10 +/* Time to wait before completing a command */ +#define DISK_SPEED (HZ/10) /* 100ms */ #define CAPACITY (0x80000) -static int starts[] = {N_HEAD, N_HEAD * N_SECTOR, 50000, CAPACITY, 0}; +static int starts[] = +{N_HEAD, N_HEAD * N_SECTOR, 50000, CAPACITY, 0}; static int npart = 0; #include "scsi_debug.h" @@ -78,8 +80,8 @@ static int npart = 0; #endif #ifdef SPEEDY -#define VERIFY1_DEBUG(RW) -#define VERIFY_DEBUG(RW) +#define VERIFY1_DEBUG(RW) +#define VERIFY_DEBUG(RW) #else #define VERIFY1_DEBUG(RW) \ @@ -115,15 +117,15 @@ static int npart = 0; }; #endif -typedef void (*done_fct_t)(Scsi_Cmnd *); +typedef void (*done_fct_t) (Scsi_Cmnd *); -static volatile done_fct_t do_done[SCSI_DEBUG_MAILBOXES] = {NULL, }; +static volatile done_fct_t do_done[SCSI_DEBUG_MAILBOXES] = {NULL,}; static void scsi_debug_intr_handle(unsigned long); static struct timer_list timeout[SCSI_DEBUG_MAILBOXES]; -Scsi_Cmnd * SCint[SCSI_DEBUG_MAILBOXES] = {NULL,}; +Scsi_Cmnd *SCint[SCSI_DEBUG_MAILBOXES] = {NULL,}; static char SCrst[SCSI_DEBUG_MAILBOXES] = {0,}; /* @@ -133,379 +135,384 @@ static int scsi_debug_lockup = 0; static char sense_buffer[128] = {0,}; -static void scsi_dump(Scsi_Cmnd * SCpnt, int flag){ - int i; +static void scsi_dump(Scsi_Cmnd * SCpnt, int flag) +{ + int i; #if 0 - unsigned char * pnt; + unsigned char *pnt; #endif - unsigned int * lpnt; - struct scatterlist * sgpnt = NULL; - printk("use_sg: %d",SCpnt->use_sg); - if (SCpnt->use_sg){ - sgpnt = (struct scatterlist *) SCpnt->buffer; - for(i=0; i<SCpnt->use_sg; i++) { - lpnt = (int *) sgpnt[i].alt_address; - printk(":%p %p %d\n",sgpnt[i].alt_address, sgpnt[i].address, sgpnt[i].length); - if (lpnt) printk(" (Alt %x) ",lpnt[15]); + unsigned int *lpnt; + struct scatterlist *sgpnt = NULL; + printk("use_sg: %d", SCpnt->use_sg); + if (SCpnt->use_sg) { + sgpnt = (struct scatterlist *) SCpnt->buffer; + for (i = 0; i < SCpnt->use_sg; i++) { + lpnt = (int *) sgpnt[i].alt_address; + printk(":%p %p %d\n", sgpnt[i].alt_address, sgpnt[i].address, sgpnt[i].length); + if (lpnt) + printk(" (Alt %x) ", lpnt[15]); + }; + } else { + printk("nosg: %p %p %d\n", SCpnt->request.buffer, SCpnt->buffer, + SCpnt->bufflen); + lpnt = (int *) SCpnt->request.buffer; + if (lpnt) + printk(" (Alt %x) ", lpnt[15]); + }; + lpnt = (unsigned int *) SCpnt; + for (i = 0; i < sizeof(Scsi_Cmnd) / 4 + 1; i++) { + if ((i & 7) == 0) + printk("\n"); + printk("%x ", *lpnt++); + }; + printk("\n"); + if (flag == 0) + return; + lpnt = (unsigned int *) sgpnt[0].alt_address; + for (i = 0; i < sizeof(Scsi_Cmnd) / 4 + 1; i++) { + if ((i & 7) == 0) + printk("\n"); + printk("%x ", *lpnt++); }; - } else { - printk("nosg: %p %p %d\n",SCpnt->request.buffer, SCpnt->buffer, - SCpnt->bufflen); - lpnt = (int *) SCpnt->request.buffer; - if (lpnt) printk(" (Alt %x) ",lpnt[15]); - }; - lpnt = (unsigned int *) SCpnt; - for (i=0;i<sizeof(Scsi_Cmnd)/4+1; i++) { - if ((i & 7) == 0) printk("\n"); - printk("%x ",*lpnt++); - }; - printk("\n"); - if (flag == 0) return; - lpnt = (unsigned int *) sgpnt[0].alt_address; - for (i=0;i<sizeof(Scsi_Cmnd)/4+1; i++) { - if ((i & 7) == 0) printk("\n"); - printk("%x ",*lpnt++); - }; #if 0 - printk("\n"); - lpnt = (unsigned int *) sgpnt[0].address; - for (i=0;i<sizeof(Scsi_Cmnd)/4+1; i++) { - if ((i & 7) == 0) printk("\n"); - printk("%x ",*lpnt++); - }; - printk("\n"); + printk("\n"); + lpnt = (unsigned int *) sgpnt[0].address; + for (i = 0; i < sizeof(Scsi_Cmnd) / 4 + 1; i++) { + if ((i & 7) == 0) + printk("\n"); + printk("%x ", *lpnt++); + }; + printk("\n"); #endif - printk("DMA free %d sectors.\n", scsi_dma_free_sectors); + printk("DMA free %d sectors.\n", scsi_dma_free_sectors); } -int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) +int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) { - unchar *cmd = (unchar *) SCpnt->cmnd; - struct partition * p; - int block; - struct buffer_head * bh = NULL; - unsigned char * buff; - int nbytes, sgcount; - int scsi_debug_errsts; - struct scatterlist * sgpnt; - int target = SCpnt->target; - int bufflen = SCpnt->request_bufflen; - unsigned long flags; - int i; - sgcount = 0; - sgpnt = NULL; - - /* - * If we are being notified of the mid-level reposessing a command due to timeout, - * just return. - */ - if( done == NULL ) - { - return 0; - } - - DEB(if (target >= NR_FAKE_DISKS) - { - SCpnt->result = DID_TIME_OUT << 16;done(SCpnt);return 0; - }); - - buff = (unsigned char *) SCpnt->request_buffer; - - if(target>=NR_FAKE_DISKS || SCpnt->lun != 0) - { - SCpnt->result = DID_NO_CONNECT << 16; - done(SCpnt); - return 0; - } - - if( SCrst[target] != 0 && !scsi_debug_lockup ) - { - SCrst[target] = 0; - memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer)); - SCpnt->sense_buffer[0] = 0x70; - SCpnt->sense_buffer[2] = UNIT_ATTENTION; - SCpnt->result = (CHECK_CONDITION << 1); - done(SCpnt); - } - switch(*cmd){ - case REQUEST_SENSE: - SCSI_LOG_LLQUEUE(3,printk("Request sense...\n")); + unchar *cmd = (unchar *) SCpnt->cmnd; + struct partition *p; + int block; + struct buffer_head *bh = NULL; + unsigned char *buff; + int nbytes, sgcount; + int scsi_debug_errsts; + struct scatterlist *sgpnt; + int target = SCpnt->target; + int bufflen = SCpnt->request_bufflen; + unsigned long flags; + int i; + sgcount = 0; + sgpnt = NULL; + + /* + * If we are being notified of the mid-level reposessing a command due to timeout, + * just return. + */ + if (done == NULL) { + return 0; + } + DEB(if (target >= NR_FAKE_DISKS) { + SCpnt->result = DID_TIME_OUT << 16; done(SCpnt); return 0; + } + ); + + buff = (unsigned char *) SCpnt->request_buffer; + + if (target >= NR_FAKE_DISKS || SCpnt->lun != 0) { + SCpnt->result = DID_NO_CONNECT << 16; + done(SCpnt); + return 0; + } + if (SCrst[target] != 0 && !scsi_debug_lockup) { + SCrst[target] = 0; + memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer)); + SCpnt->sense_buffer[0] = 0x70; + SCpnt->sense_buffer[2] = UNIT_ATTENTION; + SCpnt->result = (CHECK_CONDITION << 1); + done(SCpnt); + } + switch (*cmd) { + case REQUEST_SENSE: + SCSI_LOG_LLQUEUE(3, printk("Request sense...\n")); #ifndef DEBUG - { - int i; - printk("scsi_debug: Requesting sense buffer (%p %p %p %d):", SCpnt, buff, done, bufflen); - for(i=0;i<12;i++) printk("%d ",sense_buffer[i]); - printk("\n"); - }; + { + int i; + printk("scsi_debug: Requesting sense buffer (%p %p %p %d):", SCpnt, buff, done, bufflen); + for (i = 0; i < 12; i++) + printk("%d ", sense_buffer[i]); + printk("\n"); + }; #endif - memset(buff, 0, bufflen); - memcpy(buff, sense_buffer, bufflen); - memset(sense_buffer, 0, sizeof(sense_buffer)); - SCpnt->result = 0; - done(SCpnt); - return 0; - case ALLOW_MEDIUM_REMOVAL: - if(cmd[4]) - { - SCSI_LOG_LLQUEUE(2,printk("Medium removal inhibited...")); - } - else - { - SCSI_LOG_LLQUEUE(2,printk("Medium removal enabled...")); - } - scsi_debug_errsts = 0; - break; - case INQUIRY: - SCSI_LOG_LLQUEUE(3,printk("Inquiry...(%p %d)\n", buff, bufflen)); - memset(buff, 0, bufflen); - buff[0] = TYPE_DISK; - buff[1] = DISK_REMOVEABLE(target) ? 0x80 : 0; /* Removable disk */ - buff[2] = 1; - buff[4] = 33 - 5; - memcpy(&buff[8],"Foo Inc",7); - memcpy(&buff[16],"XYZZY",5); - memcpy(&buff[32],"1",1); - scsi_debug_errsts = 0; - break; - case TEST_UNIT_READY: - SCSI_LOG_LLQUEUE(3,printk("Test unit ready(%p %d)\n", buff, bufflen)); - if (buff) - memset(buff, 0, bufflen); - scsi_debug_errsts = 0; - break; - case READ_CAPACITY: - SCSI_LOG_LLQUEUE(3,printk("Read Capacity\n")); - if(NR_REAL < 0) NR_REAL = (MINOR(SCpnt->request.rq_dev) >> 4) & 0x0f; - memset(buff, 0, bufflen); - buff[0] = (CAPACITY >> 24); - buff[1] = (CAPACITY >> 16) & 0xff; - buff[2] = (CAPACITY >> 8) & 0xff; - buff[3] = CAPACITY & 0xff; - buff[6] = 2; /* 512 byte sectors */ - scsi_debug_errsts = 0; - break; - case READ_10: - case READ_6: + memset(buff, 0, bufflen); + memcpy(buff, sense_buffer, bufflen); + memset(sense_buffer, 0, sizeof(sense_buffer)); + SCpnt->result = 0; + done(SCpnt); + return 0; + case ALLOW_MEDIUM_REMOVAL: + if (cmd[4]) { + SCSI_LOG_LLQUEUE(2, printk("Medium removal inhibited...")); + } else { + SCSI_LOG_LLQUEUE(2, printk("Medium removal enabled...")); + } + scsi_debug_errsts = 0; + break; + case INQUIRY: + SCSI_LOG_LLQUEUE(3, printk("Inquiry...(%p %d)\n", buff, bufflen)); + memset(buff, 0, bufflen); + buff[0] = TYPE_DISK; + buff[1] = DISK_REMOVEABLE(target) ? 0x80 : 0; /* Removable disk */ + buff[2] = 1; + buff[4] = 33 - 5; + memcpy(&buff[8], "Foo Inc", 7); + memcpy(&buff[16], "XYZZY", 5); + memcpy(&buff[32], "1", 1); + scsi_debug_errsts = 0; + break; + case TEST_UNIT_READY: + SCSI_LOG_LLQUEUE(3, printk("Test unit ready(%p %d)\n", buff, bufflen)); + if (buff) + memset(buff, 0, bufflen); + scsi_debug_errsts = 0; + break; + case READ_CAPACITY: + SCSI_LOG_LLQUEUE(3, printk("Read Capacity\n")); + if (NR_REAL < 0) + NR_REAL = (MINOR(SCpnt->request.rq_dev) >> 4) & 0x0f; + memset(buff, 0, bufflen); + buff[0] = (CAPACITY >> 24); + buff[1] = (CAPACITY >> 16) & 0xff; + buff[2] = (CAPACITY >> 8) & 0xff; + buff[3] = CAPACITY & 0xff; + buff[6] = 2; /* 512 byte sectors */ + scsi_debug_errsts = 0; + break; + case READ_10: + case READ_6: #ifdef DEBUG - printk("Read..."); + printk("Read..."); #endif - if ((*cmd) == READ_10) - block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); - else - block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16); - VERIFY_DEBUG(READ); + if ((*cmd) == READ_10) + block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); + else + block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16); + VERIFY_DEBUG(READ); #if defined(SCSI_SETUP_LATENCY) || defined(SCSI_DATARATE) - { - int delay = SCSI_SETUP_LATENCY; - - delay += SCpnt->request.nr_sectors * SCSI_DATARATE; - if(delay) usleep(delay); - }; + { + int delay = SCSI_SETUP_LATENCY; + + delay += SCpnt->request.nr_sectors * SCSI_DATARATE; + if (delay) + usleep(delay); + }; #endif - + #ifdef DEBUG - printk("(r%d)",SCpnt->request.nr_sectors); + printk("(r%d)", SCpnt->request.nr_sectors); #endif - nbytes = bufflen; - if(SCpnt->use_sg){ - sgcount = 0; - sgpnt = (struct scatterlist *) buff; - buff = sgpnt[sgcount].address; - bufflen = sgpnt[sgcount].length; - bh = SCpnt->request.bh; - }; - scsi_debug_errsts = 0; - do{ - VERIFY1_DEBUG(READ); - /* For the speedy test, we do not even want to fill the buffer with anything */ -#ifdef CLEAR - memset(buff, 0, bufflen); -#endif - /* If this is block 0, then we want to read the partition table for this - * device. Let's make one up */ - if(block == 0) { - int i; - memset(buff, 0, bufflen); - *((unsigned short *) (buff+510)) = 0xAA55; - p = (struct partition* ) (buff + 0x1be); - i = 0; - while(starts[i+1]){ - p->start_sect = starts[i]; - p->nr_sects = starts[i+1] - starts [i]; - p->sys_ind = 0x81; /* Linux partition */ - p->head = (i == 0 ? 1 : 0); - p->sector = 1; - p->cyl = starts[i] / N_HEAD / N_SECTOR; - p->end_head = N_HEAD - 1; - p->end_sector = N_SECTOR; - p->end_cyl = starts[i + 1] / N_HEAD / N_SECTOR; - p++; - i++; + nbytes = bufflen; + if (SCpnt->use_sg) { + sgcount = 0; + sgpnt = (struct scatterlist *) buff; + buff = sgpnt[sgcount].address; + bufflen = sgpnt[sgcount].length; + bh = SCpnt->request.bh; }; - if (!npart) npart = i; scsi_debug_errsts = 0; - break; - }; + do { + VERIFY1_DEBUG(READ); + /* For the speedy test, we do not even want to fill the buffer with anything */ +#ifdef CLEAR + memset(buff, 0, bufflen); +#endif + /* If this is block 0, then we want to read the partition table for this + * device. Let's make one up */ + if (block == 0) { + int i; + memset(buff, 0, bufflen); + *((unsigned short *) (buff + 510)) = 0xAA55; + p = (struct partition *) (buff + 0x1be); + i = 0; + while (starts[i + 1]) { + p->start_sect = starts[i]; + p->nr_sects = starts[i + 1] - starts[i]; + p->sys_ind = 0x81; /* Linux partition */ + p->head = (i == 0 ? 1 : 0); + p->sector = 1; + p->cyl = starts[i] / N_HEAD / N_SECTOR; + p->end_head = N_HEAD - 1; + p->end_sector = N_SECTOR; + p->end_cyl = starts[i + 1] / N_HEAD / N_SECTOR; + p++; + i++; + }; + if (!npart) + npart = i; + scsi_debug_errsts = 0; + break; + }; #ifdef DEBUG - if (SCpnt->use_sg) printk("Block %x (%d %d)\n",block, SCpnt->request.nr_sectors, - SCpnt->request.current_nr_sectors); + if (SCpnt->use_sg) + printk("Block %x (%d %d)\n", block, SCpnt->request.nr_sectors, + SCpnt->request.current_nr_sectors); #endif - + #if 0 - /* Simulate a disk change */ - if(block == 0xfff0) { - sense_buffer[0] = 0x70; - sense_buffer[2] = UNIT_ATTENTION; - starts[0] += 10; - starts[1] += 10; - starts[2] += 10; - + /* Simulate a disk change */ + if (block == 0xfff0) { + sense_buffer[0] = 0x70; + sense_buffer[2] = UNIT_ATTENTION; + starts[0] += 10; + starts[1] += 10; + starts[2] += 10; + #ifdef DEBUG - { - int i; - printk("scsi_debug: Filling sense buffer:"); - for(i=0;i<12;i++) printk("%d ",sense_buffer[i]); - printk("\n"); - }; + { + int i; + printk("scsi_debug: Filling sense buffer:"); + for (i = 0; i < 12; i++) + printk("%d ", sense_buffer[i]); + printk("\n"); + }; #endif - scsi_debug_errsts = (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); - break; - } /* End phony disk change code */ + scsi_debug_errsts = (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); + break; + } /* End phony disk change code */ #endif - + #ifdef CLEAR - memcpy(buff, &target, sizeof(target)); - memcpy(buff+sizeof(target), cmd, 24); - memcpy(buff+60, &block, sizeof(block)); - memcpy(buff+64, SCpnt, sizeof(Scsi_Cmnd)); + memcpy(buff, &target, sizeof(target)); + memcpy(buff + sizeof(target), cmd, 24); + memcpy(buff + 60, &block, sizeof(block)); + memcpy(buff + 64, SCpnt, sizeof(Scsi_Cmnd)); #endif - nbytes -= bufflen; - if(SCpnt->use_sg){ + nbytes -= bufflen; + if (SCpnt->use_sg) { #ifdef CLEAR - memcpy(buff+128, bh, sizeof(struct buffer_head)); + memcpy(buff + 128, bh, sizeof(struct buffer_head)); #endif - block += bufflen >> 9; - bh = bh->b_reqnext; - sgcount++; - if (nbytes) { - if(!bh) panic("Too few blocks for linked request."); - buff = sgpnt[sgcount].address; - bufflen = sgpnt[sgcount].length; - }; - } - } while(nbytes); - - SCpnt->result = 0; - (done)(SCpnt); - return 0; - - if (SCpnt->use_sg && !scsi_debug_errsts) - if(bh) scsi_dump(SCpnt, 0); - break; - case WRITE_10: - case WRITE_6: + block += bufflen >> 9; + bh = bh->b_reqnext; + sgcount++; + if (nbytes) { + if (!bh) + panic("Too few blocks for linked request."); + buff = sgpnt[sgcount].address; + bufflen = sgpnt[sgcount].length; + }; + } + } while (nbytes); + + SCpnt->result = 0; + (done) (SCpnt); + return 0; + + if (SCpnt->use_sg && !scsi_debug_errsts) + if (bh) + scsi_dump(SCpnt, 0); + break; + case WRITE_10: + case WRITE_6: #ifdef DEBUG - printk("Write\n"); + printk("Write\n"); #endif - if ((*cmd) == WRITE_10) - block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); - else - block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16); - VERIFY_DEBUG(WRITE); - /* printk("(w%d)",SCpnt->request.nr_sectors); */ - if (SCpnt->use_sg){ - if ((bufflen >> 9) != SCpnt->request.nr_sectors) - panic ("Trying to write wrong number of blocks\n"); - sgpnt = (struct scatterlist *) buff; - buff = sgpnt[sgcount].address; - }; + if ((*cmd) == WRITE_10) + block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); + else + block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16); + VERIFY_DEBUG(WRITE); + /* printk("(w%d)",SCpnt->request.nr_sectors); */ + if (SCpnt->use_sg) { + if ((bufflen >> 9) != SCpnt->request.nr_sectors) + panic("Trying to write wrong number of blocks\n"); + sgpnt = (struct scatterlist *) buff; + buff = sgpnt[sgcount].address; + }; #if 0 - if (block != *((unsigned long *) (buff+60))) { - printk("%x %x :",block, *((unsigned long *) (buff+60))); - scsi_dump(SCpnt,1); - panic("Bad block written.\n"); - }; + if (block != *((unsigned long *) (buff + 60))) { + printk("%x %x :", block, *((unsigned long *) (buff + 60))); + scsi_dump(SCpnt, 1); + panic("Bad block written.\n"); + }; #endif - scsi_debug_errsts = 0; - break; - case MODE_SENSE: - /* - * Used to detect write protected status. - */ - scsi_debug_errsts = 0; - memset(buff, 0, 6); - break; - default: - SCSI_LOG_LLQUEUE(3,printk("Unknown command %d\n",*cmd)); - SCpnt->result = DID_NO_CONNECT << 16; - done(SCpnt); - return 0; - }; - - save_flags(flags); - cli(); - for(i=0;i<SCSI_DEBUG_MAILBOXES; i++){ - if( timeout[i].function == NULL ) break; - }; - - /* - * If all of the slots are full, just return 1. The new error handling scheme - * allows this, and the mid-level should queue things. - */ - if (i >= SCSI_DEBUG_MAILBOXES || timeout[i].function != 0) - { - SCSI_LOG_LLQUEUE(1,printk("Command rejected - host busy\n")); - restore_flags(flags); - return 1; - } - - SCSI_LOG_LLQUEUE(1,printk("Command accepted - slot %d\n", i)); - + scsi_debug_errsts = 0; + break; + case MODE_SENSE: + /* + * Used to detect write protected status. + */ + scsi_debug_errsts = 0; + memset(buff, 0, 6); + break; + default: + SCSI_LOG_LLQUEUE(3, printk("Unknown command %d\n", *cmd)); + SCpnt->result = DID_NO_CONNECT << 16; + done(SCpnt); + return 0; + }; + + save_flags(flags); + cli(); + for (i = 0; i < SCSI_DEBUG_MAILBOXES; i++) { + if (timeout[i].function == NULL) + break; + }; + + /* + * If all of the slots are full, just return 1. The new error handling scheme + * allows this, and the mid-level should queue things. + */ + if (i >= SCSI_DEBUG_MAILBOXES || timeout[i].function != 0) { + SCSI_LOG_LLQUEUE(1, printk("Command rejected - host busy\n")); + restore_flags(flags); + return 1; + } + SCSI_LOG_LLQUEUE(1, printk("Command accepted - slot %d\n", i)); + #ifdef IMMEDIATE - if( !scsi_debug_lockup ) - { - SCpnt->result = scsi_debug_errsts; - scsi_debug_intr_handle(i); /* No timer - do this one right away */ - } - restore_flags(flags); + if (!scsi_debug_lockup) { + SCpnt->result = scsi_debug_errsts; + scsi_debug_intr_handle(i); /* No timer - do this one right away */ + } + restore_flags(flags); #else - - SCpnt->result = scsi_debug_errsts; - timeout[i].function = scsi_debug_intr_handle; - timeout[i].data = i; - timeout[i].expires = jiffies + DISK_SPEED; - SCint[i] = SCpnt; - do_done[i] = done; - - restore_flags(flags); - add_timer(&timeout[i]); - if (!done) - panic("scsi_debug_queuecommand: done can't be NULL\n"); - + + SCpnt->result = scsi_debug_errsts; + timeout[i].function = scsi_debug_intr_handle; + timeout[i].data = i; + timeout[i].expires = jiffies + DISK_SPEED; + SCint[i] = SCpnt; + do_done[i] = done; + + restore_flags(flags); + add_timer(&timeout[i]); + if (!done) + panic("scsi_debug_queuecommand: done can't be NULL\n"); + #if 0 - printk("Sending command (%d %x %d %d)...", i, done, timeout[i].expires,jiffies); + printk("Sending command (%d %x %d %d)...", i, done, timeout[i].expires, jiffies); #endif #endif - - return 0; + + return 0; } volatile static int internal_done_flag = 0; volatile static int internal_done_errcode = 0; static void internal_done(Scsi_Cmnd * SCpnt) { - internal_done_errcode = SCpnt->result; - ++internal_done_flag; + internal_done_errcode = SCpnt->result; + ++internal_done_flag; } int scsi_debug_command(Scsi_Cmnd * SCpnt) { - DEB(printk("scsi_debug_command: ..calling scsi_debug_queuecommand\n")); - scsi_debug_queuecommand(SCpnt, internal_done); - - while (!internal_done_flag); - internal_done_flag = 0; - return internal_done_errcode; + DEB(printk("scsi_debug_command: ..calling scsi_debug_queuecommand\n")); + scsi_debug_queuecommand(SCpnt, internal_done); + + while (!internal_done_flag); + internal_done_flag = 0; + return internal_done_errcode; } /* A "high" level interrupt handler. This should be called once per jiffy @@ -513,184 +520,175 @@ int scsi_debug_command(Scsi_Cmnd * SCpnt) static void scsi_debug_intr_handle(unsigned long indx) { - Scsi_Cmnd * SCtmp; - void (*my_done)(Scsi_Cmnd *); + Scsi_Cmnd *SCtmp; + void (*my_done) (Scsi_Cmnd *); #ifdef DEBUG - int to; + int to; #endif - + #if 0 - del_timer(&timeout[indx]); + del_timer(&timeout[indx]); #endif - - SCtmp = (Scsi_Cmnd *) SCint[indx]; - my_done = do_done[indx]; - do_done[indx] = NULL; - timeout[indx].function = NULL; - SCint[indx] = NULL; - - if (!my_done) { - printk("scsi_debug_intr_handle: Unexpected interrupt\n"); - return; - } - + + SCtmp = (Scsi_Cmnd *) SCint[indx]; + my_done = do_done[indx]; + do_done[indx] = NULL; + timeout[indx].function = NULL; + SCint[indx] = NULL; + + if (!my_done) { + printk("scsi_debug_intr_handle: Unexpected interrupt\n"); + return; + } #ifdef DEBUG - printk("In intr_handle..."); - printk("...done %d %x %d %d\n",i , my_done, to, jiffies); - printk("In intr_handle: %d %x %x\n",i, SCtmp, my_done); + printk("In intr_handle..."); + printk("...done %d %x %d %d\n", i, my_done, to, jiffies); + printk("In intr_handle: %d %x %x\n", i, SCtmp, my_done); #endif - - my_done(SCtmp); + + my_done(SCtmp); #ifdef DEBUG - printk("Called done.\n"); + printk("Called done.\n"); #endif } int scsi_debug_detect(Scsi_Host_Template * tpnt) { - int i; - - for(i=0; i < NR_HOSTS_PRESENT; i++) - { - tpnt->proc_dir = &proc_scsi_scsi_debug; - scsi_register(tpnt,0); - } - return NR_HOSTS_PRESENT; + int i; + + for (i = 0; i < NR_HOSTS_PRESENT; i++) { + tpnt->proc_dir = &proc_scsi_scsi_debug; + scsi_register(tpnt, 0); + } + return NR_HOSTS_PRESENT; } int scsi_debug_abort(Scsi_Cmnd * SCpnt) { #if 0 - int j; - void (*my_done)(Scsi_Cmnd *); - unsigned long flags; + int j; + void (*my_done) (Scsi_Cmnd *); + unsigned long flags; #endif - - DEB(printk("scsi_debug_abort\n")); + + DEB(printk("scsi_debug_abort\n")); #if 0 - SCpnt->result = SCpnt->abort_reason << 16; - for(j=0;j<SCSI_DEBUG_MAILBOXES; j++) { - if(SCpnt == SCint[j]) { - my_done = do_done[j]; - my_done(SCpnt); - save_flags(flags); - cli(); - timeout[j] = 0; - SCint[j] = NULL; - do_done[j] = NULL; - restore_flags(flags); + SCpnt->result = SCpnt->abort_reason << 16; + for (j = 0; j < SCSI_DEBUG_MAILBOXES; j++) { + if (SCpnt == SCint[j]) { + my_done = do_done[j]; + my_done(SCpnt); + save_flags(flags); + cli(); + timeout[j] = 0; + SCint[j] = NULL; + do_done[j] = NULL; + restore_flags(flags); + }; }; - }; #endif - return SCSI_ABORT_SNOOZE; + return SCSI_ABORT_SNOOZE; } -int scsi_debug_biosparam(Disk * disk, kdev_t dev, int* info){ - int size = disk->capacity; - info[0] = N_HEAD; - info[1] = N_SECTOR; - info[2] = (size + 2047) >> 11; - if (info[2] >= 1024) info[2] = 1024; - return 0; +int scsi_debug_biosparam(Disk * disk, kdev_t dev, int *info) +{ + int size = disk->capacity; + info[0] = N_HEAD; + info[1] = N_SECTOR; + info[2] = (size + 2047) >> 11; + if (info[2] >= 1024) + info[2] = 1024; + return 0; } int scsi_debug_reset(Scsi_Cmnd * SCpnt, unsigned int why) { - int i; - unsigned long flags; - - void (*my_done)(Scsi_Cmnd *); - printk("Bus unlocked by reset - %d\n", why); - scsi_debug_lockup = 0; - DEB(printk("scsi_debug_reset called\n")); - for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) { - if (SCint[i] == NULL) continue; - SCint[i]->result = DID_RESET << 16; - my_done = do_done[i]; - my_done(SCint[i]); - save_flags(flags); - cli(); - SCint[i] = NULL; - do_done[i] = NULL; - timeout[i].function = NULL; - restore_flags(flags); - } - return SCSI_RESET_SUCCESS; + int i; + unsigned long flags; + + void (*my_done) (Scsi_Cmnd *); + printk("Bus unlocked by reset - %d\n", why); + scsi_debug_lockup = 0; + DEB(printk("scsi_debug_reset called\n")); + for (i = 0; i < SCSI_DEBUG_MAILBOXES; i++) { + if (SCint[i] == NULL) + continue; + SCint[i]->result = DID_RESET << 16; + my_done = do_done[i]; + my_done(SCint[i]); + save_flags(flags); + cli(); + SCint[i] = NULL; + do_done[i] = NULL; + timeout[i].function = NULL; + restore_flags(flags); + } + return SCSI_RESET_SUCCESS; } const char *scsi_debug_info(void) { - static char buffer[] = " "; /* looks nicer without anything here */ - return buffer; + static char buffer[] = " "; /* looks nicer without anything here */ + return buffer; } /* scsi_debug_proc_info * Used if the driver currently has no own support for /proc/scsi */ -int scsi_debug_proc_info(char *buffer, char **start, off_t offset, - int length, int inode, int inout) +int scsi_debug_proc_info(char *buffer, char **start, off_t offset, + int length, int inode, int inout) { - int len, pos, begin; - int orig_length; - - orig_length = length; - - if(inout == 1) - { - /* First check for the Signature */ - if (length >= 10 && strncmp(buffer, "scsi_debug", 10) == 0) { - buffer += 11; - length -= 11; - - if( buffer[length - 1] == '\n' ) - { - buffer[length-1] = '\0'; - length--; - } - - /* - * OK, we are getting some kind of command. Figure out - * what we are supposed to do here. Simulate bus lockups - * to test our reset capability. - */ - if( length == 6 && strncmp(buffer, "lockup", length) == 0 ) - { - scsi_debug_lockup = 1; - return orig_length; - } - - if( length == 6 && strncmp(buffer, "unlock", length) == 0 ) - { - scsi_debug_lockup = 0; - return orig_length; - } - - printk("Unknown command:%s (%d)\n", buffer, length); - } else - printk("Wrong Signature:%10s\n", (char *) buffer); - - return -EINVAL; - - } - - begin = 0; - pos = len = sprintf(buffer, - "This driver is not a real scsi driver, but it plays one on TV.\n" - "It is very handy for debugging specific problems because you\n" - "can simulate a variety of error conditions\n"); - if(pos < offset) - { - len = 0; - begin = pos; - } - - *start = buffer + (offset - begin); /* Start of wanted data */ - len -= (offset - begin); - if(len > length) - len = length; - - return(len); + int len, pos, begin; + int orig_length; + + orig_length = length; + + if (inout == 1) { + /* First check for the Signature */ + if (length >= 10 && strncmp(buffer, "scsi_debug", 10) == 0) { + buffer += 11; + length -= 11; + + if (buffer[length - 1] == '\n') { + buffer[length - 1] = '\0'; + length--; + } + /* + * OK, we are getting some kind of command. Figure out + * what we are supposed to do here. Simulate bus lockups + * to test our reset capability. + */ + if (length == 6 && strncmp(buffer, "lockup", length) == 0) { + scsi_debug_lockup = 1; + return orig_length; + } + if (length == 6 && strncmp(buffer, "unlock", length) == 0) { + scsi_debug_lockup = 0; + return orig_length; + } + printk("Unknown command:%s (%d)\n", buffer, length); + } else + printk("Wrong Signature:%10s\n", (char *) buffer); + + return -EINVAL; + + } + begin = 0; + pos = len = sprintf(buffer, + "This driver is not a real scsi driver, but it plays one on TV.\n" + "It is very handy for debugging specific problems because you\n" + "can simulate a variety of error conditions\n"); + if (pos < offset) { + len = 0; + begin = pos; + } + *start = buffer + (offset - begin); /* Start of wanted data */ + len -= (offset - begin); + if (len > length) + len = length; + + return (len); } #ifdef MODULE @@ -699,7 +697,7 @@ Scsi_Host_Template driver_template = SCSI_DEBUG; #include "scsi_module.c" #endif - + /* * Overrides for Emacs so that we almost follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically |