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

📄 scsi_disk.c

📁 ml-rsim 多处理器模拟器 支持类bsd操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
      pdisk->current_req  = NULL;      if (IsNotScheduled(pdisk->request_event))	schedule_event(pdisk->request_event, YS__Simtime);    }    /* schedule sector event for other requests -----------------------------*/  else    {      pdisk->state = DISK_TRANSFER;      if (IsNotScheduled(pdisk->request_event))	schedule_event(pdisk->sector_event,		       YS__Simtime +		       rint(DISK_rotation_time(pdisk, 1)*pdisk->ticks_per_ms));    }}/*=========================================================================*//* sector event handler: complete sector has been transferred.             *//* Insert data into cache for reads, get new segment unless it is a        *//* prefetch. Make segment clean if all data has been written, get new      *//* write segment. Schedule new sector or seek event if more data needs to  *//* be transferred, or request-event if current request is completed.       *//*=========================================================================*/void DISK_sector_handler(){  SCSI_DISK *pdisk = (SCSI_DISK*)EventGetArg(NULL);  SCSI_REQ  *req = pdisk->current_req, *sreq;  int        start_block, next_cylinder, next_head, length;  if (req == NULL)    return;    req->current_length++;    pdisk->transfer_time += DISK_rotation_time(pdisk, 1);    /*=======================================================================*/  /* Handle reads and prefetches (both requested and triggered by a read)  */    if ((req->orig_request == SCSI_REQ_READ) ||      (req->orig_request == SCSI_REQ_PREFETCH))    {#ifdef SCSI_DISK_TRACE      YS__logmsg(pdisk->scsi_me->scsi_bus->node_id,		 "[%i:%i] Read %.1f  Sector %i  Segment %i\n",		 pdisk->scsi_me->scsi_bus->bus_id+1,		 pdisk->scsi_me->dev_id,		 YS__Simtime,		 req->start_block + req->current_length - 1,		 req->cache_segment);#endif      pdisk->blocks_read_media++;            /* insert sector in cache -------------------------------------------*/      DISK_cache_insert(pdisk, req->start_block + req->current_length - 1,			1, req->cache_segment);            /* read-induced prefetch reaches end of segment - abort -------------*/      if ((DISK_cache_segment_full(pdisk, req->cache_segment) ||	   (!lqueue_empty(&(pdisk->inqueue)))) &&	  (req->orig_request == SCSI_REQ_PREFETCH) &&	  (req->request_type == SCSI_REQ_READ))	{#ifdef SCSI_DISK_TRACE	  YS__logmsg(pdisk->scsi_me->scsi_bus->node_id,		     "[%i:%i]  Abort Prefetch\n",		     pdisk->scsi_me->scsi_bus->bus_id+1,		     pdisk->scsi_me->dev_id);#endif	  	  pdisk->state = DISK_IDLE;	  pdisk->current_req = NULL;	  YS__PoolReturnObj(&YS__ScsiReqPool, req);	  	  if (IsNotScheduled(pdisk->request_event))	    schedule_event(pdisk->request_event, YS__Simtime);	  return;	}            /* requested prefetch or read fills up segment - get new segment ----*/      if ((DISK_cache_segment_full(pdisk, req->cache_segment)) &&	  (req->current_length < req->length))	{#ifdef SCSI_DISK_TRACE	  YS__logmsg(pdisk->scsi_me->scsi_bus->node_id,		     "[%i:%i] Segment full\n",		     pdisk->scsi_me->scsi_bus->bus_id+1,		     pdisk->scsi_me->dev_id);#endif          req->cache_segment =	    DISK_cache_getsegment(pdisk,				  req->start_block + req->current_length,				  req->length - req->current_length - 1, 0);	}            /* return data if threshold reached ---------------------------------*/      if (((double)(req->current_length - req->transferred) >=	   (double)(req->length-req->transferred)*pdisk->buffer_full_ratio) &&	  (req->length - req->transferred > 0) &&	  (req->orig_request == SCSI_REQ_READ))	{#ifdef SCSI_DISK_TRACE	  YS__logmsg(pdisk->scsi_me->scsi_bus->node_id,		     "[%i:%i]  Return Data %f > %f ?",		     pdisk->scsi_me->scsi_bus->bus_id+1,		     pdisk->scsi_me->dev_id,		     DISK_estimate_access_time(pdisk,					       req->start_block+req->current_length,					       req->length - req->current_length),		     (double)((req->length - req->transferred) * SCSI_BLOCK_SIZE) / (double)(SCSI_WIDTH * SCSI_FREQUENCY * 1000.0));#endif	  if (DISK_estimate_access_time(pdisk,					req->start_block + req->current_length,					req->length - req->current_length) <	      (double)((req->length - req->transferred) * SCSI_BLOCK_SIZE) /	      (double)(SCSI_WIDTH * SCSI_FREQUENCY * 1000.0))	    {	      req->request_type  = SCSI_REQ_RECONNECT;	      req->reply_type    = SCSI_REP_COMPLETE;	      req->buscycles     = (req->length - req->transferred) *		SCSI_BLOCK_SIZE / SCSI_WIDTH;	      req->current_data_size = req->buscycles * SCSI_WIDTH;	      req->transferred   = req->length;	      DISK_issue_request(pdisk, req);#ifdef SCSI_DISK_TRACE	      YS__logmsg(pdisk->scsi_me->scsi_bus->node_id,			 " %s (%i)\n",			 SCSI_RepName[req->reply_type], req->buscycles);#endif	    }	  else	    {	      sreq = (SCSI_REQ*)YS__PoolGetObj(&YS__ScsiReqPool);	      memcpy(sreq, req, sizeof(SCSI_REQ));	      sreq->request_type      = SCSI_REQ_RECONNECT;	      sreq->reply_type        = SCSI_REP_SAVE_DATA_POINTER;	      sreq->buscycles         =		(req->current_length - req->transferred) *		SCSI_BLOCK_SIZE / SCSI_WIDTH;	      sreq->current_data_size = sreq->buscycles * SCSI_WIDTH;	      sreq->parent            = req;	      DISK_issue_request(pdisk, sreq);	      req->transferred       = req->current_length;#ifdef SCSI_DISK_TRACE	      YS__logmsg(pdisk->scsi_me->scsi_bus->node_id,			 " %s (%i)\n",			 SCSI_RepName[sreq->reply_type], sreq->buscycles);#endif	    }	}    }    /*=======================================================================*/  /* handle write request: mark segment as clean if completely written     */  if (req->orig_request == SCSI_REQ_WRITE)    {#ifdef SCSI_DISK_TRACE      YS__logmsg(pdisk->scsi_me->scsi_bus->node_id,		 "[%i:%i] Wrote %.1f  Sector %i  Segment %i\n",		 pdisk->scsi_me->scsi_bus->bus_id+1,		 pdisk->scsi_me->dev_id,		 YS__Simtime,		 req->start_block + req->current_length - 1,		 req->cache_segment);#endif      pdisk->blocks_written_media++;      /*-------------------------------------------------------------------*/      /* segment completely written: mark as clean                         */      if ((req->current_length % ((pdisk->cache_size * 1024) /	   (pdisk->cache_segments * SCSI_BLOCK_SIZE)) == 0) ||	  (req->current_length == req->length))	{	  DISK_cache_complete_write(pdisk, req->cache_segment);	  /*---------------------------------------------------------------*/	  /* need to get more data from initiator                          */	  if (req->transferred < req->length)	    {	      SCSI_REQ *sreq;	      	      length = DISK_cache_write(pdisk,					req->start_block + req->transferred,					req->length - req->transferred);#ifdef SCSI_DISK_TRACE	      YS__logmsg(pdisk->scsi_me->scsi_bus->node_id,			 "[%i:%i]  Get More Data %i %i %i %i\n",			 pdisk->scsi_me->scsi_bus->bus_id+1,			 pdisk->scsi_me->dev_id,			 req->length,			 req->current_length,			 req->start_block + req->transferred,			 length);#endif	      	      DISK_cache_commit_write(pdisk,				      req->start_block + req->transferred,				      req->length - req->transferred);	      req->buscycles         = length * SCSI_BLOCK_SIZE / SCSI_WIDTH;	      req->current_data_size = req->buscycles * SCSI_WIDTH;	      req->transferred      += length;	      req->request_type      = SCSI_REQ_RECONNECT;	      if (req->transferred < req->length)		req->reply_type      = SCSI_REP_SAVE_DATA_POINTER;	      else		req->reply_type      = SCSI_REP_COMPLETE;	      sreq = (SCSI_REQ*)YS__PoolGetObj(&YS__ScsiReqPool);	      memcpy(sreq, req, sizeof(SCSI_REQ));	      DISK_issue_request(pdisk, sreq);	    }	  if ((pdisk->fast_writes) && (req->imm_flag) && (req->request_type != SCSI_REQ_RECONNECT))	    {	      req->start_block = 0;	      req->length = MAXINT;	      req->cache_segment =		DISK_cache_getwsegment(pdisk,				       &(req->start_block),				       &(req->length));#ifdef SCSI_DISK_TRACE	      YS__logmsg(pdisk->scsi_me->scsi_bus->node_id,			 "[%i:%i]   New Segment Fast %i\n",			 pdisk->scsi_me->scsi_bus->bus_id+1,			 pdisk->scsi_me->dev_id,			 req->cache_segment);#endif	      if (req->cache_segment < 0)		{		  pdisk->state = DISK_IDLE;		  pdisk->current_req = NULL;		  YS__PoolReturnObj(&YS__ScsiReqPool, req);		  if (IsNotScheduled(pdisk->request_event))		    schedule_event(pdisk->request_event, YS__Simtime);		  return;		}	      req->current_length = 0;	      req->transferred = req->length;	      req->lba = req->start_block;	    }	  else if (req->current_length < req->length)	    {	      req->cache_segment =		DISK_cache_getsegment(pdisk, 				      req->start_block + req->current_length,				      1, 1);#ifdef SCSI_DISK_TRACE	      YS__logmsg(pdisk->scsi_me->scsi_bus->node_id,			 "[%i:%i]   New Segment %i %i -> %i\n",			 pdisk->scsi_me->scsi_bus->bus_id+1,			 pdisk->scsi_me->dev_id,			 req->start_block + req->current_length,			 req->length - req->current_length,			 req->cache_segment);#endif	    }	}    }      /*=======================================================================*/  /* handle sync request: mark segment as clean if completely written      */  if (req->orig_request == SCSI_REQ_SYNC_CACHE)    {#ifdef SCSI_DISK_TRACE      YS__logmsg(pdisk->scsi_me->scsi_bus->node_id,		 "[%i:%i] Synced %.1f  Sector %i  Segment %i\n",		 pdisk->scsi_me->scsi_bus->bus_id+1,		 pdisk->scsi_me->dev_id,		 YS__Simtime,		 req->start_block + req->current_length - 1,		 req->cache_segment);#endif      pdisk->blocks_written_media++;      if (req->current_length == req->length)	{	  DISK_cache_complete_write(pdisk, req->cache_segment);	  req->start_block = 0;                   /* not exactly correct @@@ */	  req->length = MAXINT;	  req->cache_segment = DISK_cache_getwsegment(pdisk,						      &(req->start_block),						      &(req->length));	  req->current_length = 0;	  if (req->cache_segment < 0)	    {	      if (!req->imm_flag)		{		  req->request_type      = SCSI_REQ_RECONNECT;		  req->reply_type        = SCSI_REP_COMPLETE;		  req->buscycles         = 0;		  req->current_data_size = 0;		  DISK_issue_request(pdisk, req);		}	      else		YS__PoolReturnObj(&YS__ScsiReqPool, req);	      pdisk->current_req = NULL;	      pdisk->state       = DISK_IDLE;	      if (IsNotScheduled(pdisk->request_event))		schedule_event(pdisk->request_event,			       YS__Simtime+pdisk->cntl_overhead*SCSI_FREQ_RATIO);	      return;	    }	}    }	      /*=======================================================================*/  /* transfer next sector: wait for rotation if on same track, or seek     */  if (req->current_length < req->length)    {      next_cylinder = DISK_sector_to_cylinder(pdisk, req->start_block +					      req->current_length);      next_head     = DISK_sector_to_head(pdisk, req->start_block +					  req->current_length);      if ((next_cylinder == pdisk->current_cylinder) &&	  (next_head == pdisk->current_head) &&	  ((req->start_block + req->current_length ==	    DISK_sector_at_time(pdisk, next_head,				next_cylinder, YS__Simtime)) ||	   (req->start_block + req->current_length + 1 ==	    DISK_sector_at_time(pdisk, next_head,				next_cylinder, YS__Simtime))))	   	{	  if (IsNotScheduled(pdisk->sector_event))	    schedule_event(pdisk->sector_event,			   YS__Simtime +			   floor(DISK_rotation_time(pdisk, 1) *				 pdisk->ticks_per_ms));	  pdisk->seek_target_sector = req->start_block + req->current_length;	  #ifdef SCSI_DISK_TRACE	  YS__logmsg(pdisk->scsi_me->scsi_bus->node_id,		     "[%i:%i]  More Transfer %i %i (estimated %f ms %f) -> %.0f\n",

⌨️ 快捷键说明

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