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

📄 seagate.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 4 页
字号:
		DANY ("Base address overridden to %x, controller type is %s\n",		      base_address,		      controller_type == SEAGATE ? "SEAGATE" : "FD");#else				/* OVERRIDE *//* * 	To detect this card, we simply look for the signature *      from the BIOS version notice in all the possible locations *      of the ROM's.  This has a nice side effect of not trashing *      any register locations that might be used by something else. * * XXX - note that we probably should be probing the address * space for the on-board RAM instead. */		for (i = 0;		     i < (sizeof (seagate_bases) / sizeof (unsigned int)); ++i)			for (j = 0; !base_address && j < NUM_SIGNATURES; ++j)				if (isa_check_signature				    (seagate_bases[i] + signatures[j].offset,				     signatures[j].signature,				     signatures[j].length)) {					base_address = seagate_bases[i];					controller_type = signatures[j].type;				}#endif				/* OVERRIDE */	}	/* (! controller_type) */	tpnt->this_id = (controller_type == SEAGATE) ? 7 : 6;	tpnt->name = (controller_type == SEAGATE) ? ST0X_ID_STR : FD_ID_STR;	if (!base_address) {		DANY ("ST0x / TMC-8xx not detected.\n");		return 0;	}	st0x_cr_sr =	    base_address + (controller_type == SEAGATE ? 0x1a00 : 0x1c00);	st0x_dr = st0x_cr_sr + 0x200;	DANY ("%s detected. Base address = %x, cr = %x, dr = %x\n",	      tpnt->name, base_address, st0x_cr_sr, st0x_dr);/* *	At all times, we will use IRQ 5.  Should also check for IRQ3 if we *      loose our first interrupt. */	instance = scsi_register (tpnt, 0);	if (instance == NULL)		return 0;	hostno = instance->host_no;	if (request_irq (irq, do_seagate_reconnect_intr, SA_INTERRUPT,			 (controller_type == SEAGATE) ? "seagate" : "tmc-8xx",			 NULL)) {		printk ("scsi%d : unable to allocate IRQ%d\n", hostno, irq);		return 0;	}	instance->irq = irq;	instance->io_port = base_address;#ifdef SLOW_RATE	printk (KERN_INFO "Calibrating borken timer... ");	borken_init ();	printk (" %d cycles per transfer\n", borken_calibration);#endif	printk (KERN_INFO "This is one second... ");	{		int clock;		ULOOP (1 * 1000 * 1000) {			STATUS;			if (TIMEOUT)				break;		}	}	printk ("done, %s options:"#ifdef ARBITRATE		" ARBITRATE"#endif#ifdef DEBUG		" DEBUG"#endif#ifdef FAST		" FAST"#ifdef FAST32		"32"#endif#endif#ifdef LINKED		" LINKED"#endif#ifdef PARITY		" PARITY"#endif#ifdef SEAGATE_USE_ASM		" SEAGATE_USE_ASM"#endif#ifdef SLOW_RATE		" SLOW_RATE"#endif#ifdef SWAPSTAT		" SWAPSTAT"#endif#ifdef SWAPCNTDATA		" SWAPCNTDATA"#endif		"\n", tpnt->name);	return 1;}const char *seagate_st0x_info (struct Scsi_Host *shpnt){	static char buffer[64];	sprintf (buffer, "%s at irq %d, address 0x%05X",		 (controller_type == SEAGATE) ? ST0X_ID_STR : FD_ID_STR,		 irq, base_address);	return buffer;}/* * These are our saved pointers for the outstanding command that is * waiting for a reconnect */static unsigned char current_target, current_lun;static unsigned char *current_cmnd, *current_data;static int current_nobuffs;static struct scatterlist *current_buffer;static int current_bufflen;#ifdef LINKED/* * linked_connected indicates whether or not we are currently connected to * linked_target, linked_lun and in an INFORMATION TRANSFER phase, * using linked commands. */static int linked_connected = 0;static unsigned char linked_target, linked_lun;#endifstatic void (*done_fn) (Scsi_Cmnd *) = NULL;static Scsi_Cmnd *SCint = NULL;/* * These control whether or not disconnect / reconnect will be attempted, * or are being attempted. */#define NO_RECONNECT    0#define RECONNECT_NOW   1#define CAN_RECONNECT   2/* * LINKED_RIGHT indicates that we are currently connected to the correct target * for this command, LINKED_WRONG indicates that we are connected to the wrong * target. Note that these imply CAN_RECONNECT and require defined(LINKED). */#define LINKED_RIGHT    3#define LINKED_WRONG    4/* * This determines if we are expecting to reconnect or not. */static int should_reconnect = 0;/* * The seagate_reconnect_intr routine is called when a target reselects the * host adapter.  This occurs on the interrupt triggered by the target * asserting SEL. */static void do_seagate_reconnect_intr (int irq, void *dev_id, struct pt_regs *regs){	unsigned long flags;	spin_lock_irqsave (&io_request_lock, flags);	seagate_reconnect_intr (irq, dev_id, regs);	spin_unlock_irqrestore (&io_request_lock, flags);}static void seagate_reconnect_intr (int irq, void *dev_id, struct pt_regs *regs){	int temp;	Scsi_Cmnd *SCtmp;	DPRINTK (PHASE_RESELECT, "scsi%d : seagate_reconnect_intr() called\n",		 hostno);	if (!should_reconnect)		printk ("scsi%d: unexpected interrupt.\n", hostno);	else {		should_reconnect = 0;		DPRINTK (PHASE_RESELECT, "scsi%d : internal_command("			 "%d, %08x, %08x, RECONNECT_NOW\n", hostno,			 current_target, current_data, current_bufflen);		temp =		    internal_command (current_target, current_lun, current_cmnd,				      current_data, current_bufflen,				      RECONNECT_NOW);		if (msg_byte (temp) != DISCONNECT) {			if (done_fn) {				DPRINTK (PHASE_RESELECT,					 "scsi%d : done_fn(%d,%08x)", hostno,					 hostno, temp);				if (!SCint)					panic ("SCint == NULL in seagate");				SCtmp = SCint;				SCint = NULL;				SCtmp->result = temp;				done_fn (SCtmp);			} else				printk ("done_fn() not defined.\n");		}	}}/* * The seagate_st0x_queue_command() function provides a queued interface * to the seagate SCSI driver.  Basically, it just passes control onto the * seagate_command() function, after fixing it so that the done_fn() * is set to the one passed to the function.  We have to be very careful, * because there are some commands on some devices that do not disconnect, * and if we simply call the done_fn when the command is done then another * command is started and queue_command is called again...  We end up * overflowing the kernel stack, and this tends not to be such a good idea. */static int recursion_depth = 0;int seagate_st0x_queue_command (Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)){	int result, reconnect;	Scsi_Cmnd *SCtmp;	DANY ("seagate: que_command");	done_fn = done;	current_target = SCpnt->target;	current_lun = SCpnt->lun;	(const void *) current_cmnd = SCpnt->cmnd;	current_data = (unsigned char *) SCpnt->request_buffer;	current_bufflen = SCpnt->request_bufflen;	SCint = SCpnt;	if (recursion_depth)		return 0;	recursion_depth++;	do {#ifdef LINKED/* * Set linked command bit in control field of SCSI command. */		current_cmnd[SCpnt->cmd_len] |= 0x01;		if (linked_connected) {			DPRINTK (DEBUG_LINKED,				 "scsi%d : using linked commands, current I_T_L nexus is ",				 hostno);			if ((linked_target == current_target)			    && (linked_lun == current_lun)) {				DPRINTK (DEBUG_LINKED, "correct\n");				reconnect = LINKED_RIGHT;			} else {				DPRINTK (DEBUG_LINKED, "incorrect\n");				reconnect = LINKED_WRONG;			}		} else#endif				/* LINKED */			reconnect = CAN_RECONNECT;		result =		    internal_command (SCint->target, SCint->lun, SCint->cmnd,				      SCint->request_buffer,				      SCint->request_bufflen, reconnect);		if (msg_byte (result) == DISCONNECT)			break;		SCtmp = SCint;		SCint = NULL;		SCtmp->result = result;		done_fn (SCtmp);	}	while (SCint);	recursion_depth--;	return 0;}int seagate_st0x_command (Scsi_Cmnd * SCpnt){	return internal_command (SCpnt->target, SCpnt->lun, SCpnt->cmnd,				 SCpnt->request_buffer, SCpnt->request_bufflen,				 (int) NO_RECONNECT);}static int internal_command (unsigned char target, unsigned char lun,		  const void *cmnd, void *buff, int bufflen, int reselect){	unsigned char *data = NULL;	struct scatterlist *buffer = NULL;	int clock, temp, nobuffs = 0, done = 0, len = 0;	unsigned long flags;#ifdef DEBUG	int transfered = 0, phase = 0, newphase;#endif	register unsigned char status_read;	unsigned char tmp_data, tmp_control, status = 0, message = 0;	unsigned transfersize = 0, underflow = 0;#ifdef SLOW_RATE	int borken = (int) SCint->device->borken;	/* Does the current target require							   Very Slow I/O ?  */#endif	incommand = 0;	st0x_aborted = 0;#if (DEBUG & PRINT_COMMAND)	printk ("scsi%d : target = %d, command = ", hostno, target);	print_command ((unsigned char *) cmnd);#endif#if (DEBUG & PHASE_RESELECT)	switch (reselect) {	case RECONNECT_NOW:		printk ("scsi%d : reconnecting\n", hostno);		break;#ifdef LINKED	case LINKED_RIGHT:		printk ("scsi%d : connected, can reconnect\n", hostno);		break;	case LINKED_WRONG:		printk ("scsi%d : connected to wrong target, can reconnect\n",			hostno);		break;#endif	case CAN_RECONNECT:		printk ("scsi%d : allowed to reconnect\n", hostno);		break;	default:		printk ("scsi%d : not allowed to reconnect\n", hostno);	}#endif	if (target == (controller_type == SEAGATE ? 7 : 6))		return DID_BAD_TARGET;/* *	We work it differently depending on if this is is "the first time," *      or a reconnect.  If this is a reselect phase, then SEL will *      be asserted, and we must skip selection / arbitration phases. */	switch (reselect) {	case RECONNECT_NOW:		DPRINTK (PHASE_RESELECT, "scsi%d : phase RESELECT \n", hostno);/* *	At this point, we should find the logical or of our ID and the original *      target's ID on the BUS, with BSY, SEL, and I/O signals asserted. * *      After ARBITRATION phase is completed, only SEL, BSY, and the *      target ID are asserted.  A valid initiator ID is not on the bus *      until IO is asserted, so we must wait for that. */		ULOOP (100 * 1000) {			temp = STATUS;			if ((temp & STAT_IO) && !(temp & STAT_BSY))				break;			if (TIMEOUT) {				DPRINTK (PHASE_RESELECT,					 "scsi%d : RESELECT timed out while waiting for IO .\n",					 hostno);				return (DID_BAD_INTR << 16);			}		}/* *	After I/O is asserted by the target, we can read our ID and its *      ID off of the BUS. */		if (!		    ((temp =		      DATA) & (controller_type == SEAGATE ? 0x80 : 0x40))) {			DPRINTK (PHASE_RESELECT,				 "scsi%d : detected reconnect request to different target.\n"				 "\tData bus = %d\n", hostno, temp);			return (DID_BAD_INTR << 16);		}		if (!(temp & (1 << current_target))) {			printk			    ("scsi%d : Unexpected reselect interrupt.  Data bus = %d\n",			     hostno, temp);			return (DID_BAD_INTR << 16);		}		buffer = current_buffer;		cmnd = current_cmnd;	/* WDE add */		data = current_data;	/* WDE add */		len = current_bufflen;	/* WDE add */		nobuffs = current_nobuffs;/* *	We have determined that we have been selected.  At this point, *      we must respond to the reselection by asserting BSY ourselves */#if 1		WRITE_CONTROL (BASE_CMD | CMD_DRVR_ENABLE | CMD_BSY);#else		WRITE_CONTROL (BASE_CMD | CMD_BSY);#endif/* *	The target will drop SEL, and raise BSY, at which time we must drop *      BSY. */		ULOOP (100 * 1000) {			if (!(STATUS & STAT_SEL))				break;			if (TIMEOUT) {				WRITE_CONTROL (BASE_CMD | CMD_INTR);				DPRINTK (PHASE_RESELECT,					 "scsi%d : RESELECT timed out while waiting for SEL.\n",					 hostno);				return (DID_BAD_INTR << 16);			}		}		WRITE_CONTROL (BASE_CMD);/* *	At this point, we have connected with the target and can get *      on with our lives. */		break;	case CAN_RECONNECT:#ifdef LINKED

⌨️ 快捷键说明

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