⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scsi_debug.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
#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;#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;		SCint[i] = SCpnt;		do_done[i] = done;		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;}static void scsi_debug_send_self_command(struct Scsi_Host * shpnt){	static unsigned char cmd[6] =	{TEST_UNIT_READY, 0, 0, 0, 0, 0};        Scsi_Request  * scp;        Scsi_Device   * sdev;                printk("Allocating host dev\n");        sdev = scsi_get_host_dev(shpnt);        if(sdev==NULL)        {        	printk("Out of memory.\n");        	return;        }                printk("Got %p. Allocating command block\n", sdev);        scp  = scsi_allocate_request(sdev);        printk("Got %p\n", scp);                if(scp==NULL)        {        	printk("Out of memory.\n");        	goto bail;        }        scp->sr_cmd_len = 6;        scp->sr_use_sg = 0;                printk("Sending command\n");        scsi_wait_req (scp, (void *) cmd, (void *) NULL,                       0, 100, 3);                printk("Releasing command\n");        scsi_release_request(scp);bail:	printk("Freeing device\n");        scsi_free_host_dev(sdev);}/* 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_name = "scsi_debug";	/* Huh? In the loop??? */		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] = N_CYLINDER;	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 == 4 && strncmp(buffer, "test", length) == 0) {                                printk("Testing send self command %p\n", SHpnt);                                scsi_debug_send_self_command(SHpnt);                                return orig_length;                        }			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 CONFIG_USER_DEBUG/* * This is a hack for the user space emulator.  It allows us to * "insert" arbitrary numbers of additional drivers. */void *scsi_debug_get_handle(void){	static Scsi_Host_Template driver_copy = SCSI_DEBUG;	void *rtn;	rtn = kmalloc(sizeof(driver_copy), GFP_ATOMIC);	if(rtn==NULL)		return NULL;	memcpy(rtn, (void *) &driver_copy, sizeof(driver_copy));	return rtn;}#endif/* Eventually this will go into an include file, but this will be later */static Scsi_Host_Template driver_template = SCSI_DEBUG;#include "scsi_module.c"/* * 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 + -