📄 scsi_debug.c
字号:
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"); };#endif 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));#endif nbytes -= bufflen; if(SCpnt->use_sg){#ifdef CLEAR 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:#ifdef DEBUG 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 0 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)); #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);#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"); #if 0 printk("Sending command (%d %x %d %d)...", i, done, timeout[i].expires,jiffies);#endif#endif 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;}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;}/* A "high" level interrupt handler. This should be called once per jiffy * to simulate a regular scsi disk. We use a timer to do this. */static void scsi_debug_intr_handle(unsigned long indx){ Scsi_Cmnd * SCtmp; void (*my_done)(Scsi_Cmnd *); #ifdef DEBUG int to;#endif #if 0 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; } #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);#endif my_done(SCtmp);#ifdef DEBUG 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 scsi_debug_abort(Scsi_Cmnd * SCpnt){#if 0 int j; void (*my_done)(Scsi_Cmnd *); unsigned long flags;#endif 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); }; };#endif 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_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;}const char *scsi_debug_info(void){ 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 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/* Eventually this will go into an include file, but this will be later */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 * adjust the settings for this buffer only. This must remain at the end * of the file. * --------------------------------------------------------------------------- * Local variables: * c-indent-level: 4 * c-brace-imaginary-offset: 0 * c-brace-offset: -4 * c-argdecl-indent: 4 * c-label-offset: -4 * c-continued-statement-offset: 4 * c-continued-brace-offset: 0 * indent-tabs-mode: nil * tab-width: 8 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -