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

📄 seagate.c

📁 LINUX1.0内核源代码,学习LINUX编程的一定要看。
💻 C
📖 第 1 页 / 共 3 页
字号:
                                ++buffer;                                len = buffer->length;                                data = (unsigned char *) buffer->address;#if (DEBUG & DEBUG_SG)	printk("scsi%d : next scatter-gather buffer len = %d address = %08x\n",		hostno, len, data);#endif                        }			break;		case REQ_DATAIN : #ifdef SLOW_HANDSHAKE	if (borken) {#if (DEBUG & (PHASE_DATAIN))		transfered += len;#endif		for (; len && (STATUS & (REQ_MASK | STAT_REQ)) == (REQ_DATAIN |			STAT_REQ); --len) {				*data++ = DATA;				borken_wait();}#if (DEBUG & (PHASE_DATAIN))		transfered -= len;#endif	} else#endif#ifdef FASTif (fast && transfersize && !(len % transfersize) && (len >= transfersize)#ifdef FAST32	&& !(transfersize % 4)#endif	) {#if (DEBUG & DEBUG_FAST)         printk("scsi%d : FAST transfer, underflow = %d, transfersize = %d\n"               "         len = %d, data = %08x\n", hostno, SCint->underflow,                SCint->transfersize, len, data);#endif        __asm__("	cld;"#ifdef FAST32"	shr $2, %%ecx;1:	movl (%%esi), %%eax;	stosl;"#else"1:	movb (%%esi), %%al;        stosb;"#endif"	loop 1b;" : :        /* input */        "S" (st0x_dr), "D" (data), "c" (SCint->transfersize) :        /* clobbered */        "eax", "ecx", "edi");	len -= transfersize;	data += transfersize;#if (DEBUG & PHASE_DATAIN)	printk("scsi%d: transfered += %d\n", hostno, transfersize);	transfered += transfersize;#endif#if (DEBUG & DEBUG_FAST)	printk("scsi%d : FAST transfer complete len = %d data = %08x\n", 		hostno, len, data);#endif} else#endif{#if (DEBUG & PHASE_DATAIN)	printk("scsi%d: transfered += %d\n", hostno, len);	transfered += len;	/* Assume we'll transfer it all, then				   subtract what we *didn't* transfer */#endif	/* * 	We loop as long as we are in a data in phase, there is room to read,  * 	and BSY is still active */ 			__asm__ (/*	Local variables : 	ecx = len	edi = data	esi = st0x_cr_sr	ebx = st0x_dr	Test for room to read*/	"\torl %%ecx, %%ecx	jz 2f	cld	movl _st0x_cr_sr, %%esi	movl _st0x_dr, %%ebx1:	movb (%%esi), %%al\n"/*	Test for BSY*/	"\ttest $1, %%al 	jz 2f\n"/*	Test for data in phase - STATUS & REQ_MASK should be REQ_DATAIN, = STAT_IO, which is 4.*/	"\tmovb $0xe, %%ah		andb %%al, %%ah	cmpb $0x04, %%ah	jne 2f\n"		/*	Test for REQ*/		"\ttest $0x10, %%al	jz 1b	movb (%%ebx), %%al		stosb		loop 1b\n""2:\n"									:/* output */"=D" (data), "=c" (len) :/* input */"0" (data), "1" (len) :/* clobbered */"eax","ebx", "esi"); #if (DEBUG & PHASE_DATAIN)	printk("scsi%d: transfered -= %d\n", hostno, len);	transfered -= len;		/* Since we assumed all of Len got 					 * transfered, correct our mistake */#endif}	                        if (!len && nobuffs) {                                --nobuffs;                                ++buffer;                                len = buffer->length;                                data = (unsigned char *) buffer->address;#if (DEBUG & DEBUG_SG)	printk("scsi%d : next scatter-gather buffer len = %d address = %08x\n",		hostno, len, data);#endif                        }			break;		case REQ_CMDOUT : 			while (((status_read = STATUS) & STAT_BSY) && 			       ((status_read & REQ_MASK) == REQ_CMDOUT))				if (status_read & STAT_REQ) {					DATA = *(unsigned char *) cmnd;					cmnd = 1+(unsigned char *) cmnd;#ifdef SLOW_HANDSHAKE					if (borken) 						borken_wait();#endif				}			break;			case REQ_STATIN : 			status = DATA;			break;						case REQ_MSGOUT : /* *	We can only have sent a MSG OUT if we requested to do this  *	by raising ATTN.  So, we must drop ATTN. */			CONTROL = BASE_CMD | CMD_DRVR_ENABLE;/* * 	If we are reconecting, then we must send an IDENTIFY message in  *	 response  to MSGOUT. */			switch (reselect) {			case CAN_RECONNECT:				DATA = IDENTIFY(1, lun);#if (DEBUG & (PHASE_RESELECT | PHASE_MSGOUT)) 				printk("scsi%d : sent IDENTIFY message.\n", hostno);#endif				break;#ifdef LINKED			case LINKED_WRONG:				DATA = ABORT;				linked_connected = 0;				reselect = CAN_RECONNECT;				goto connect_loop;#if (DEBUG & (PHASE_MSGOUT | DEBUG_LINKED))				printk("scsi%d : sent ABORT message to cancle incorrect I_T_L nexus.\n", hostno);#endif#endif /* LINKED */#if (DEBUG & DEBUG_LINKED) 	    printk("correct\n");#endif			default:				DATA = NOP;				printk("scsi%d : target %d requested MSGOUT, sent NOP message.\n", hostno, target);			}			break;							case REQ_MSGIN : 			switch (message = DATA) {			case DISCONNECT :				should_reconnect = 1;                                current_data = data;    /* WDE add */				current_buffer = buffer;                                current_bufflen = len;  /* WDE add */				current_nobuffs = nobuffs;#ifdef LINKED				linked_connected = 0;#endif				done=1;#if (DEBUG & (PHASE_RESELECT | PHASE_MSGIN))				printk("scsi%d : disconnected.\n", hostno);#endif				break;#ifdef LINKED			case LINKED_CMD_COMPLETE:			case LINKED_FLG_CMD_COMPLETE:#endif			case COMMAND_COMPLETE :/* * Note : we should check for underflow here.    */#if (DEBUG & PHASE_MSGIN)					printk("scsi%d : command complete.\n", hostno);#endif				done = 1;				break;			case ABORT :#if (DEBUG & PHASE_MSGIN)				printk("scsi%d : abort message.\n", hostno);#endif				done=1;				break;			case SAVE_POINTERS :				current_buffer = buffer;                                current_bufflen = len;  /* WDE add */				current_data = data;	/* WDE mod */				current_nobuffs = nobuffs;#if (DEBUG & PHASE_MSGIN)				printk("scsi%d : pointers saved.\n", hostno);#endif 				break;			case RESTORE_POINTERS:				buffer=current_buffer;				cmnd=current_cmnd;				data=current_data;	/* WDE mod */				len=current_bufflen;				nobuffs=current_nobuffs;#if (DEBUG & PHASE_MSGIN)				printk("scsi%d : pointers restored.\n", hostno);#endif				break;			default:/* * 	IDENTIFY distinguishes itself from the other messages by setting the *	high byte. * 	 *	Note : we need to handle at least one outstanding command per LUN, *	and need to hash the SCSI command for that I_T_L nexus based on the  *	known ID (at this point) and LUN. */				if (message & 0x80) {#if (DEBUG & PHASE_MSGIN)					printk("scsi%d : IDENTIFY message received from id %d, lun %d.\n",						hostno, target, message & 7);#endif				} else {/* *      We should go into a MESSAGE OUT phase, and send  a MESSAGE_REJECT  * 	if we run into a message that we don't like.  The seagate driver  * 	needs some serious restructuring first though. */#if (DEBUG & PHASE_MSGIN)					printk("scsi%d : unknown message %d from target %d.\n",						hostno,  message,   target);#endif					}			}			break;		default : 			printk("scsi%d : unknown phase.\n", hostno); 			st0x_aborted = DID_ERROR; 		}	#ifdef SLOW_HANDSHAKE/* * I really don't care to deal with borken devices in each single  * byte transfer case (ie, message in, message out, status), so * I'll do the wait here if necessary. */		if (borken)			borken_wait();#endif 		} /* if ends */		} /* while ends */#if (DEBUG & (PHASE_DATAIN | PHASE_DATAOUT | PHASE_EXIT))	printk("scsi%d : Transfered %d bytes\n", hostno, transfered);#endif#if (DEBUG & PHASE_EXIT)#if 0		/* Doesn't work for scatter / gather */	printk("Buffer : \n");	for (i = 0; i < 20; ++i) 		printk ("%02x  ", ((unsigned char *) data)[i]);	/* WDE mod */	printk("\n");#endif	printk("scsi%d : status = ", hostno);        print_status(status);	printk("message = %02x\n", message);#endif/* We shouldn't reach this until *after* BSY has been deasserted */#ifdef notyet	if (st0x_aborted) {		if (STATUS & STAT_BSY) {				seagate_st0x_reset(NULL);			st0x_aborted = DID_RESET;		} 		abort_confirm = 1;	} #endif#ifdef LINKEDelse {/* * Fix the message byte so that unsuspecting high level drivers don't  * puke when they see a LINKED COMMAND message in place of the COMMAND  * COMPLETE they may be expecting.  Shouldn't be necessary, but it's  * better to be on the safe side.  * * A non LINKED* message byte will indicate that the command completed,  * and we are now disconnected. */		switch (message) {		case LINKED_CMD_COMPLETE :		case LINKED_FLG_CMD_COMPLETE : 			message = COMMAND_COMPLETE;			linked_target = current_target;			linked_lun = current_lun;			linked_connected = 1;#if (DEBUG & DEBUG_LINKED)			printk("scsi%d : keeping I_T_L nexus established for linked command.\n", 				hostno);#endif/* * We also will need to adjust status to accomodate intermediate conditions. */			if ((status == INTERMEDIATE_GOOD) ||				(status == INTERMEDIATE_C_GOOD))				status = GOOD;						break;/* * We should also handle what are "normal" termination messages  * here (ABORT, BUS_DEVICE_RESET?, and COMMAND_COMPLETE individually,  * and flake if things aren't right. */		default :#if (DEBUG & DEBUG_LINKED)			printk("scsi%d : closing I_T_L nexus.\n", hostno);#endif			linked_connected = 0;		}	}#endif /* LINKED */	if (should_reconnect) {#if (DEBUG & PHASE_RESELECT)		printk("scsi%d : exiting seagate_st0x_queue_command() with reconnect enabled.\n",			hostno);#endif		CONTROL = BASE_CMD | CMD_INTR ;	} else 		CONTROL = BASE_CMD;	return retcode (st0x_aborted);	}int seagate_st0x_abort (Scsi_Cmnd * SCpnt, int code)	{	if (code)		st0x_aborted = code;	else		st0x_aborted = DID_ABORT;		return 0;	}/*	the seagate_st0x_reset function resets the SCSI bus*/	int seagate_st0x_reset (Scsi_Cmnd * SCpnt)	{	unsigned clock;	/*		No timeouts - this command is going to fail because 		it was reset.	*/#ifdef DEBUG	printk("In seagate_st0x_reset()\n");#endif	/* assert  RESET signal on SCSI bus.  */			CONTROL = BASE_CMD  | CMD_RST;	clock=jiffies+2;		/* Wait.  */		while (jiffies < clock);	CONTROL = BASE_CMD;		st0x_aborted = DID_RESET;#ifdef DEBUG	printk("SCSI bus reset.\n");#endif	if(SCpnt) SCpnt->flags |= NEEDS_JUMPSTART;	return 0;	}#ifdef CONFIG_BLK_DEV_SD#include <asm/segment.h>#include "sd.h"#include "scsi_ioctl.h"int seagate_st0x_biosparam(int size, int dev, int* ip) {  unsigned char buf[256 + sizeof(int) * 2], cmd[6], *data, *page;  int *sizes, result, formatted_sectors, total_sectors;  int cylinders, heads, sectors;  Scsi_Device *disk;  disk = rscsi_disks[MINOR(dev) >> 4].device;/* * Only SCSI-I CCS drives and later implement the necessary mode sense  * pages.   */  if (disk->scsi_level < 2) 	return -1;  sizes = (int *) buf;  data = (unsigned char *) (sizes + 2);  cmd[0] = MODE_SENSE;  cmd[1] = (disk->lun << 5) & 0xe5;  cmd[2] = 0x04; /* Read page 4, rigid disk geometry page current values */  cmd[3] = 0;  cmd[4] = 255;  cmd[5] = 0;/* * We are transfering 0 bytes in the out direction, and expect to get back * 24 bytes for each mode page. */  sizes[0] = 0;  sizes[1] = 256;  memcpy (data, cmd, 6);  if (!(result = kernel_scsi_ioctl (disk, SCSI_IOCTL_SEND_COMMAND, (void *) buf))) {/* * The mode page lies beyond the MODE SENSE header, with length 4, and  * the BLOCK DESCRIPTOR, with length header[3]. */    page = data + 4 + data[3];    heads = (int) page[5];    cylinders = (page[2] << 16) | (page[3] << 8) | page[4];    cmd[2] = 0x03; /* Read page 3, format page current values */    memcpy (data, cmd, 6);    if (!(result = kernel_scsi_ioctl (disk, SCSI_IOCTL_SEND_COMMAND, (void *) buf))) {      page = data + 4 + data[3];      sectors = (page[10] << 8) | page[11];		/* * Get the total number of formatted sectors from the block descriptor,  * so we can tell how many are being used for alternates.   */      formatted_sectors = (data[4 + 1] << 16) | (data[4 + 2] << 8) |	data[4 + 3] ;      total_sectors = (heads * cylinders * sectors);/* * Adjust the real geometry by subtracting  * (spare sectors / (heads * tracks)) cylinders from the number of cylinders. * * It appears that the CE cylinder CAN be a partial cylinder. */     printk("scsi%d : heads = %d cylinders = %d sectors = %d total = %d formatted = %d\n",    hostno, heads, cylinders, sectors, total_sectors, formatted_sectors);      if (!heads || !sectors || !cylinders)	result = -1;      else	cylinders -= ((total_sectors - formatted_sectors) / (heads * sectors));/* * Now, we need to do a sanity check on the geometry to see if it is  * BIOS compatable.  The maximum BIOS geometry is 1024 cylinders *  * 256 heads * 64 sectors.  */      if ((cylinders > 1024) || (sectors > 64)) 	result = -1;      else {	ip[0] = heads;	ip[1] = sectors;	ip[2] = cylinders;      }/*  * There should be an alternate mapping for things the seagate doesn't * understand, but I couldn't say what it is with reasonable certainty. */      }    }      return result;}#endif /* CONFIG_BLK_DEV_SD */#endif	/* defined(CONFIG_SCSI_SEGATE) */

⌨️ 快捷键说明

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