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

📄 seagate.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 3 页
字号:
		hostno, len, data);#endif} else #endif{/* * 	We loop as long as we are in a data out phase, there is data to send,  *	and BSY is still active. */            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;              }            }}			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_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	{#ifdef FAST32	  const unsigned int *iop = phys_to_virt (st0x_dr);	  unsigned int *dp = (unsigned int *) data;	  int xferlen = len >> 2;#else	  const unsigned char *iop = phys_to_virt (st0x_dr);	  unsigned char *dp = data;	  int xferlen = len;#endif	  for (; xferlen; --xferlen)	    *dp++ = *iop;	}	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 */ 	while (len)	  {	    unsigned char stat;	    stat = STATUS;	    if (!(stat & STAT_BSY) || ((stat & REQ_MASK) != REQ_DATAIN))	      break;	    if (stat & STAT_REQ)              {                *data++ = DATA;                --len;              }	  }#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 = *(const unsigned char *) cmnd;					cmnd = 1+(const 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 reconnecting, 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 cancel 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 accommodate 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)	{	  st0x_aborted = DID_ABORT;	  	  return SCSI_ABORT_PENDING;	}/*	the seagate_st0x_reset function resets the SCSI bus*/	int seagate_st0x_reset (Scsi_Cmnd * SCpnt, unsigned int reset_flags)	{	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	return SCSI_RESET_WAKEUP;	}#include <asm/segment.h>#include "sd.h"#include <scsi/scsi_ioctl.h>int seagate_st0x_biosparam(Disk * disk, kdev_t 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;  int capacity;/* * Only SCSI-I CCS drives and later implement the necessary mode sense  * pages.   */  if (disk->device->scsi_level < 2) 	return -1;  sizes = (int *) buf;  data = (unsigned char *) (sizes + 2);  cmd[0] = MODE_SENSE;  cmd[1] = (disk->device->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 transferring 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->device, 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->device, 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 compatible.  The maximum BIOS geometry is 1024 cylinders *  * 256 heads * 64 sectors.  */      if ((cylinders > 1024) || (sectors > 64)) {	/* The Seagate's seem to have some mapping	 * Multiple heads * sectors * cyl to get capacity	 * Then start rounding down. */	capacity = heads * sectors * cylinders;	sectors = 17;	/* Old MFM Drives use this, so does the Seagate */	heads = 2;	capacity = capacity / sectors;	while (cylinders > 1024)	{		heads *= 2;	/* For some reason, they go in multiples */		cylinders = capacity / heads;	}      }      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;}#ifdef MODULE/* Eventually this will go into an include file, but this will be later */Scsi_Host_Template driver_template = SEAGATE_ST0X;#include "scsi_module.c"#endif

⌨️ 快捷键说明

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