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

📄 seagate.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * This is a bletcherous hack, just as bad as the Unix #! interpreter stuff. * If it turns out we are using the wrong I_T_L nexus, the easiest way to deal * with it is to go into our INFORMATION TRANSFER PHASE code, send a ABORT * message on MESSAGE OUT phase, and then loop back to here. */	      connect_loop:#endif		DPRINTK (PHASE_BUS_FREE, "scsi%d : phase = BUS FREE \n",			 hostno);/* *    BUS FREE PHASE * *      On entry, we make sure that the BUS is in a BUS FREE *      phase, by insuring that both BSY and SEL are low for *      at least one bus settle delay.  Several reads help *      eliminate wire glitch. */#ifndef ARBITRATE#error FIXME: this is broken: we may not use jiffies here - we are under cli(). It will hardlock.		clock = jiffies + ST0X_BUS_FREE_DELAY;		while (((STATUS | STATUS | STATUS) &			(STAT_BSY | STAT_SEL)) &&		       (!st0x_aborted) && time_before (jiffies, clock)) ;		if (time_after (jiffies, clock))			return retcode (DID_BUS_BUSY);		else if (st0x_aborted)			return retcode (st0x_aborted);#endif		DPRINTK (PHASE_SELECTION, "scsi%d : phase = SELECTION\n",			 hostno);		clock = jiffies + ST0X_SELECTION_DELAY;/* * Arbitration/selection procedure : * 1.  Disable drivers * 2.  Write HOST adapter address bit * 3.  Set start arbitration. * 4.  We get either ARBITRATION COMPLETE or SELECT at this *     point. * 5.  OR our ID and targets on bus. * 6.  Enable SCSI drivers and asserted SEL and ATTN */#ifdef ARBITRATE		save_flags (flags);		cli ();		WRITE_CONTROL (0);		WRITE_DATA ((controller_type == SEAGATE) ? 0x80 : 0x40);		WRITE_CONTROL (CMD_START_ARB);		restore_flags (flags);		ULOOP (ST0X_SELECTION_DELAY * 10000) {			status_read = STATUS;			if (status_read & STAT_ARB_CMPL)				break;			if (st0x_aborted)	/* FIXME: What? We are going to do something even after abort? */				break;			if (TIMEOUT || (status_read & STAT_SEL)) {				printk				    ("scsi%d : arbitration lost or timeout.\n",				     hostno);				WRITE_CONTROL (BASE_CMD);				return retcode (DID_NO_CONNECT);			}		}		DPRINTK (PHASE_SELECTION, "scsi%d : arbitration complete\n",			 hostno);#endif/* *    When the SCSI device decides that we're gawking at it, it will *    respond by asserting BUSY on the bus. * *    Note : the Seagate ST-01/02 product manual says that we should *    twiddle the DATA register before the control register.    However, *    this does not work reliably so we do it the other way around. * *    Probably could be a problem with arbitration too, we really should *    try this with a SCSI protocol or logic analyzer to see what is *    going on. */		tmp_data =		    (unsigned char) ((1 << target) |				     (controller_type ==				      SEAGATE ? 0x80 : 0x40));		tmp_control =		    BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL | (reselect ? CMD_ATTN							    : 0);		save_flags (flags);		cli ();#ifdef OLDCNTDATASCEME#ifdef SWAPCNTDATA		WRITE_CONTROL (tmp_control);		WRITE_DATA (tmp_data);#else		WRITE_DATA (tmp_data);		WRITE_CONTROL (tmp_control);#endif#else		tmp_control ^= CMD_BSY;	/* This is guesswork. What used to be in driver    */		WRITE_CONTROL (tmp_control);	/* could never work: it sent data into control     */		WRITE_DATA (tmp_data);	/* register and control info into data. Hopefully  */		tmp_control ^= CMD_BSY;	/* fixed, but order of first two may be wrong.     */		WRITE_CONTROL (tmp_control);	/* -- pavel@ucw.cz   */#endif		restore_flags (flags);		ULOOP (250 * 1000) {			if (st0x_aborted) {/* *	If we have been aborted, and we have a command in progress, IE the *      target still has BSY asserted, then we will reset the bus, and *      notify the midlevel driver to expect sense. */				WRITE_CONTROL (BASE_CMD);				if (STATUS & STAT_BSY) {					printk					    ("scsi%d : BST asserted after we've been aborted.\n",					     hostno);					seagate_st0x_reset (NULL, 0);					return retcode (DID_RESET);				}				return retcode (st0x_aborted);			}			if (STATUS & STAT_BSY)				break;			if (TIMEOUT) {				DPRINTK (PHASE_SELECTION,					 "scsi%d : NO CONNECT with target %d, stat = %x \n",					 hostno, target, STATUS);				return retcode (DID_NO_CONNECT);			}		}/* Establish current pointers.  Take into account scatter / gather */		if ((nobuffs = SCint->use_sg)) {#if (DEBUG & DEBUG_SG)			{				int i;				printk				    ("scsi%d : scatter gather requested, using %d buffers.\n",				     hostno, nobuffs);				for (i = 0; i < nobuffs; ++i)					printk					    ("scsi%d : buffer %d address = %08x length = %d\n",					     hostno, i, buffer[i].address,					     buffer[i].length);			}#endif			buffer = (struct scatterlist *) SCint->buffer;			len = buffer->length;			data = (unsigned char *) buffer->address;		} else {			DPRINTK (DEBUG_SG,				 "scsi%d : scatter gather not requested.\n",				 hostno);			buffer = NULL;			len = SCint->request_bufflen;			data = (unsigned char *) SCint->request_buffer;		}		DPRINTK (PHASE_DATAIN | PHASE_DATAOUT, "scsi%d : len = %d\n",			 hostno, len);		break;#ifdef LINKED	case LINKED_RIGHT:		break;	case LINKED_WRONG:		break;#endif	}			/* end of switch(reselect) *//* *    There are several conditions under which we wish to send a message : *      1.  When we are allowing disconnect / reconnect, and need to establish *          the I_T_L nexus via an IDENTIFY with the DiscPriv bit set. * *      2.  When we are doing linked commands, are have the wrong I_T_L nexus *          established and want to send an ABORT message. *//* GCC does not like an ifdef inside a macro, so do it the hard way. */#ifdef LINKED	WRITE_CONTROL (BASE_CMD | CMD_DRVR_ENABLE |		       (((reselect == CAN_RECONNECT)			 || (reselect == LINKED_WRONG)			)? CMD_ATTN : 0));#else	WRITE_CONTROL (BASE_CMD | CMD_DRVR_ENABLE |		       (((reselect == CAN_RECONNECT)			)? CMD_ATTN : 0));#endif/* *    INFORMATION TRANSFER PHASE * *      The nasty looking read / write inline assembler loops we use for *      DATAIN and DATAOUT phases are approximately 4-5 times as fast as *      the 'C' versions - since we're moving 1024 bytes of data, this *      really adds up. * *      SJT: The nasty-looking assembler is gone, so it's slower. * */	DPRINTK (PHASE_ETC, "scsi%d : phase = INFORMATION TRANSFER\n", hostno);	incommand = 1;	transfersize = SCint->transfersize;	underflow = SCint->underflow;/* *	Now, we poll the device for status information, *      and handle any requests it makes.  Note that since we are unsure of *      how much data will be flowing across the system, etc and cannot *      make reasonable timeouts, that we will instead have the midlevel *      driver handle any timeouts that occur in this phase. */	while (((status_read = STATUS) & STAT_BSY) && !st0x_aborted && !done) {#ifdef PARITY		if (status_read & STAT_PARITY) {			printk ("scsi%d : got parity error\n", hostno);			st0x_aborted = DID_PARITY;		}#endif		if (status_read & STAT_REQ) {#if ((DEBUG & PHASE_ETC) == PHASE_ETC)			if ((newphase = (status_read & REQ_MASK)) != phase) {				phase = newphase;				switch (phase) {				case REQ_DATAOUT:					printk ("scsi%d : phase = DATA OUT\n",						hostno);					break;				case REQ_DATAIN:					printk ("scsi%d : phase = DATA IN\n",						hostno);					break;				case REQ_CMDOUT:					printk					    ("scsi%d : phase = COMMAND OUT\n",					     hostno);					break;				case REQ_STATIN:					printk ("scsi%d : phase = STATUS IN\n",						hostno);					break;				case REQ_MSGOUT:					printk					    ("scsi%d : phase = MESSAGE OUT\n",					     hostno);					break;				case REQ_MSGIN:					printk ("scsi%d : phase = MESSAGE IN\n",						hostno);					break;				default:					printk ("scsi%d : phase = UNKNOWN\n",						hostno);					st0x_aborted = DID_ERROR;				}			}#endif			switch (status_read & REQ_MASK) {			case REQ_DATAOUT:/* * If we are in fast mode, then we simply splat the data out * in word-sized chunks as fast as we can. */				if (!len) {#if 0					printk					    ("scsi%d: underflow to target %d lun %d \n",					     hostno, target, lun);					st0x_aborted = DID_ERROR;					fast = 0;#endif					break;				}				if (fast && transfersize				    && !(len % transfersize)				    && (len >= transfersize)#ifdef FAST32				    && !(transfersize % 4)#endif				    ) {					DPRINTK (DEBUG_FAST,						 "scsi%d : FAST transfer, underflow = %d, transfersize = %d\n"						 "         len = %d, data = %08x\n",						 hostno, SCint->underflow,						 SCint->transfersize, len,						 data);/* SJT: Start. Fast Write */#ifdef SEAGATE_USE_ASM					__asm__ ("cld\n\t"#ifdef FAST32						 "shr $2, %%ecx\n\t"						 "1:\t"						 "lodsl\n\t"						 "movl %%eax, (%%edi)\n\t"#else						 "1:\t"						 "lodsb\n\t"						 "movb %%al, (%%edi)\n\t"#endif						 "loop 1b;"				      /* output */ :				      /* input */ :"D" (phys_to_virt (st0x_dr)),						 "S"						 (data),						 "c" (SCint->transfersize)/* clobbered */				      :	 "eax", "ecx",						 "esi");#else				/* SEAGATE_USE_ASM */					{#ifdef FAST32						unsigned int *iop =						    phys_to_virt (st0x_dr);						const unsigned int *dp =						    (unsigned int *) data;						int xferlen = transfersize >> 2;#else						unsigned char *iop =						    phys_to_virt (st0x_dr);						const unsigned char *dp = data;						int xferlen = transfersize;#endif						for (; xferlen; --xferlen)							*iop = *dp++;					}#endif				/* SEAGATE_USE_ASM *//* SJT: End */					len -= transfersize;					data += transfersize;					DPRINTK (DEBUG_FAST,						 "scsi%d : FAST transfer complete len = %d data = %08x\n",						 hostno, len, data);				} else {/* *    We loop as long as we are in a data out phase, there is data to send, *      and BSY is still active. *//* SJT: Start. Slow Write. */#ifdef SEAGATE_USE_ASM					int __dummy_1, __dummy_2;/* *      We loop as long as we are in a data out phase, there is data to send,  *      and BSY is still active. *//* Local variables : len = ecx , data = esi,                      st0x_cr_sr = ebx, st0x_dr =  edi*/					__asm__ (							/* Test for any data here at all. */							"orl %%ecx, %%ecx\n\t"							"jz 2f\n\t" "cld\n\t"/*                    "movl " SYMBOL_NAME_STR(st0x_cr_sr) ", %%ebx\n\t"  *//*                    "movl " SYMBOL_NAME_STR(st0x_dr) ", %%edi\n\t"  */							"1:\t"							"movb (%%ebx), %%al\n\t"							/* Test for BSY */							"test $1, %%al\n\t"							"jz 2f\n\t"							/* Test for data out phase - STATUS & REQ_MASK should be 							   REQ_DATAOUT, which is 0. */							"test $0xe, %%al\n\t"							"jnz 2f\n\t"							/* Test for REQ */							"test $0x10, %%al\n\t"							"jz 1b\n\t"							"lodsb\n\t"							"movb %%al, (%%edi)\n\t"							"loop 1b\n\t" "2:\n"				      /* output */ :"=S" (data), "=c" (len),							"=b"							(__dummy_1),							"=D" (__dummy_2)/* input */				      :		"0" (data), "1" (len),							"2" (phys_to_virt							     (st0x_cr_sr)),							"3" (phys_to_virt							     (st0x_dr))/* clobbered */				      :		"eax");#else				/* SEAGATE_USE_ASM */					while (len) {						unsigned char stat;						stat = STATUS;						if (!(stat & STAT_BSY)						    || ((stat & REQ_MASK) !=							REQ_DATAOUT))							break;						if (stat & STAT_REQ) {							WRITE_DATA (*data++);							--len;						}					}#endif				/* SEAGATE_USE_ASM *//* SJT: End. */				}				if (!len && nobuffs) {					--nobuffs;					++buffer;					len = buffer->length;					data =					    (unsigned char *) buffer->address;					DPRINTK (DEBUG_SG,						 "scsi%d : next scatter-gather buffer len = %d address = %08x\n",						 hostno, len, data);				}				break;			case REQ_DATAIN:#ifdef SLOW_RATE				if (borken) {#if (DEBUG & (PHASE_DATAIN))					transfered += len;#endif					for (;					     len					     && (STATUS & (REQ_MASK | STAT_REQ))

⌨️ 快捷键说明

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