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

📄 ncr5380.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			     int length, int hostno, int inout){	unsigned long flags;	char *pos = buffer;	struct Scsi_Host *instance;	struct NCR5380_hostdata *hostdata;	Scsi_Cmnd *ptr;	for (instance = first_instance; instance &&	     instance->host_no != hostno; instance = instance->next);	if (!instance)		return (-ESRCH);	hostdata = (struct NCR5380_hostdata *) instance->hostdata;	if (inout) {		/* Has data been written to the file ? */#ifdef DTC_PUBLIC_RELEASE		dtc_wmaxi = dtc_maxi = 0;#endif#ifdef PAS16_PUBLIC_RELEASE		pas_wmaxi = pas_maxi = 0;#endif		return (-ENOSYS);	/* Currently this is a no-op */	}	SPRINTF("NCR5380 core release=%d.   ", NCR5380_PUBLIC_RELEASE);	if (((struct NCR5380_hostdata *) instance->hostdata)->flags & FLAG_NCR53C400)		SPRINTF("ncr53c400 release=%d.  ", NCR53C400_PUBLIC_RELEASE);#ifdef DTC_PUBLIC_RELEASE	SPRINTF("DTC 3180/3280 release %d", DTC_PUBLIC_RELEASE);#endif#ifdef T128_PUBLIC_RELEASE	SPRINTF("T128 release %d", T128_PUBLIC_RELEASE);#endif#ifdef GENERIC_NCR5380_PUBLIC_RELEASE	SPRINTF("Generic5380 release %d", GENERIC_NCR5380_PUBLIC_RELEASE);#endif#ifdef PAS16_PUBLIC_RELEASE	SPRINTF("PAS16 release=%d", PAS16_PUBLIC_RELEASE);#endif	SPRINTF("\nBase Addr: 0x%05lX    ", (long) instance->base);	SPRINTF("io_port: %04x      ", (int) instance->io_port);	if (instance->irq == IRQ_NONE)		SPRINTF("IRQ: None.\n");	else		SPRINTF("IRQ: %d.\n", instance->irq);#ifdef DTC_PUBLIC_RELEASE	SPRINTF("Highwater I/O busy_spin_counts -- write: %d  read: %d\n",		dtc_wmaxi, dtc_maxi);#endif#ifdef PAS16_PUBLIC_RELEASE	SPRINTF("Highwater I/O busy_spin_counts -- write: %d  read: %d\n",		pas_wmaxi, pas_maxi);#endif	save_flags(flags);	cli();	SPRINTF("NCR5380 : coroutine is%s running.\n", main_running ? "" : "n't");	if (!hostdata->connected)		SPRINTF("scsi%d: no currently connected command\n", instance->host_no);	else		pos = lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected,				       pos, buffer, length);	SPRINTF("scsi%d: issue_queue\n", instance->host_no);	for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr;	     ptr = (Scsi_Cmnd *) ptr->host_scribble)		pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);	SPRINTF("scsi%d: disconnected_queue\n", instance->host_no);	for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;	     ptr = (Scsi_Cmnd *) ptr->host_scribble)		pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);	restore_flags(flags);	*start = buffer;	if (pos - buffer < offset)		return 0;	else if (pos - buffer - offset < length)		return pos - buffer - offset;	return length;}staticchar *lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, char *pos, char *buffer, int length){	SPRINTF("scsi%d : destination target %d, lun %d\n",		cmd->host->host_no, cmd->target, cmd->lun);	SPRINTF("        command = ");	pos = lprint_command(cmd->cmnd, pos, buffer, length);	return (pos);}staticchar *lprint_command(unsigned char *command,		     char *pos, char *buffer, int length){	int i, s;	pos = lprint_opcode(command[0], pos, buffer, length);	for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)		SPRINTF("%02x ", command[i]);	SPRINTF("\n");	return (pos);}staticchar *lprint_opcode(int opcode, char *pos, char *buffer, int length){	SPRINTF("%2d (0x%02x)", opcode, opcode);	return (pos);}/*  * Function : void NCR5380_init (struct Scsi_Host *instance, flags) * * Purpose : initializes *instance and corresponding 5380 chip, *      with flags OR'd into the initial flags value. * * Inputs : instance - instantiation of the 5380 driver.   * * Notes : I assume that the host, hostno, and id bits have been *      set correctly.  I don't care about the irq and other fields.  *  */static void __init NCR5380_init(struct Scsi_Host *instance, int flags){	NCR5380_local_declare();	int i, pass;	unsigned long timeout;	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)	instance->hostdata;	/* 	 * On NCR53C400 boards, NCR5380 registers are mapped 8 past 	 * the base address.	 */#ifdef NCR53C400	if (flags & FLAG_NCR53C400)		instance->NCR5380_instance_name += NCR53C400_address_adjust;#endif	NCR5380_setup(instance);	NCR5380_all_init();	hostdata->aborted = 0;	hostdata->id_mask = 1 << instance->this_id;	for (i = hostdata->id_mask; i <= 0x80; i <<= 1)		if (i > hostdata->id_mask)			hostdata->id_higher_mask |= i;	for (i = 0; i < 8; ++i)		hostdata->busy[i] = 0;#ifdef REAL_DMA	hostdata->dmalen = 0;#endif	hostdata->targets_present = 0;	hostdata->connected = NULL;	hostdata->issue_queue = NULL;	hostdata->disconnected_queue = NULL;#ifdef NCR5380_STATS	for (i = 0; i < 8; ++i) {		hostdata->time_read[i] = 0;		hostdata->time_write[i] = 0;		hostdata->bytes_read[i] = 0;		hostdata->bytes_write[i] = 0;	}	hostdata->timebase = 0;	hostdata->pendingw = 0;	hostdata->pendingr = 0;#endif	/* The CHECK code seems to break the 53C400. Will check it later maybe */	if (flags & FLAG_NCR53C400)		hostdata->flags = FLAG_HAS_LAST_BYTE_SENT | flags;	else		hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT | flags;	if (!the_template) {		the_template = instance->hostt;		first_instance = instance;	}#ifdef USLEEP	hostdata->time_expires = 0;	hostdata->next_timer = NULL;#endif#ifndef AUTOSENSE	if ((instance->cmd_per_lun > 1) || instance->can_queue > 1)		)		    printk("scsi%d : WARNING : support for multiple outstanding commands enabled\n"			   "         without AUTOSENSE option, contingent allegiance conditions may\n"		"         be incorrectly cleared.\n", instance->host_no);#endif				/* def AUTOSENSE */	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);	NCR5380_write(MODE_REG, MR_BASE);	NCR5380_write(TARGET_COMMAND_REG, 0);	NCR5380_write(SELECT_ENABLE_REG, 0);#ifdef NCR53C400	if (hostdata->flags & FLAG_NCR53C400) {		NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);	}#endif	/* 	 * Detect and correct bus wedge problems.	 *	 * If the system crashed, it may have crashed in a state 	 * where a SCSI command was still executing, and the 	 * SCSI bus is not in a BUS FREE STATE.	 *	 * If this is the case, we'll try to abort the currently	 * established nexus which we know nothing about, and that	 * failing, do a hard reset of the SCSI bus 	 */	for (pass = 1; (NCR5380_read(STATUS_REG) & SR_BSY) &&	     pass <= 6; ++pass) {		switch (pass) {		case 1:		case 3:		case 5:			printk("scsi%d: SCSI bus busy, waiting up to five seconds\n",			       instance->host_no);			timeout = jiffies + 5 * HZ;			while (time_before(jiffies,timeout) && (NCR5380_read(STATUS_REG) & SR_BSY));			break;		case 2:			printk("scsi%d: bus busy, attempting abort\n",			       instance->host_no);			do_abort(instance);			break;		case 4:			printk("scsi%d: bus busy, attempting reset\n",			       instance->host_no);			do_reset(instance);			break;		case 6:			printk("scsi%d: bus locked solid or invalid override\n",			       instance->host_no);		}	}}/*  * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd,  *      void (*done)(Scsi_Cmnd *))  * * Purpose :  enqueues a SCSI command * * Inputs : cmd - SCSI command, done - function called on completion, with *      a pointer to the command descriptor. *  * Returns : 0 * * Side effects :  *      cmd is added to the per instance issue_queue, with minor  *      twiddling done to the host specific fields of cmd.  If the  *      main coroutine is not running, it is restarted. * *//* Only make static if a wrapper function is used */#ifndef NCR5380_queue_commandstatic#endifint NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) {	struct Scsi_Host *instance = cmd->host;	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)	 instance->hostdata;	Scsi_Cmnd *tmp;#if (NDEBUG & NDEBUG_NO_WRITE)	switch (cmd->cmnd[0]) {		case WRITE_6:		    case WRITE_10:		    printk("scsi%d : WRITE attempted with NO_WRITE debugging flag set\n",			   instance->host_no);		cmd->result = (DID_ERROR << 16);		done(cmd);		return 0;	}#endif				/* (NDEBUG & NDEBUG_NO_WRITE) */#ifdef NCR5380_STATS#if 0	if (!hostdata->connected && !hostdata->issue_queue &&	    !hostdata->disconnected_queue) {		hostdata->timebase = jiffies;	}#endif#ifdef NCR5380_STAT_LIMIT	if (cmd->request_bufflen > NCR5380_STAT_LIMIT)#endif		switch (cmd->cmnd[0]) {			case WRITE:			    case WRITE_6:			    case WRITE_10:			    hostdata->time_write[cmd->target] -= (jiffies - hostdata->timebase);			hostdata->bytes_write[cmd->target] += cmd->request_bufflen;			hostdata->pendingw++;			break;			case READ:			    case READ_6:			    case READ_10:			    hostdata->time_read[cmd->target] -= (jiffies - hostdata->timebase);			hostdata->bytes_read[cmd->target] += cmd->request_bufflen;			hostdata->pendingr++;			break;		}#endif	/* 	 * We use the host_scribble field as a pointer to the next command  	 * in a queue 	 */	cmd->host_scribble = NULL;	cmd->scsi_done = done;	cmd->result = 0;	/* 	 * Insert the cmd into the issue queue. Note that REQUEST SENSE 	 * commands are added to the head of the queue since any command will	 * clear the contingent allegiance condition that exists and the 	 * sense data is only guaranteed to be valid while the condition exists.	 */	if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {		LIST(cmd, hostdata->issue_queue);		cmd->host_scribble = (unsigned char *) hostdata->issue_queue;		hostdata->issue_queue = cmd;	} else {		for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp->host_scribble;		     tmp = (Scsi_Cmnd *) tmp->host_scribble);		LIST(cmd, tmp);		tmp->host_scribble = (unsigned char *) cmd;	}#if (NDEBUG & NDEBUG_QUEUES)	printk("scsi%d : command added to %s of queue\n", instance->host_no,	       (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");#endif/* Run the coroutine if it isn't already running. */	run_main();	return 0;}/* * Function : NCR5380_main (void)  * * Purpose : NCR5380_main is a coroutine that runs as long as more work can  *      be done on the NCR5380 host adapters in a system.  Both  *      NCR5380_queue_command() and NCR5380_intr() will try to start it  *      in case it is not running. *  * NOTE : NCR5380_main exits with interrupts *disabled*, the caller should  *  reenable them.  This prevents reentrancy and kernel stack overflow. */static void NCR5380_main(void) {	Scsi_Cmnd *tmp, *prev;	struct Scsi_Host *instance;	struct NCR5380_hostdata *hostdata;	int done;	unsigned long flags;	/*	 * We run (with interrupts disabled) until we're sure that none of 	 * the host adapters have anything that can be done, at which point 	 * we set main_running to 0 and exit.	 *	 * Interrupts are enabled before doing various other internal 	 * instructions, after we've decided that we need to run through	 * the loop again.	 *	 * this should prevent any race conditions.	 */	spin_unlock_irq(&io_request_lock);		save_flags(flags);		do {		cli();		/* Freeze request queues */		done = 1;		for (instance = first_instance; instance &&		     instance->hostt == the_template; instance = instance->next) {			 hostdata = (struct NCR5380_hostdata *) instance->hostdata;			 cli();#ifdef USLEEP			if (!hostdata->connected && !hostdata->selecting) {#else			if (!hostdata->connected) {#endif			#if (NDEBUG & NDEBUG_MAIN)				printk("scsi%d : not connected\n", instance->host_no);#endif				/*				 * Search through the issue_queue for a command destined				 * for a target that's not busy.				 */#if (NDEBUG & NDEBUG_LISTS)				for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp && (tmp != prev); prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble);				/*printk("%p  ", tmp); */				if ((tmp == prev) && tmp)					printk(" LOOP\n");	/* else printk("\n"); */#endif				for (tmp = (Scsi_Cmnd *) hostdata->issue_queue,				     prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *)				     tmp->host_scribble) {#if (NDEBUG & NDEBUG_LISTS)					if (prev != tmp)						printk("MAIN tmp=%p   target=%d   busy=%d lun=%d\n", tmp, tmp->target, hostdata->busy[tmp->target], tmp->lun);#endif					/*  When we find one, remove it from the issue queue. */					if (!(hostdata->busy[tmp->target] & (1 << tmp->lun))) {						if (prev) {							REMOVE(prev, prev->host_scribble, tmp, tmp->host_scribble);							prev->host_scribble = tmp->host_scribble;						} else {							REMOVE(-1, hostdata->issue_queue, tmp, tmp->host_scribble);							hostdata->issue_queue = (Scsi_Cmnd *) tmp->host_scribble;						}						tmp->host_scribble = NULL;						/* reenable interrupts after finding one */						restore_flags(flags);						/* 						 * Attempt to establish an I_T_L nexus here. 						 * On success, instance->hostdata->connected is set.						 * On failure, we must add the command back to the						 *   issue queue so we can keep trying. 						 */#if (NDEBUG & (NDEBUG_MAIN | NDEBUG_QUEUES))						printk("scsi%d : main() : command for target %d lun %d removed from issue_queue\n",						       instance->host_no, tmp->target, tmp->lun);#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -