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

📄 scsi_disk.c

📁 ml-rsim 多处理器模拟器 支持类bsd操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Copyright (c) 2002 The Board of Trustees of the University of Illinois and *                    William Marsh Rice University * Copyright (c) 2002 The University of Utah * Copyright (c) 2002 The University of Notre Dame du Lac * * All rights reserved. * * Based on RSIM 1.0, developed by: *   Professor Sarita Adve's RSIM research group *   University of Illinois at Urbana-Champaign and     William Marsh Rice University *   http://www.cs.uiuc.edu/rsim and http://www.ece.rice.edu/~rsim/dist.html * ML-RSIM/URSIM extensions by: *   The Impulse Research Group, University of Utah *   http://www.cs.utah.edu/impulse *   Lambert Schaelicke, University of Utah and University of Notre Dame du Lac *   http://www.cse.nd.edu/~lambert *   Mike Parker, University of Utah *   http://www.cs.utah.edu/~map * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal with the Software without restriction, including without * limitation the rights to use, copy, modify, merge, publish, distribute, * sublicense, and/or sell copies of the Software, and to permit persons to * whom the Software is furnished to do so, subject to the following * conditions: * * 1. Redistributions of source code must retain the above copyright notice, *    this list of conditions and the following disclaimers.  * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimers in the *    documentation and/or other materials provided with the distribution. * 3. Neither the names of Professor Sarita Adve's RSIM research group, *    the University of Illinois at Urbana-Champaign, William Marsh Rice *    University, nor the names of its contributors may be used to endorse *    or promote products derived from this Software without specific prior *    written permission.  * 4. Neither the names of the ML-RSIM project, the URSIM project, the *    Impulse research group, the University of Utah, the University of *    Notre Dame du Lac, nor the names of its contributors may be used to *    endorse or promote products derived from this software without specific *    prior written permission.  * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS WITH THE SOFTWARE.  */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <values.h>#include <math.h>#include "sim_main/simsys.h"#include "sim_main/util.h"#include "sim_main/evlst.h"#include "Processor/simio.h"#include "Caches/system.h"#include "Caches/lqueue.h"#include "IO/scsi_bus.h"#include "IO/scsi_disk.h"#include "IO/pci.h"#ifndef linuxtypedef unsigned char u_int8_t;#endif#include "../../lamix/dev/scsipi/scsipi_all.h"#define min(a, b)               ((a) > (b) ? (b) : (a))void      DISK_request_handler    ();void      DISK_seek_handler       ();void      DISK_sector_handler     ();int       DISK_issue_request      (SCSI_DISK *pdisk, SCSI_REQ* req);void      DISK_wonbus             (void*, SCSI_REQ*);void      DISK_request            (void*, SCSI_REQ*);void      DISK_response           (void*, SCSI_REQ*);void      DISK_perform            (void*, SCSI_REQ*);void      DISK_stat_report        (void*);void      DISK_stat_clear         (void*);void      DISK_dump               (void*);/*=========================================================================*//* Create and configure a SCSI disk module                                 *//* Allocate and initialize a new disk drive control structure. Redirect    *//* configuration file if a separate disk-config file is specified, and     *//* read parameters. Restore original configuration file name. Allocate and *//* initialize queues, cache and persistent storage. Attach to SCSI bus.    *//*=========================================================================*/void SCSI_disk_init(SCSI_BUS *psbus, int dev_id){  SCSI_DISK   *pdisk;  char         seek_method[128];  char         disk_configfile[PATH_MAX];  char        *old_configfile;  extern FILE *pfp;  extern char *configfile;  int          n;  pdisk = (SCSI_DISK*)malloc(sizeof(SCSI_DISK));  if (pdisk == NULL)    YS__errmsg(psbus->node_id, "Malloc failed at %s:%i", __FILE__, __LINE__);  pdisk->dev_id = dev_id;  pdisk->current_cylinder = 0;  pdisk->current_head     = 0;  /*-----------------------------------------------------------------------*/  strcpy(pdisk->name, "IBM/Ultrastar_9LP");  pdisk->seek_single          =  0.7;  pdisk->seek_avg             =  6.5;  pdisk->seek_full            = 14.0;  pdisk->seek_method          = DISK_SEEK_CURVE;  pdisk->write_settle         = 1.3;  pdisk->head_switch          = 0.85;  pdisk->cntl_overhead        = 40;  pdisk->rpm                  = 7200;  pdisk->cylinders            = 8420;  pdisk->heads                = 10;  pdisk->sectors              = 209;  pdisk->cylinder_skew        = 20;  pdisk->track_skew           = 35;  pdisk->request_queue_size   = 32;  pdisk->response_queue_size  = 32;  pdisk->cache_size           = 1024;  pdisk->cache_segments       = 16;  pdisk->cache_write_segments = 2;  pdisk->prefetch             = 1;  pdisk->fast_writes          = 0;  pdisk->buffer_full_ratio    = 0.75;  pdisk->buffer_empty_ratio   = 0.75;  pdisk->ticks_per_ms         = 1000000000 / CPU_CLK_PERIOD;  /*-----------------------------------------------------------------------*/  pdisk->scsi_me = SCSI_device_init(psbus, dev_id, pdisk,				    DISK_wonbus,				    DISK_request,				    DISK_response,				    DISK_perform,				    DISK_stat_report,				    DISK_stat_clear,				    DISK_dump);  /*-----------------------------------------------------------------------*/  strcpy(disk_configfile, "");  get_parameter("DISK_params", disk_configfile, PARAM_STRING);  if (strlen(disk_configfile) > 0)    {      fclose(pfp);      pfp = NULL;      old_configfile = configfile;      configfile = disk_configfile;    }  get_parameter("DISK_name",         &(pdisk->name),           PARAM_STRING);  get_parameter("DISK_seek_single",  &(pdisk->seek_single),    PARAM_DOUBLE);  get_parameter("DISK_seek_av",      &(pdisk->seek_avg),       PARAM_DOUBLE);  get_parameter("DISK_seek_full",    &(pdisk->seek_full),      PARAM_DOUBLE);  strcpy(seek_method, "");  get_parameter("DISK_seek_method",  seek_method,              PARAM_STRING);  if (strncasecmp("DISK_SEEK_NONE",  seek_method, 14) == 0)    pdisk->seek_method = DISK_SEEK_NONE;  if (strncasecmp("DISK_SEEK_CONST", seek_method, 15) == 0)    pdisk->seek_method = DISK_SEEK_CONST;  if (strncasecmp("DISK_SEEK_LINE",  seek_method, 14) == 0)    pdisk->seek_method = DISK_SEEK_LINE;  if (strncasecmp("DISK_SEEK_CURVE", seek_method, 15) == 0)    pdisk->seek_method = DISK_SEEK_CURVE;  get_parameter("DISK_write_settle",  &(pdisk->write_settle),  PARAM_DOUBLE);  get_parameter("DISK_head_switch",   &(pdisk->head_switch),   PARAM_DOUBLE);  get_parameter("DISK_cntl_ov",       &(pdisk->cntl_overhead), PARAM_DOUBLE);  get_parameter("DISK_rpm",           &(pdisk->rpm),           PARAM_INT);  get_parameter("DISK_cyl",           &(pdisk->cylinders),     PARAM_INT);  get_parameter("DISK_heads",         &(pdisk->heads),         PARAM_INT);  get_parameter("DISK_sect",          &(pdisk->sectors),       PARAM_INT);  get_parameter("DISK_cylinder_skew", &(pdisk->cylinder_skew), PARAM_INT);  get_parameter("DISK_track_skew",    &(pdisk->track_skew),    PARAM_INT);  get_parameter("DISK_request_q",   &(pdisk->request_queue_size), PARAM_INT);  get_parameter("DISK_response_q",  &(pdisk->response_queue_size),PARAM_INT);  get_parameter("DISK_cache_size",  &(pdisk->cache_size),         PARAM_INT);  get_parameter("DISK_cache_seg",   &(pdisk->cache_segments),     PARAM_INT);  get_parameter("DISK_cache_write_seg", &(pdisk->cache_write_segments), PARAM_INT);  get_parameter("DISK_prefetch"  ,  &(pdisk->prefetch)   ,        PARAM_INT);  get_parameter("DISK_fast_write",  &(pdisk->fast_writes),        PARAM_INT);  get_parameter("DISK_buffer_full", &(pdisk->buffer_full_ratio),		PARAM_DOUBLE);  get_parameter("DISK_buffer_empty",&(pdisk->buffer_empty_ratio),		PARAM_DOUBLE);  if (pdisk->cache_size != ToPowerOf2(pdisk->cache_size))    YS__errmsg(psbus->node_id,	       "DISK: Size of disk cache must be power of two");  if (pdisk->cache_segments != ToPowerOf2(pdisk->cache_segments))    YS__errmsg(psbus->node_id,	       "DISK: Number of disksegments must be power of two");  if (strlen(disk_configfile) > 0)    {      fclose(pfp);      pfp = NULL;      configfile = old_configfile;    }  /*-----------------------------------------------------------------------*/  lqueue_init(&(pdisk->inqueue), pdisk->request_queue_size);  lqueue_init(&(pdisk->outqueue), pdisk->response_queue_size);  pdisk->state        = DISK_IDLE;  pdisk->current_req  = NULL;  pdisk->start_offset =    (pdisk->scsi_me->scsi_bus->node_id * SCSI_WIDTH * 8 * PCI_MAX_DEVICES) +    (pdisk->scsi_me->scsi_bus->bus_id * SCSI_WIDTH * 8) +    pdisk->scsi_me->dev_id;  pdisk->start_offset %= pdisk->sectors;  pdisk->request_event = NewEvent("Disk Request",				  DISK_request_handler, NODELETE, 0);  EventSetArg(pdisk->request_event, (char*)pdisk, sizeof(pdisk));  pdisk->seek_event = NewEvent("Disk Sector Reached",			       DISK_seek_handler, NODELETE, 0);  EventSetArg(pdisk->seek_event, (char*)pdisk, sizeof(pdisk));  pdisk->sector_event = NewEvent("Disk Sector Transferred",				 DISK_sector_handler, NODELETE, 0);  EventSetArg(pdisk->sector_event, (char*)pdisk, sizeof(pdisk));  DISK_storage_init(pdisk);    DISK_cache_init(pdisk);  DISK_stat_clear(pdisk);  /*-----------------------------------------------------------------------*/  /* initialize inquiry data command return structure                      */  memset(&pdisk->inquiry_data, 0, sizeof(pdisk->inquiry_data));  pdisk->inquiry_data.type                 = SCSI_DEVICE_DISK;  pdisk->inquiry_data.qualifier            = 0;  pdisk->inquiry_data.version              = 2;  pdisk->inquiry_data.response_format      = 0;  pdisk->inquiry_data.additional_length    = sizeof(SCSI_INQUIRY_DATA) - 4;  pdisk->inquiry_data.flags                =    SID_CmdQue | SID_Linked | SID_WBus16 | SID_WBus32;  n = strcspn(pdisk->name, "/");  if ((n > sizeof(pdisk->inquiry_data.vendor) - 1) || (n == 0))    strcpy(pdisk->inquiry_data.vendor, "Unknown");  else    strncpy(pdisk->inquiry_data.vendor, pdisk->name, n);  n += strspn(pdisk->name + n, "/");  strncpy(pdisk->inquiry_data.product, pdisk->name + n,	  min(sizeof(pdisk->inquiry_data.product) - 1,	      strlen(pdisk->name + n)));  strcpy(pdisk->inquiry_data.revision, "1.0");  /*-----------------------------------------------------------------------*/  /* initialize mode sense command return structure                        */    memset(&pdisk->mode_sense_data, 0, sizeof(pdisk->mode_sense_data));  pdisk->mode_sense_data.data_length     = sizeof(pdisk->mode_sense_data) - 1;  pdisk->mode_sense_data.medium_type     = 0;  pdisk->mode_sense_data.blk_desc_length = 8;  pdisk->mode_sense_data.density         = 0;  n = pdisk->cylinders * pdisk->heads * pdisk->sectors;  pdisk->mode_sense_data.nblocks[0]      = (n >> 16) & 0xFF;  pdisk->mode_sense_data.nblocks[1]      = (n >> 8) & 0xFF;  pdisk->mode_sense_data.nblocks[2]      = n & 0xFF;  pdisk->mode_sense_data.blklen[0]       = (SCSI_BLOCK_SIZE >> 16) & 0xFF;  pdisk->mode_sense_data.blklen[1]       = (SCSI_BLOCK_SIZE >> 8) & 0xFF;  pdisk->mode_sense_data.blklen[2]       = SCSI_BLOCK_SIZE & 0xFF;  pdisk->mode_sense_data.page_code       = 4;  pdisk->mode_sense_data.page_length     = 22;    pdisk->mode_sense_data.disk_pages.rigid_geometry.ncyl[0] =    (pdisk->cylinders >> 16) & 0xFF;  pdisk->mode_sense_data.disk_pages.rigid_geometry.ncyl[1] =    (pdisk->cylinders >> 8) & 0xFF;  pdisk->mode_sense_data.disk_pages.rigid_geometry.ncyl[2] =    pdisk->cylinders & 0xFF;  pdisk->mode_sense_data.disk_pages.rigid_geometry.nheads = pdisk->heads;  pdisk->mode_sense_data.disk_pages.rigid_geometry.rpm[0] =    (pdisk->rpm >> 8) & 0xFF;  pdisk->mode_sense_data.disk_pages.rigid_geometry.rpm[1] =    pdisk->rpm & 0xFF;  /*-----------------------------------------------------------------------*/  /* allocate sense data return structure array - one per initiator        */  pdisk->sense_data = (SCSI_EXT_SENSE_DATA*)malloc(sizeof(SCSI_EXT_SENSE_DATA) * SCSI_WIDTH * 8);}/*=========================================================================*//* Event handler for incoming requests: takes requests off the input       *//* queue, checks for cache hits, attaches a cache segment to the request   *//* and starts a seek operation if necessary.                               *//* Event is scheduled by 'disk_request' when a new request enters an empty *//* qeueue and the disk is idle, by itself when a request is completed, by  *//* the seek event handler when a seek request is completed or by the       *//* sector event all sectors are transferred.                               *//*=========================================================================*/void DISK_request_handler(){  SCSI_DISK *pdisk = (SCSI_DISK*)EventGetArg(NULL);  SCSI_REQ  *req;  int        start_block;  int        length, segment;  int        hit_type;  /*=======================================================================*/  /* if queue is empty and fast writes are pending create a write request  */  start_block = 0;  length  = MAXINT;  segment = DISK_cache_getwsegment(pdisk, &start_block, &length);  if (!lqueue_empty(&pdisk->inqueue))    req = lqueue_head(&pdisk->inqueue);  if ((pdisk->fast_writes) &&      (pdisk->current_req == NULL) &&      (segment >= 0) &&      ((lqueue_empty(&pdisk->inqueue)) ||       ((!lqueue_empty(&pdisk->inqueue)) &&	(req->orig_request == SCSI_REQ_WRITE) &&	(req->transferred == 0))))    {#ifdef SCSI_DISK_TRACE      YS__logmsg(pdisk->scsi_me->scsi_bus->node_id,		 "[%i:%i] %0.f: Start Cache Writeback Segment %i\n",		 pdisk->scsi_me->scsi_bus->bus_id+1,		 pdisk->scsi_me->dev_id,		 YS__Simtime, segment);#endif      req = (SCSI_REQ*)YS__PoolGetObj(&YS__ScsiReqPool);      req->orig_request   = SCSI_REQ_WRITE;      req->start_block    = start_block;      req->length         = length;      req->current_length = 0;      req->transferred    = length;      req->cache_segment  = segment;      req->imm_flag       = SCSI_FLAG_TRUE;      req->buscycles      = 0;      pdisk->current_req  = req;    }  /*=======================================================================*/  /* no current request (could be write-back or prefetch)                  */  /* get new request from queue                                            */

⌨️ 快捷键说明

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