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

📄 ahc.c

📁 ml-rsim 多处理器模拟器 支持类bsd操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
      ahc->seq_state = SEQ_DMA_VECTOR;                  /*===================================================================*/      /* read DMA S/G vector via DMA                                       */      /* issue host bus transactions until remaining length is 0, then     */      /* wait for all data returns. If a reconnect request arrived in the  */      /* meantime drop current request and return to idle, otherwise       */      /* issue request on SCSI bus and remove from input queue.            */          case SEQ_DMA_VECTOR:      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: Vector DMA Done\n",		 ahc->scsi_me->mid, YS__Simtime);      for (n = 0; n < scb->sg_segment_count; n++)      YS__logmsg(ahc->scsi_me->nodeid,		 "[%i]   Segment %i: 0x%02X%02X%02X%02X 0x%02X%02X%02X%02X\n",		 ahc->scsi_me->mid,		 n,		 scb->dma_segments[n].addr3,		 scb->dma_segments[n].addr2,		 scb->dma_segments[n].addr1,		 scb->dma_segments[n].addr0,		 scb->dma_segments[n].length3,		 scb->dma_segments[n].length2,		 scb->dma_segments[n].length1,		 scb->dma_segments[n].length0);#endif            /* reconnect request arrived: drop current request and return to idle*/      if (ahc_queue_size(ahc->reconnect_scbs) > 0)	{#ifdef AHC_TRACE	  YS__logmsg(ahc->scsi_me->nodeid,		     "[%i] %.0f: Reconnect while processing command\n",		     ahc->scsi_me->mid, YS__Simtime);#endif	  	  if (IsNotScheduled(ahc->sequencer))	    schedule_event(ahc->sequencer, YS__Simtime + ahc->seq_cycle_fast);          ahc->seq_state = SEQ_IDLE;	  return;	}      /* otherwise: issue request on SCSI bus and remove from input queue  */      if (!ahc_scsi_command(ahc, scb))	YS__errmsg(ahc->scsi_me->nodeid,		   "AHC[%i]: SCSI Command failed", ahc->scsi_me->mid);      if ((ahc_queue_size(ahc->qin_fifo) > 0) &&	  (ahc_queue_head(ahc->qin_fifo) == ahc->seq_scb))	{	  ahc_queue_shiftout(ahc->qin_fifo, data);	  ahc->regs[QINCNT] = ahc_queue_size(ahc->qin_fifo);	  memcpy(regs + SCBARRAY,		 &ahc->scbs[data],		 AHC_REG_END - SCBARRAY);	  if (!(scb->control & TAG_ENB))	    ahc->pending[scb->tcl >> 4] = scb;	  scb->queue_time = YS__Simtime - scb->start_time;	}      scb->current_segment = 0;      scb->dma_length = scb->dma_length_done = 0;      regs[SCSIID] |= (scb->tcl & 0xF0);      /* prepare for data transfer, start at current S/G segment ----------*/      ahc->seq_state = SEQ_RESPONSE;      if (scb->sg_segment_count > 0)	{	  scb->dma_addr =	    (scb->dma_segments[scb->current_segment].addr3 << 24) |	    (scb->dma_segments[scb->current_segment].addr2 << 16) |	    (scb->dma_segments[scb->current_segment].addr1 << 8) |	    scb->dma_segments[scb->current_segment].addr0;	  scb->dma_sg_length =	    (scb->dma_segments[scb->current_segment].length3 << 24) |	    (scb->dma_segments[scb->current_segment].length2 << 16) |	    (scb->dma_segments[scb->current_segment].length1 << 8) |	    scb->dma_segments[scb->current_segment].length0;	  scb->dma_buffer = scb->data;	}      else	{	  scb->data          = NULL;	  scb->dma_buffer    = NULL;	  scb->dma_addr      = 0;	  scb->dma_sg_length = 0;	}      /*===================================================================*/      /* Wait for SCSI device response.                                    */    case SEQ_RESPONSE:      if (scb->status == SCB_ACTIVE)     /* keep polling while no response */	{	  if (IsNotScheduled(ahc->sequencer))	    schedule_event(ahc->sequencer, YS__Simtime + ahc->seq_cycle_fast);	  return;	}      lat = YS__Simtime - scb->start_time;      if (lat > ahc->request_connect_time_max)	ahc->request_connect_time_max = lat;      if (lat < ahc->request_connect_time_min)	ahc->request_connect_time_min = lat;      ahc->request_connect_time_avg += lat;      regs[WAITING_SCBH] = ahc->scbs[regs[WAITING_SCBH]].next;      if (scb->status == SCB_ERROR)      /* SCSI error (timeout): finish   */	{                                /* request and return to idle     */#ifdef AHC_TRACE	  YS__logmsg(ahc->scsi_me->nodeid,		     "[%i] %.0f: AHC Command Error\n",		     ahc->scsi_me->mid, YS__Simtime);#endif	  ahc_scsi_complete(ahc, scb);	  ahc->seq_state = SEQ_IDLE;	  if (IsNotScheduled(ahc->sequencer))	    schedule_event(ahc->sequencer, YS__Simtime + ahc->seq_cycle_fast);	  return;	}            if (scb->status == SCB_BUSY)       /* device busy: finish request    */	{                                /* and return to idle             */#ifdef AHC_TRACE	  YS__logmsg(ahc->scsi_me->nodeid,		     "[%i] %.0f: AHC Command Busy\n",		     ahc->scsi_me->mid, YS__Simtime);#endif	  ahc_scsi_complete(ahc, scb);	  ahc->seq_state = SEQ_IDLE;	  if (IsNotScheduled(ahc->sequencer))	    schedule_event(ahc->sequencer,			   YS__Simtime + ahc->seq_cycle_read * 50);	  return;	  	}            if (scb->status == SCB_DISCONNECT) /* SCSI disconnect: return to idle*/	{#ifdef AHC_TRACE	  YS__logmsg(ahc->scsi_me->nodeid,		     "[%i] %.0f: AHC Command Disconnect\n",		     ahc->scsi_me->mid, YS__Simtime);#endif	  ahc->seq_state = SEQ_IDLE;	  scb->control |= 0x04;	  if (IsNotScheduled(ahc->sequencer))	    schedule_event(ahc->sequencer,			   YS__Simtime + ahc->seq_cycle_fast);	  ahc->request_disconnect_count++;	  return;	}          if (scb->status == SCB_CONNECT)    /* SCSI connect: start data xfer  */	{	  ahc->seq_state = SEQ_DATA;	  if (IsNotScheduled(ahc->sequencer))	    schedule_event(ahc->sequencer,			   YS__Simtime + (scb->write ?			   ahc->seq_cycle_read :			   ahc->seq_cycle_write));	  return;	  	}            if (scb->status == SCB_COMPLETE)  /* request complete: finish it and */	{                               /* return to idle                  */#ifdef AHC_TRACE	  YS__logmsg(ahc->scsi_me->nodeid,		     "%.0f: AHC Command Complete %i (no DMA)\n",		     YS__Simtime, scb->status);#endif	  ahc_scsi_complete(ahc, scb);	  if (IsNotScheduled(ahc->sequencer))	    schedule_event(ahc->sequencer,			   YS__Simtime + (scb->write ?			   ahc->seq_cycle_read :			   ahc->seq_cycle_write));	  ahc->seq_state = SEQ_IDLE;	  return;	  	}                  /*===================================================================*/      /* data transfer: dma_length is set by connect/reconnect request,    */      /* issue host transactions until length is 0, if at end of current   */      /* segment move to next segment, check status at end of transfer.    */          case SEQ_DATA:      if (scb->dma_length > 0)	ahc_dma(ahc, scb);      /* at end of segment, more data and more segments: go to next segment*/      if ((scb->dma_sg_length <= 0) &&	  (scb->current_segment + 1 < scb->sg_segment_count))	{	  scb->current_segment++;          scb->dma_sg_length =	    (scb->dma_segments[scb->current_segment].length3 << 24) |	    (scb->dma_segments[scb->current_segment].length2 << 16) |	    (scb->dma_segments[scb->current_segment].length1 << 8) |	    scb->dma_segments[scb->current_segment].length0;	  scb->dma_addr =	    (scb->dma_segments[scb->current_segment].addr3 << 24) |	    (scb->dma_segments[scb->current_segment].addr2 << 16) |	    (scb->dma_segments[scb->current_segment].addr1 << 8) |	    scb->dma_segments[scb->current_segment].addr0;#ifdef AHC_TRACE	  YS__logmsg(ahc->scsi_me->nodeid,		     "[%i] %.0f: AHC Next Segment %i of %i -> 0x%08X 0x%08X\n",		     ahc->scsi_me->mid,		     YS__Simtime, scb->current_segment, scb->sg_segment_count,		     scb->dma_addr, scb->dma_sg_length);#endif	}      if (scb->dma_length_done > 0)       /* wait for completion           */	{	  if (IsNotScheduled(ahc->sequencer))	    schedule_event(ahc->sequencer,			   YS__Simtime + (scb->write ?			   ahc->seq_cycle_read :			   ahc->seq_cycle_write));	  return;	}      /* request is complete: finish it and return to idle ----------------*/      if (scb->status == SCB_COMPLETE)	{#ifdef AHC_TRACE	  YS__logmsg(ahc->scsi_me->nodeid,		     "[%i] %.0f: AHC Command Complete %i %i\n",		     ahc->scsi_me->mid, YS__Simtime, scb->status, ahc_queue_size(ahc->reconnect_scbs));#endif	  ahc_scsi_complete(ahc, scb);	  if (IsNotScheduled(ahc->sequencer))	    schedule_event(ahc->sequencer,			   YS__Simtime + (scb->write ?			   ahc->seq_cycle_read :			   ahc->seq_cycle_write));	  ahc->seq_state = SEQ_IDLE;	  return;	  	}      if (scb->status == SCB_DISCONNECT)	{	  ahc->seq_state = SEQ_IDLE;	  if (IsNotScheduled(ahc->sequencer))	    schedule_event(ahc->sequencer, YS__Simtime + ahc->seq_cycle_fast);	  return;	}	            /* no request status (neither complete nor save_data_ptr): poll -----*/            if (scb->status == SCB_CONNECT)	{	  if (IsNotScheduled(ahc->sequencer))	    schedule_event(ahc->sequencer, YS__Simtime + ahc->seq_cycle_fast);	  return;	}	      break;                  /*-------------------------------------------------------------------*/    default:      YS__errmsg(ahc->scsi_me->nodeid,		 "AHC[%i]: Unknown SCSI Sequencer State %i\n",		 ahc->scsi_me->mid, ahc->seq_state);    }}/*=========================================================================*//* Perform a pending DMA transaction                                       *//* copy data between internal buffer and main memory.                      *//* Called when request is completed at caches/memory.                      *//*=========================================================================*/static void ahc_perform(REQ *req){  ahc_scb_t *scb = (ahc_scb_t*)req->d.mem.aux;  char *addr;  int   n;  addr = PageTable_lookup(req->node, req->paddr);  if (addr == NULL)    YS__errmsg(req->node,	       "AHC: DMA to/from non-existing memory location 0x%08X\n",	       req->paddr);  if (req->prcr_req_type == WRITE)    memcpy(addr, req->d.mem.buf, req->d.mem.count);  else    memcpy(req->d.mem.buf, addr, req->d.mem.count);  scb->dma_length_done -= req->d.mem.count;}void ahc_complete(REQ *req, HIT_TYPE ht){}/*=========================================================================*//* Issue a host bus DMA transaction: Determine size based on remaining     *//* length and address aligmnent, determine read/write, set physical address*//* and completion callback routines. Issue to generic SCSI controller.     *//* Adjust DMA address, buffer pointer and length before returning.         *//*=========================================================================*/void ahc_dma(ahc_t *ahc, ahc_scb_t *scb){  REQ *req;  req = (REQ*)YS__PoolGetObj(&YS__ReqPool);  memset(req, 0, sizeof(REQ));  req->vaddr = scb->dma_addr;  req->paddr = scb->dma_addr;  req->size  = ARCH_linesz2;    req->perform     = ahc_perform;  req->complete    = ahc_complete;  req->d.mem.buf   = scb->dma_buffer;  req->d.mem.aux   = scb;  req->d.mem.count = min(min(scb->dma_length, scb->dma_sg_length),			 ARCH_linesz2 - (scb->dma_addr % ARCH_linesz2));  if (scb->write)    req->prcr_req_type = WRITE;  else    req->prcr_req_type = READ;    if (!SCSI_cntl_host_issue(ahc->scsi_me, req))    {      YS__PoolReturnObj(&YS__ReqPool, req);      return;    }  scb->dma_addr      += req->d.mem.count;  scb->dma_buffer    += req->d.mem.count;  scb->dma_length    -= req->d.mem.count;  scb->dma_sg_length -= req->d.mem.count;  if (req->d.mem.count <= 0)    YS__errmsg(ahc->scsi_me->nodeid,	       "AHC[%i]: Invalid DMA Transaction size %i 0x%08X in state %i\n",	       ahc->scsi_me->mid, req->d.mem.count, req->paddr, ahc->seq_state);  #ifdef AHC_TRACE  YS__logmsg(ahc->scsi_me->nodeid,	     "[%i] %.0f: DMA %s (%s) 0x%08X %i bytes -> %i %i %p\n",	     ahc->scsi_me->mid, YS__Simtime,	     scb->write ? "Write" : "Read",	     req->type == WRITEPURGE ? "WRITE_PURGE" : ReqName[req->req_type],	     req->paddr,	     req->d.mem.count,	     scb->dma_length,	     scb->dma_sg_length, req->d.mem.buf);#endif}/*=========================================================================*//* Assemble and issue SCSI request based on command vector. Allocate       *//* request structure, fill in initiator, target and lun, set queue tags    *//* and decode command, including length and block size. Also set DMA       *//* direction and allocate data buffer.                                     *//*=========================================================================*/int ahc_scsi_command(ahc_t *ahc, ahc_scb_t *scb)

⌨️ 快捷键说明

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