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

📄 ahc.c

📁 ml-rsim 多处理器模拟器 支持类bsd操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
	  regs[SSTAT0] &= ~data;          /* clear interrupt status bits   */	  if (!ahc->intr_scsi_clr_done)   /* compute interrupt latency     */	    {	      lat = YS__Simtime - ahc->intr_scsi_start;	      ahc->intr_scsi_clr_avg += lat;	      if (lat > ahc->intr_scsi_clr_max)		ahc->intr_scsi_clr_max = lat;	      if (lat < ahc->intr_scsi_clr_min)		ahc->intr_scsi_clr_min = lat;	      ahc->intr_scsi_clr_done = 1;	    }	  	  break;	  	  /*---------------------------------------------------------------*/	  /* clear SCSI interrupt status 1 (write only)                    */	case CLRSINT1:	  regs[CLRSINT1] &= ~data;        /* clear register                */	  regs[SSTAT1] &= ~data;          /* clear interrupt status bits   */	  if (!ahc->intr_scsi_clr_done)   /* compute interrupt latency     */	    {	      lat = YS__Simtime - ahc->intr_scsi_start;	      ahc->intr_scsi_clr_avg += lat;	      if (lat > ahc->intr_scsi_clr_max)		ahc->intr_scsi_clr_max = lat;	      if (lat < ahc->intr_scsi_clr_min)		ahc->intr_scsi_clr_min = lat;	      ahc->intr_scsi_clr_done = 1;	    }	  	  break;	  	  /*---------------------------------------------------------------*/	  /* clear host interrupt (write only)                             */	case CLRINT:	  regs[CLRINT] &= ~data;          /* clear register                */	  regs[INTSTAT] &= ~data;         /* clear interrupt status bits   */	  if (!ahc->intr_seq_clr_done)    /* compute interrupt latency     */	    {	      lat = YS__Simtime - ahc->intr_seq_start;	      ahc->intr_seq_clr_avg += lat;	      if (lat > ahc->intr_seq_clr_max)		ahc->intr_seq_clr_max = lat;	      if (lat < ahc->intr_seq_clr_min)		ahc->intr_seq_clr_min = lat;	      ahc->intr_seq_clr_done = 1;	    }	  if (!ahc->intr_cmpl_clr_done)   /* compute interrupt latency     */	    {	      lat = YS__Simtime - ahc->intr_cmpl_start;	      ahc->intr_cmpl_clr_avg += lat;	      if (lat > ahc->intr_cmpl_clr_max)		ahc->intr_cmpl_clr_max = lat;	      if (lat < ahc->intr_cmpl_clr_min)		ahc->intr_cmpl_clr_min = lat;	      ahc->intr_cmpl_clr_done = 1;	    }	  	  break;	  	  /*---------------------------------------------------------------*/	  /* write to SCB input queue: load queue, adjust counter,         */	  /* start seqencer                                                */	case QINFIFO:	  ahc_queue_shiftin(ahc->qin_fifo, data);	  regs[QINCNT] = ahc_queue_size(ahc->qin_fifo);#ifdef AHC_TRACE	  YS__logmsg(ahc->scsi_me->nodeid,		     "  Load QIN -> %i\n", regs[QINCNT]);#endif	  	  if (!(regs[HCNTRL] & PAUSE) &&	      (IsNotScheduled(ahc->sequencer)))	    schedule_event(ahc->sequencer, YS__Simtime + ahc->seq_cycle_fast);	  ahc->scbs[data].start_time = YS__Simtime;	  ahc->request_count++;	  break;	  /*---------------------------------------------------------------*/	  /* write to any SCB register: copy new byte into current SCB     */	  /* entry and add SCB index to offset if in auto-increment mode   */	case SCB_CONTROL:	case SCB_TCL:	case SCB_TARGET_STATUS:	case SCB_SGCOUNT:	case SCB_SGPTR0:	case SCB_SGPTR1:	case SCB_SGPTR2:	case SCB_SGPTR3:	case SCB_RESID_SGCNT:	case SCB_RESID_DCNT0:	case SCB_RESID_DCNT1:	case SCB_RESID_DCNT2:	case SCB_DATAPTR0:	case SCB_DATAPTR1:	case SCB_DATAPTR2:	case SCB_DATAPTR3:	case SCB_DATACNT0:	case SCB_DATACNT1:	case SCB_DATACNT2:	case SCB_CMDPTR0:	case SCB_CMDPTR1:	case SCB_CMDPTR2:	case SCB_CMDPTR3:	case SCB_CMDLEN:	case SCB_TAG:	case SCB_NEXT:	case SCB_PREV:	  {	    unsigned char *p;	    p = (unsigned char*)&(ahc->scbs[regs[SCBPTR]]);	    p += offset - SCBARRAY;	    	    if (regs[SCBCNT] & SCBAUTO)	      p += (regs[SCBCNT] & SCBCNT_MASK);	    *p = data;	    break;	  }	  	  /*---------------------------------------------------------------*/	default:	  break;	}    }  /* end of request per-byte loop */    /*-----------------------------------------------------------------------*/  /* for writes to a SCB register, increment SCB index if auto-increment   */    if ((offset >= SCBARRAY) &&      (offset <= AHC_REG_END) &&      (regs[SCBCNT] & SCBAUTO))    {      memcpy(regs + SCBARRAY,	     &ahc->scbs[regs[SCBPTR]],	     AHC_REG_END - SCBARRAY);      regs[SCBCNT] =	SCBAUTO | (((regs[SCBCNT] & SCBCNT_MASK) + olength) & SCBCNT_MASK);    }  return(1);}/*=========================================================================*//* PCI Mapping callback routine: called when host writes to PCI address    *//* space register. If new value is -1 simply return required address space *//* and flag bits, otherwise map control registers at new base address.     *//*=========================================================================*/void ahc_pci_map(void *controller, unsigned address,		 int node, int module, int function, int reg,		 unsigned *size, unsigned *flags){  ahc_t *ahc = (ahc_t*)controller;  *flags = PCI_MAPREG_TYPE_IO;              /* require I/O space           */  if (address == 0xFFFFFFFF)                /* return size for function 0  */    {                                       /* and register 0, otherwise   */      if ((function == 0) && (reg == 0))    /* return 0 (unused)           */	*size = AHC_REG_END;      else	*size = 0;      return;    }  else                                      /* map control registers       */    {      if (ahc->base_addr != 0)	{	  AddrMap_remove(node, ahc->base_addr, ahc->base_addr + AHC_REG_END,			 module);	  PageTable_remove(node, ahc->base_addr);	}      address = PCI_MAPREG_IO_ADDR(address);      AddrMap_insert(node, address, address + AHC_REG_END, module);      PageTable_insert(node, address, (char*)ahc->regs);      ahc->base_addr = address;    }}/*=========================================================================*//* SCSI Controller Sequencer state machine                                 *//* Controls processing of requests, SCSI bus transactions and host bus DMA *//*=========================================================================*/void ahc_sequencer(void){  ahc_t           *ahc = (ahc_t*)EventGetArg(NULL);  unsigned char   *regs  = ahc->regs;  unsigned char    data;  ahc_scb_t       *scb;  double           lat;  int              n;  scb = &ahc->scbs[ahc->seq_scb];  switch (ahc->seq_state)    {      /*===================================================================*/      /* Idle state: return immediately if sequencer is halted, check for  */      /* reconnect-SCB, otherwise take SCB off the input queue. Check if   */      /* new request is a second non-queued request to a target.           */          case SEQ_IDLE:      if (ahc->seq_pause)	return;      if (regs[WAITING_SCBH] != SCB_LIST_NULL)	{	  data = regs[WAITING_SCBH];	  ahc->regs[QINCNT] = ahc_queue_size(ahc->qin_fifo);	  if ((ahc_queue_size(ahc->qin_fifo) == 0) ||	      ((ahc_queue_size(ahc->qin_fifo) > 0) &&	       (ahc_queue_head(ahc->qin_fifo) != data)))	    {	      ahc_queue_shiftin_head(ahc->qin_fifo, data);	    }	  regs[WAITING_SCBH] = ahc->scbs[data].next;#ifdef AHC_TRACE	  YS__logmsg(ahc->scsi_me->nodeid,		     "[%i] %.0f: AHC Taking entry %i off selection queue; next = %i\n",		     ahc->scsi_me->mid, YS__Simtime, data, regs[WAITING_SCBH]);#endif	}      if (ahc_queue_size(ahc->reconnect_scbs) > 0)   /* reconnect SCB ?    */	{	  data = ahc_queue_head(ahc->reconnect_scbs); /* take 1. elem. from Q*/	  ahc->seq_scb = data;	  scb = &(ahc->scbs[data]);	  ahc_queue_shiftout(ahc->reconnect_scbs, data);	  regs[SCBPTR]  = ahc->seq_scb;          memcpy(regs + SCBARRAY, scb, AHC_REG_END - SCBARRAY);#ifdef AHC_TRACE	  YS__logmsg(ahc->scsi_me->nodeid,		     "[%i] %.0f: AHC Taking entry %i off reconnect queue; %i waiting\n",		     ahc->scsi_me->mid, YS__Simtime, data,		     ahc_queue_size(ahc->reconnect_scbs));#endif	  ahc->seq_state = SEQ_DATA;	  schedule_event(ahc->sequencer, YS__Simtime + ahc->seq_cycle_fast);	  return;	}      else                                       /* else check input queue */	{	  if (ahc_queue_size(ahc->qin_fifo) == 0)	    return;	  data = ahc_queue_head(ahc->qin_fifo);  /* take first elem. from Q*/	  ahc->seq_scb = data;	  scb = &(ahc->scbs[data]);#ifdef AHC_TRACE	  YS__logmsg(ahc->scsi_me->nodeid,		     "[%i] %.0f: AHC Taking entry %i off command queue; %i waiting\n",		     ahc->scsi_me->mid, YS__Simtime, data,		     ahc_queue_size(ahc->qin_fifo)-1);#endif	  if ((ahc->pending[scb->tcl >> 4] != NULL) &&	      (!(scb->control & TAG_ENB)))       /* stall second non-queued*/	    {                                    /* request to a target    */#ifdef AHC_TRACE	      YS__logmsg(ahc->scsi_me->nodeid,			 "[%i] %.0f: AHC Stall additional non-queued request\n",			 ahc->scsi_me->mid, YS__Simtime);#endif	      return;	    }	  if (regs[WAITING_SCBH] == SCB_LIST_NULL)	    regs[WAITING_SCBH] = data;	  else	    {	      unsigned char p;	      p = regs[WAITING_SCBH];	      while (ahc->scbs[p].next != SCB_LIST_NULL)		p = ahc->scbs[p].next;	      ahc->scbs[p].next = data; 	    }	  scb->next = SCB_LIST_NULL;	  regs[SCBPTR]  = ahc->seq_scb;          memcpy(regs + SCBARRAY, scb, AHC_REG_END - SCBARRAY);	}#ifdef AHC_TRACE      YS__logmsg(ahc->scsi_me->nodeid,		 "[%i] SCB[%i]\n", ahc->scsi_me->mid, data);      YS__logmsg(ahc->scsi_me->nodeid,		 "      Control  = 0x%02X\n", scb->control);      YS__logmsg(ahc->scsi_me->nodeid,		 "      Target   = 0x%02X\n", scb->tcl);      YS__logmsg(ahc->scsi_me->nodeid,		 "      SegCount = 0x%02X\n", scb->sg_segment_count);      YS__logmsg(ahc->scsi_me->nodeid,		 "      Segment  = 0x%02X%02X%02X%02X\n",		 scb->sg_segment_ptr3, scb->sg_segment_ptr2, 		 scb->sg_segment_ptr1, scb->sg_segment_ptr0);      YS__logmsg(ahc->scsi_me->nodeid,		 "      Data     = 0x%02X%02X%02X%02X\n",		 scb->data_ptr3, scb->data_ptr2, 		 scb->data_ptr1, scb->data_ptr0);      YS__logmsg(ahc->scsi_me->nodeid,		 "      DataLen  = 0x00%02X%02X%02X\n",		 scb->data_count2, scb->data_count1, 		 scb->data_count0);      YS__logmsg(ahc->scsi_me->nodeid,		 "      Command  = 0x%02X%02X%02X%02X\n",		 scb->scsi_cmd_ptr3, scb->scsi_cmd_ptr2, 		 scb->scsi_cmd_ptr1, scb->scsi_cmd_ptr0);      YS__logmsg(ahc->scsi_me->nodeid,		 "      CmdLen   = 0x%02X\n", scb->scsi_cmd_len);      YS__logmsg(ahc->scsi_me->nodeid,		 "      Tag      = 0x%02X\n", scb->tag);      YS__logmsg(ahc->scsi_me->nodeid,		 "      Next     = 0x%02X\n", scb->next);      YS__logmsg(ahc->scsi_me->nodeid,		 "      Prev     = 0x%02X\n", scb->prev);#endif            /* prepare for command DMA ------------------------------------------*/      scb->dma_addr =	(scb->scsi_cmd_ptr3 << 24) | (scb->scsi_cmd_ptr2 << 16) |	(scb->scsi_cmd_ptr1 << 8) | scb->scsi_cmd_ptr0;      scb->dma_length      = scb->scsi_cmd_len;      scb->dma_sg_length   = scb->scsi_cmd_len;      scb->dma_length_done = scb->scsi_cmd_len;      scb->dma_buffer      = scb->command;      if (scb->dma_length > sizeof(scb->command))	YS__errmsg(ahc->scsi_me->nodeid,		   "AHC[%i]: SCSI Command too long (0x%02X)",		   ahc->scsi_me->mid, scb->dma_length);      ahc->seq_state = SEQ_COMMAND;      scb->status = SCB_ACTIVE;      scb->write  = 0;                  /*===================================================================*/      /* read SCSI command into internal buffer via DMA                    */      /* issue host bus transactions until dma_length is 0, then wait for  */      /* all data returns.                                                 */    case SEQ_COMMAND:      if (scb->dma_length > 0)                    /* need more data        */	ahc_dma(ahc, scb);      if (scb->dma_length_done > 0)               /* wait for data returns */	{	  if (IsNotScheduled(ahc->sequencer))	    schedule_event(ahc->sequencer, YS__Simtime + ahc->seq_cycle_fast);	  return;	}#ifdef AHC_TRACE      YS__logmsg(ahc->scsi_me->nodeid,		 "[%i] %.0f: Command DMA Done\n",		 ahc->scsi_me->mid, YS__Simtime);#endif      /* prepare for DMA of S/G vector if it has not been read ------------*/            if ((scb->dma_segments == NULL) && (scb->sg_segment_count > 0))	{	  scb->dma_segments = malloc(scb->sg_segment_count *				     sizeof(ahc_dmaseg_t));	  if (scb->dma_segments == NULL)	    YS__errmsg(ahc->scsi_me->nodeid,		       "Malloc failed in %s:%i", __FILE__, __LINE__);	  scb->dma_addr =	    (scb->sg_segment_ptr3 << 24) | (scb->sg_segment_ptr2 << 16) |	    (scb->sg_segment_ptr1 << 8) | scb->sg_segment_ptr0;	  scb->dma_length      = scb->sg_segment_count * sizeof(ahc_dmaseg_t);	  scb->dma_sg_length   = scb->sg_segment_count * sizeof(ahc_dmaseg_t);	  scb->dma_length_done = scb->dma_length;	  scb->dma_buffer      = (unsigned char*)scb->dma_segments;	}      else	{	  scb->dma_length      = 0;	  scb->dma_sg_length   = 0;	  scb->dma_length_done = 0;	}

⌨️ 快捷键说明

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