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

📄 ahc.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 <malloc.h>#include <stdio.h>#include <string.h>#include <values.h>#include "sim_main/simsys.h"#include "sim_main/util.h"#include "sim_main/evlst.h"#include "Processor/pagetable.h"#include "Caches/req.h"#include "Bus/bus.h"#include "IO/addr_map.h"#include "IO/ahc.h"#include "IO/scsi_bus.h"#include "IO/scsi_controller.h"#include "IO/io_generic.h"#include "../../lamix/dev/ic/aic7xxxreg.h"#include "../../lamix/dev/pci/pcireg.h"typedef unsigned char u_int8_t;#include "../../lamix/dev/scsipi/scsi_all.h"#include "../../lamix/dev/scsipi/scsipi_all.h"#include "../../lamix/dev/scsipi/scsi_disk.h"#include "../../lamix/dev/scsipi/scsipi_disk.h"#define min(a, b)               ((a) > (b) ? (b) : (a))/*=========================================================================*//* This structure contains the handles for the generic SCSI controller to  *//* communicate with the Adaptec model.                                     */SCSI_CONTROLLER_SPEC ahc_spec ={  ahc_host_read,  ahc_host_write,  ahc_pci_map,  ahc_scsi_wonbus,  ahc_scsi_request,  ahc_scsi_response,  ahc_print_params,  ahc_stat_report,  ahc_stat_clear,  ahc_dump};/*=========================================================================*//* Initialize Adaptec SCSI Controller: allocate control structure, allocate*//* control registers and SCB array, create sequencer event and initialize. *//*=========================================================================*/void ahc_init(SCSI_CONTROLLER *pscsi, int scsi_id){  ahc_t *ahc;  int    scbs;  scbs = MAX_SCBS_DEFAULT;    get_parameter("AHC_scbs", &scbs, PARAM_INT);  /* allocate internal data structures ------------------------------------*/  ahc = malloc(sizeof(ahc_t));  if (ahc == NULL)    YS__errmsg(pscsi->nodeid, "Malloc failed at %s:%i", __FILE__, __LINE__);  memset(ahc, 0, sizeof(ahc_t));  ahc->scsi_me      = pscsi;  ahc->scsi_id      = scsi_id;  ahc->max_scbs     = scbs;  ahc->base_addr    = 0;  pscsi->contr_spec = &ahc_spec;  pscsi->controller = ahc;  ahc->regs = malloc(AHC_REG_END);  if (ahc->regs == NULL)    YS__errmsg(pscsi->nodeid, "Malloc failed at %s:%i", __FILE__, __LINE__);  memset(ahc->regs, 0, AHC_REG_END);  ahc->scbs = malloc(sizeof(ahc_scb_t) * ahc->max_scbs);  if (ahc->scbs == NULL)    YS__errmsg(pscsi->nodeid, "Malloc failed at %s:%i", __FILE__, __LINE__);  memset(ahc->scbs, 0, sizeof(ahc_scb_t) * ahc->max_scbs);  ahc->pending = malloc(sizeof(ahc_scb_t*) * SCSI_WIDTH * 8);  if (ahc->pending == NULL)    YS__errmsg(pscsi->nodeid, "Malloc failed at %s:%i", __FILE__, __LINE__);  memset(ahc->pending, 0, sizeof(ahc_scb_t*) * SCSI_WIDTH * 8);  /* create sequencer event -----------------------------------------------*/  ahc->seq_cycle_read =    ((1000000/SCSI_FREQUENCY) / CPU_CLK_PERIOD) * (ARCH_linesz2/SCSI_WIDTH);  ahc->seq_cycle_write = (int)((double)ahc->seq_cycle_read*0.98);  ahc->seq_cycle_fast = BUS_FREQUENCY * 2;  ahc->seq_state = SEQ_IDLE;  ahc->sequencer = NewEvent("AHC SCSI Sequencer", ahc_sequencer,			    NODELETE, 0);  EventSetArg(ahc->sequencer, ahc, sizeof(ahc));  /* initialize (reset) control registers and statistics ------------------*/    ahc_reset(ahc);    ahc_stat_clear(ahc);}/*=========================================================================*//* Reset internal data structures. Called during initialization and upon   *//* software reset (write to reset register).                               *//* Clear all registers, return sequencer to idle state and reset SCB       *//* queues. Probably not safe during normal operation.                      *//*=========================================================================*/void ahc_reset(ahc_t *ahc){  memset(ahc->regs, 0, AHC_REG_END);  ahc->seq_state         = SEQ_IDLE;  ahc->seq_pause         = 1;  ahc->seq_scb           = 0;  if (IsScheduled(ahc->sequencer))    deschedule_event(ahc->sequencer);  ahc_queue_init(ahc->qin_fifo);  ahc_queue_init(ahc->qout_fifo);  ahc_queue_init(ahc->reconnect_scbs);  ahc->regs[SCSIID]             = ahc->scsi_id;  ahc->regs[SCSICONF]           = ahc->scsi_id;  ahc->regs[SCSICONF+1]         = ahc->scsi_id;  ahc->regs[DISC_DSB_A]         = 0x00;  ahc->regs[DISC_DSB_B]         = 0x00;  ahc->regs[WAITING_SCBH]       = SCB_LIST_NULL;  ahc->regs[TARG_SCRATCH+0x10]  = ahc->scsi_me->scsi_max_target;  ahc->regs[TARG_SCRATCH+0x11]  = ahc->scsi_me->scsi_max_lun;  if (SCSI_WIDTH > 1)    ahc->regs[SBLKCTL] = SELWIDE;  else    ahc->regs[SBLKCTL] = 0;  ahc->regs[HCNTRL]  = PAUSE | CHIPRSTACK;}/*=========================================================================*//* Callback routine for host bus reads. Shift SCB output queue upon read   *//* from head and collect statistics for interrupt status reads.            *//*=========================================================================*/int ahc_host_read(void *controller, unsigned address, unsigned length){  ahc_t         *ahc = (ahc_t*)controller;  unsigned char *regs, data;  unsigned       offset;  double         lat;  if ((address < ahc->base_addr) || (address >= ahc->base_addr + AHC_REG_END))    {      YS__warnmsg(ahc->scsi_me->nodeid,		  "AHC: Read from invalid address 0x%08X\n",		  address);      return(1);    }    offset = address - ahc->base_addr;  regs = ahc->regs;    /* handle each byte that is read by the request individually ------------*/    for (;       length > 0;       offset++, length--)    {#ifdef AHC_TRACE      YS__logmsg(ahc->scsi_me->nodeid,		 "[%i] AHC Read 0x%03X %i -> 0x%02X\n",		 ahc->scsi_me->mid, offset, length, ahc->regs[offset]);#endif      switch(offset)	{	  /*---------------------------------------------------------------*/	  /* read from SCB output queue: shift queue and adjust counter    */	case QOUTFIFO:          ahc_queue_shiftout(ahc->qout_fifo, data);	  regs[QOUTCNT]  = ahc_queue_size(ahc->qout_fifo);	  regs[QOUTFIFO] = ahc_queue_head(ahc->qout_fifo);          lat = YS__Simtime - ahc->scbs[data].start_time;	  if (lat > ahc->request_total_time_max)	    ahc->request_total_time_max = lat;	  if (lat < ahc->request_total_time_min)	    ahc->request_total_time_min = lat;	  ahc->request_total_time_avg += lat;          break;	  /*---------------------------------------------------------------*/	  /* read from interrupt status: record latency for first read     */	case INTSTAT:	  if (!ahc->intr_seq_lat_done)	    {	      lat = YS__Simtime - ahc->intr_seq_start;	      ahc->intr_seq_lat_avg += lat;	      if (lat > ahc->intr_seq_lat_max)		ahc->intr_seq_lat_max = lat;	      if (lat < ahc->intr_seq_lat_min)		ahc->intr_seq_lat_min = lat;	      ahc->intr_seq_lat_done = 1;	    }	  if (!ahc->intr_cmpl_lat_done)	    {	      lat = YS__Simtime - ahc->intr_cmpl_start;	      ahc->intr_cmpl_lat_avg += lat;	      if (lat > ahc->intr_cmpl_lat_max)		ahc->intr_cmpl_lat_max = lat;	      if (lat < ahc->intr_cmpl_lat_min)		ahc->intr_cmpl_lat_min = lat;	      ahc->intr_cmpl_lat_done = 1;	    }	  if (!ahc->intr_scsi_lat_done)	    {	      lat = YS__Simtime - ahc->intr_scsi_start;	      ahc->intr_scsi_lat_avg += lat;	      if (lat > ahc->intr_scsi_lat_max)		ahc->intr_scsi_lat_max = lat;	      if (lat < ahc->intr_scsi_lat_min)		ahc->intr_scsi_lat_min = lat;	      ahc->intr_scsi_lat_done = 1;	    }	  break;	}    }  return(1);}/*=========================================================================*//* Callback routine for host bus writes.                                   *//* Handle side-effects and statistics.                                     *//*=========================================================================*/int ahc_host_write(void *controller, unsigned address, unsigned length){  unsigned char  data, *regs;  unsigned       olength = length;  ahc_t         *ahc = (ahc_t*)controller;  unsigned       offset;  double         lat;    if ((address < ahc->base_addr) ||      (address >= ahc->base_addr + AHC_REG_END))    {      YS__warnmsg(ahc->scsi_me->nodeid,		  "AHC: Read from invalid address 0x%08X\n", address);      return(1);    }    offset = address - ahc->base_addr;  regs = ahc->regs;    /* handle each byte that is affected by the request individually --------*/    for (;       length > 0;       offset++, length--)    {      data = regs[offset];#ifdef AHC_TRACE      YS__logmsg(ahc->scsi_me->nodeid,		 "[%i] AHC Write 0x%03X %i -> 0x%02X\n",		 ahc->scsi_me->mid, offset, length, data);#endif      switch (offset)	{	  /*---------------------------------------------------------------*/	  /* change SCB pointer: copy new SCB entry into register set      */	case SCBPTR:	  data %= ahc->max_scbs;	  memcpy(regs + SCBARRAY,		 &ahc->scbs[data],		 AHC_REG_END - SCBARRAY);#ifdef AHC_TRACE	  YS__logmsg(ahc->scsi_me->nodeid,		     "[%i]  Change SCB Pointer to %i\n",		     ahc->scsi_me->mid, data);#endif	  regs[SCBPTR] = data;	  break;	  /*---------------------------------------------------------------*/	  /* host control write: start or stop sequencer, perform reset    */	case HCNTRL:	  if (data & PAUSE)               /* pause bit set: halt sequencer */	    {	      ahc->seq_pause = 1;#ifdef AHC_TRACE	      YS__logmsg(ahc->scsi_me->nodeid,			 "[%i]  Pause Sequencer\n",			 ahc->scsi_me->mid);#endif	    }	  	  if (!(data & PAUSE) &&          /* pause bit cleared: start seq. */	      (ahc->seq_pause))	    {#ifdef AHC_TRACE	      YS__logmsg(ahc->scsi_me->nodeid,			 "[%i]  UnPause Sequencer\n",			 ahc->scsi_me->mid);#endif	      if (IsNotScheduled(ahc->sequencer))		schedule_event(ahc->sequencer,			       YS__Simtime + ahc->seq_cycle_fast);	      ahc->seq_pause = 0;	    }	  	  if (data & CHIPRST)             /* reset bit set: perform reset  */	    {#ifdef AHC_TRACE	      YS__logmsg(ahc->scsi_me->nodeid,			 "[%i]  Reset AHC\n", ahc->scsi_me->mid);#endif	      ahc_reset(ahc);	      regs[HCNTRL] = CHIPRSTACK;	    }	  break;	  	  /*---------------------------------------------------------------*/	  /* clear SCSI interrupt status 0 (write only)                    */	case CLRSINT0:	  regs[CLRSINT0] &= ~data;        /* clear register                */

⌨️ 快捷键说明

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