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

📄 hd.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (C) 1996-1998 by the Board of Trustees *    of Leland Stanford Junior University. *  * This file is part of the SimOS distribution.  * See LICENSE file for terms of the license.  * *//***************************************************************** * simhd.c * * Simple SCSI disk device emulation. Emulates a number of * independent disks. Correctly models disk latencies and * DMA transfers, but does not model disk controller contention * (in fact, there is no real notion of a disk controller in * this model). * *   This model has evolved from a very simple hard disk driver that worked *   with the IRIX "sable" disk driver to someone that can act as a simple *   SCSI disk simulator as well as a disk driver. * *   Data handling now supported. The DMA uses in all cases *   an intermediate buffer for the scatter/gather * * Created by: ?? * Revised by: *   Dan Teodosiu, 07/96  Cleaned up code, changed buffering scheme. *   Dan Teodosiu, 05/97  Multiple controllers / node. * ****************************************************************/#include <stdio.h>#include <stdlib.h> /* For the use of calloc() */#include <string.h>#include <sys/types.h>#ifndef __alpha#ifndef i386#include <sys/unistd.h>#endif#endif#include <sys/mman.h>#include <sys/file.h>#include <sys/stat.h>#include <sys/signal.h>#ifndef __alpha#ifndef i386#include <sys/ioccom.h>#include <sys/filio.h>#endif#endif#include <sys/time.h>#include <sys/errno.h>#include <errno.h>#include <unistd.h>#include <assert.h>/* #include <poll.h> */#include "sim.h"#include "syslimits.h"#include "simtypes.h"#include "hd.h"#include "checkpoint.h"#include "machine_params.h"#include "cpu_interface.h"#include "sim_error.h"#include "dma.h"#include "../disk/simos_interface.h"#include "remote_access.h"#include "rmtaccess.h"#include "simutil.h"#include "arch_specifics.h"/* * SCSI commands. * * Not all of these are supported in this device. Currently, only * the commands used by IRIX are implemented. */#define CMD_TST_UNIT_RDY	0x0#define CMD_REQ_SENSE		0x3#define CMD_FORMAT		0x4#define CMD_ADD_DEFECTS		0x7#define CMD_READ_6              0x8#define CMD_WRITE_6             0xa#define CMD_INQUIRY		0x12#define CMD_MODE_SELECT		0x15#define CMD_MODE_SENSE		0x1a#define CMD_STARTUNIT		0x1b#define CMD_SEND_DIAG		0x1d#define CMD_PREVREM		0x1e#define CMD_READCAPACITY	0x25#define CMD_READ		0x28#define CMD_WRITE		0x2a#define CMD_SEEK		0x2b#define CMD_ERASE		0x2c#define CMD_RDEFECTS		0x37#define CMD_NONE                0xff /* Flag meaning no SCSI command */static char *scsiOpcode[256] = {   "testUnitRdy", NULL, NULL, "reqSense", "format", NULL, NULL, "addDefects",    "read6", NULL, "write6", NULL, NULL, NULL, NULL, NULL,   NULL, NULL, "inquiry", NULL, NULL, "modeSelect", NULL, NULL,    NULL, NULL, "modeSense", "startunit", NULL, "sendDiag", "prevrem", NULL,   NULL, NULL, NULL, NULL, NULL, "readcapacity", NULL, NULL,    "read", NULL, "write", "seek", "erase", NULL, NULL, NULL,    NULL, NULL, NULL, NULL, NULL, NULL, NULL, "rdefects"};/* Taken from /usr/include/sys/dksc.h *//* The data structure of the mode sense command */struct mode_sense_data {   u_char  sense_len;   u_char  mediatype;   u_char  wprot:1, reserv0:2, dpofua:1, reserv1:4;   u_char  bd_len;   u_char  block_descrip[8];    /* Don't need this:    union   dk_pages dk_pages; */};/* from io/cam/scsi_all.h */typedef struct all_inq_data {	u_char	dtype	: 5,	/* Peripheral device type.	[0] */		pqual	: 3;	/* Peripheral qualifier.	    */	u_char	dmodify	: 7,	/* Device type modifier.	[1] */		rmb	: 1;	/* Removable media.		    */	u_char	ansi	: 3,	/* ANSI version.		[2] */		ecma	: 3,	/* ECMA version.		    */		iso	: 2;	/* ISO version.			    */	u_char	rdf	: 4,	/* Response data format.	[3] */			: 2,	/* Reserved.			    */		trmiop	: 1,	/* Terminate I/O process	    */		aenc	: 1;	/* Async Notification of events	    */	u_char	addlen;		/* Additional length.		[4] */	u_char		: 8;	/* Reserved.			[5] */	u_char		: 8;	/* Reserved.			[6] */	u_char	sftre	: 1,	/* Soft reset 1 = yes		[7] */		cmdque	: 1,	/* Command queuing		    */			: 1,	/* Reserved bit				*/		linked	: 1,	/* Linked command support	    */		sync	: 1,	/* Synchronous data transfers	    */		wbus16	: 1, 	/* support of 16 bit transfers	    */		wbus32	: 1,	/* support of 32 bit transfers	    */		reladdr : 1;	/* Relative addressing support	    */	u_char	vid[8];		/* Vendor ID.		     [8-15] */	u_char	pid[16];	/* Product ID.		    [16-31] */	u_char	revlevel[4];	/* Revision level.	    [32-35] */} ALL_INQ_DATA;typedef struct dir_read_cap_data {	u_char	lbn3;		/* MSB of number of logical blocks	*/	u_char	lbn2;		/* MID HIGH of number of logical blocks	*/	u_char	lbn1;		/* MID LOW of number of logical blocks	*/	u_char	lbn0;		/* LSB of number of logical blocks	*/	u_char	block_len3;	/* MSB of block length in bytes		*/	u_char	block_len2;	/* MID HIGH of block length in bytes	*/	u_char	block_len1;	/* MID LOW of block length in bytes	*/	u_char	block_len0;	/* MSB of block length in bytes		*/}DIR_READ_CAP_DATA;/* Defined these for magic disk and/or magic disk sector * * #define MAGIC_CTRL * #define MAGIC_UNIT * #define MAGIC_DISK_SECTOR * */extern int inCellMode;/****************** This section is checkpoint stuff ****************/typedef struct Sector {  char           data[SectorSize];  struct Sector* next;} Sector;typedef struct{  /* Stuff from this point on are stats for the "disk" file */   char filename[128];     /* Name of hd file checkpoint is based on */  char diskname[128];     /* DISK<node>.<ctrl>.<unit> */  off_t fileSize;         /* For consistency check of the hd file */  time_t modifyTime;	  /* the checkpoint is based on		  */  bool writeable;	  /* Record whether disk is read-write */    bool doCheckSum;	  /* Boolean flag if checksum is done */  int checkSum;           /* This is not used currently */    int modifyMapSize;      /* This is the bitmap used to mark the modified */     char *modifyMap;        /* sectors in the mmapped image of the hd file  */  Sector *modifiedSectors;/* To store changes for checkpoint restore */  int dfd;                /* Actual diskfile */  int sfd;                /* Shadow file for changes to COW disk */  int *shadowOffset;      /* Offset array into shadow file */  unsigned long nextWriteOffset; /* offset to write to in shadow file */} SimhdSaveInfo;typedef struct {  int 		accessed;      /* This is int in case we have > 8 hd's */  SimhdSaveInfo simhdStats;} HdcptData;/****************** End section for checkpoint stuff ****************/typedef struct Device {  unsigned char cmd[SIM_DISK_CMD_SIZE]; /* SCSI command */  int   isRead;               /* TRUE if read request, FALSE if write. */  int64   sizeInSectors;	      /* transfer size in sectors. */  int64   sectorNum;            /* disk address (sector number) */  int   done;                 /* 0 => no transfer in progress			       * 1 => disk transfer pending			       */    int	bytesTransferred;     /* Return value from operation. */  int   errnoVal;    PA    pAddr[SIM_DISK_MAX_DMA_LENGTH];  int   offset;               /* offset for first page */  int   isReady;              /* TRUE if the disk is ready. */   int   inuse;  int   dmodel_no;            /* disk model disk # for this disk */  /* The following is shared data used for checkpointing */  HdcptData hdcpt;  /* Data handling */  struct {     int   diskOwner;    int   intrCpu;    int   execCpu;    byte  dataBuffer[SectorSize]; /* buffer for (real) I/O */    byte *currPtr;                /* ptr to NEXT position in buffer */    int64   currSector;             /* keeps track of current sec on disk */  } c;  DMARequest dmaReq;          /* DMA request area */} Device;static Device**** dks;           /* disk data structures [node][ctrl][unit] */static int        nnode;         /* number of nodes */static int*       nctrl;         /* number of disks controllers[node] */static int**      nunit;         /* number of disk units[node][controller] */static void     (*int_f)(int node,int ctrl,int unit,int on); /* int fct */static int        dmodel_next;   /* next free disk model disk number */static int***     inFixedLatency;/* */static int        performingSimpleIO = 0;#define DKS(_NODE,_CTRL,_UNIT)          \                         (*dks[_NODE][_CTRL][_UNIT])#define DKS_filename(_NODE,_CTRL,_UNIT) \                         (dks[_NODE][_CTRL][_UNIT]->hdcpt.simhdStats.filename)#define DKS_diskname(_NODE,_CTRL,_UNIT) \                         (dks[_NODE][_CTRL][_UNIT]->hdcpt.simhdStats.diskname)extern char *DevFileDir;extern char *MemFileDir;static int SimhdFindSector(int node, int ctrl, int unit, int64 sectorNum,			   int *fd, unsigned long *offset, int isRead);static int SimhdSetupModifyMap(int node, int ctrl, int unit);static void  DMATransfer ( int len, SimTime finishTime,                          void (*done)(int), int encoded_ctrl_unit);static void DiskDoneRoutine(int encoded_ctrl_unit);static void FixedLatencyDisk(int encoded_ctrl_unit);static void SimhdInitDisks(int restoreFromChkpt);static void SimhdDoCmd(int node, int ctrl, int unit);static void DoScsiCmd(int node, int ctrl, int unit);static int  DiskCheckpointCB(CptDescriptor *cptd);static long DetermineDeviceSize(int fd);/*****************************************************************//* Trace for debugging *//* #define DEBUG_HD */#define DEBUG_DMA#ifdef DEBUG_HDstatic char errbuf[32];static void Sim_Warning_NOCR(char *fmt, ...){     va_list args;     va_start(args, fmt);     vsprintf(errbuf, fmt, args);     write(1, errbuf, strlen(errbuf));} static int dotrace = 1;#define DTRACE(c,node,ctrl,unit) \    if (dotrace) {Sim_Warning_NOCR("<%c%d.%d.%d>", c, node,ctrl,unit);}#else#define DTRACE(c,node,ctrl,unit)#endif/*****************************************************************/int  rmtdiskfd = -1;voidsim_disk_init(int nodes, int uc,	      void (*int_fun)(int node, int ctrl, int unit, int on),	      int restoreFromChkpt){   int  n, c;      char name[32];   nnode = nodes;   /* allocate storage for disk shadow data structures */   dks            = (Device****) ZMALLOC(nnode*sizeof(Device***), "dks");   inFixedLatency = (int***)     ZMALLOC(nnode*sizeof(int**),"inFixedLatency");   nctrl          = (int*)       ZMALLOC(nnode*sizeof(int), "nctrl");   nunit          = (int**)      ZMALLOC(nnode*sizeof(int*), "nunit");   for (n = 0; n < nnode; n++) {     if (n >= TOTAL_CPUS) {       /* XXX for compatibility with DISCO. Remove later XXX */       nctrl[n] = 1;     } else {       nctrl[n] = NUM_DISK_CONTROLLERS(M_FROM_CPU(n), MCPU_FROM_CPU(n));     }     sprintf(name, "inFixedLatency[%d]", n);     inFixedLatency[n] = (int**) ZMALLOC(nctrl[n]*sizeof(int*), name);     ASSERT(inFixedLatency[n]);     sprintf(name, "nunit[%d]", n);     nunit[n] = (int*) ZMALLOC(sizeof(int), name);     ASSERT(nunit[n]);     for (c = 0; c < nctrl[n]; c++) {       nunit[n][c] = uc;       sprintf(name, "inFixedLatency[%d][%d]", n, c);       inFixedLatency[n][c] = (int*) ZMALLOC(nunit[n][c]*sizeof(int), name);       ASSERT(inFixedLatency[n][c]);     }   }   int_f = int_fun;   /* register diskdev files */   Simcpt_Register("diskdev", DiskCheckpointCB, ALL_CPUS);   /* Do any per disk initialization */   SimhdInitDisks(restoreFromChkpt);}static voiddisk_name(int node, int ctrl, int unit){  if (!DKS_diskname(node,ctrl,unit)[0]) {    /*     * This disk has not been opened yet, need a name for     * the disk file. Try to generate a name in Tcl.     */    char* filename = TclDiskFileName(M_FROM_CPU(node),    /* machine */				     MCPU_FROM_CPU(node), /* node */				     ctrl, unit);    if (filename) {      /* got a name from Tcl (includes path) */      strcpy(DKS_filename(node,ctrl,unit), filename);    } else {      /* default */      sprintf(DKS_filename(node,ctrl,unit), "%s/DISK%d.%d.%d",	      DevFileDir, node, ctrl, unit);    }    /* diskname is an internal id (also used in the log) */    sprintf(DKS_diskname(node,ctrl,unit), "DISK%d.%d.%d",	    node, ctrl, unit);  }}voidsim_disk_touch(int node, int ctrl, int unit){  char name[32];  ASSERT(0 <= node && node < nnode             &&	 0 <= ctrl && ctrl < nctrl[node]       &&	 0 <= unit && unit < nunit[node][ctrl] &&	 dmodel_next < SIM_MAX_DISKS);  if (!dks[node]) {    /* node touches a disk for the first time */    sprintf(name, "dks[%d]", node);    dks[node] = (Device***) ZMALLOC(nctrl[node]*sizeof(Device**), name);    ASSERT(dks[node]);  }  if (!dks[node][ctrl]) {    /* controller used for the first time */    sprintf(name, "dks[%d][%d]", node, ctrl);    dks[node][ctrl] = (Device**) ZMALLOC(nunit[node][ctrl]*sizeof(Device*),					 name);    ASSERT(dks[node][ctrl]);  }  /* The following test will fail (eg. unit will already   * be 'touched') if we have restored from a checkpoint.   * The checkpoint restore code has to allocate the disk   * data structures in order to restore them, but the shadow   * structures in simmagic aren't yet initialized so it will   * call through to here on the first use by the OS.   */  if (!dks[node][ctrl][unit]) {     sprintf(name, "dks[%d][%d][%d]", node, ctrl, unit);     dks[node][ctrl][unit] = (Device*) ZMALLOC(sizeof(Device), name);     ASSERT(&DKS(node,ctrl,unit));     /* initialize newly allocated Device */     DKS(node,ctrl,unit).hdcpt.simhdStats.dfd = -1;     DKS(node,ctrl,unit).isReady              = 1;     DKS(node,ctrl,unit).hdcpt.accessed       = 0;     DKS(node,ctrl,unit).dmodel_no            = dmodel_next++;     disk_name(node, ctrl, unit); /* generate names */     /*     Sim_Warning("dks[%d][%d][%d] model entry %d.\n",		 node, ctrl, unit, DKS(node,ctrl,unit).dmodel_no);      */  }}/* * Do any necessary per disk initialization */static void SimhdInitDisks(int restoreFromChkpt){

⌨️ 快捷键说明

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