예제 #1
0
파일: pcmcia_ide.c 프로젝트: Fyleo/rtems
/*
 * MPC5200 BestComm interrupt handlers
 */
static void pcmcia_ide_recv_dmairq_hdl(rtems_irq_hdl_param unused)
{
  SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend,IDE_RX_TASK_NO);

/*Disable receive ints*/
  bestcomm_glue_irq_disable(IDE_RX_TASK_NO);

  pcmcia_ide_rxInterrupts++; 		/* Rx int has occurred */

  if (pcmcia_ide_hdl_task != 0) {
    rtems_event_send(pcmcia_ide_hdl_task,PCMCIA_IDE_INTERRUPT_EVENT);
  }
}
예제 #2
0
/*!
 * \brief	Clear the interrupt for a given BestComm task.
 * \param	taskId	Task handle passed back from a successful TaskSetup()
 * \returns	0 on success or negative on failure
 * \returns	TASK_ERR_NO_ERR (which is not really an error) for success
 *			or TASK_ERR_INVALID_ARG for an invalid taskId.
 */
int TaskIntClear( TaskId taskId )
{
	if(    ((taskId >= 0)
		&& (taskId <  MAX_TASKS))
		|| (taskId == DEBUG_INTR_ID)
		|| (taskId == TEA_INTR_ID)
	  ) {

		SDMA_CLEAR_IEVENT( SDMA_INT_PEND, taskId );
		return TASK_ERR_NO_ERR;	/* success */
	} else {
		return TASK_ERR_INVALID_ARG;
	}
}
예제 #3
0
파일: pcmcia_ide.c 프로젝트: Fyleo/rtems
void mpc5200_pcmciaide_dma_blockop(bool is_write,
				   int minor,
				   uint16_t block_size,
				   rtems_blkdev_sg_buffer *bufs,
				   uint32_t *cbuf,
				   uint32_t *pos)

{
#if IDE_USE_DMA
  /*
   * Nameing:
   * - a block is one unit of data on disk (multiple sectors)
   * - a buffer is a contignuous chunk of data in memory
   * a block on disk may be filled with data from several buffers
   */
  uint32_t buf_idx,bufs_from_dma, bufs_to_dma,bufs_total;
  uint32_t bds_free;
  uint32_t llength;
  rtems_status_code rc = RTEMS_SUCCESSFUL;
  rtems_event_set events;
  BDIdx nxt_bd_idx;
  bool use_irq = (_System_state_Current == SYSTEM_STATE_UP);
  /*
   * determine number of blocks
   */
  llength = 0;
  buf_idx = 0;
  bufs += *cbuf; /* *cbuf is the index of the next buffer to send in this transaction */
  while (llength < block_size) {
    llength += bufs[buf_idx++].length;
  }
  bufs_from_dma = 0;
  bufs_to_dma   = 0;
  bufs_total    = buf_idx;
  /*
   * here all BDs should be unused
   */
  bds_free = is_write ? PCMCIA_IDE_DMA_WR_BD_CNT : PCMCIA_IDE_DMA_RD_BD_CNT;
  /*
   * repeat, until all bufs are transferred
   */
  while ((rc == RTEMS_SUCCESSFUL) &&
	 (bufs_from_dma < bufs_total)) {

    while ((rc == RTEMS_SUCCESSFUL) &&
	   (bufs_to_dma < bufs_total) &&
	   (bds_free > 0)) {
      /*
       * fill in BD, set interrupt if needed
       */
    SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend,(is_write
	                                  ? IDE_TX_TASK_NO
	                                  : IDE_RX_TASK_NO));
      if (is_write) {
	TaskBDAssign(pcmcia_ide_txTaskId ,
		     (void *)bufs[bufs_to_dma].buffer,
		     (void *)mpc5200_ata_drive_regs[IDE_REGISTER_DATA_WORD],
		     bufs[bufs_to_dma].length,
		     0/* flags */);
#if IDE_USE_STATISTICS
	mpc5200_pcmciaide_write_block_block_cnt++;
#endif
      }
      else {
	TaskBDAssign(pcmcia_ide_rxTaskId ,
		     (void *)mpc5200_ata_drive_regs[IDE_REGISTER_DATA_WORD],
		     (void *)bufs[bufs_to_dma].buffer,
		     bufs[bufs_to_dma].length,
		     0/* flags */);
#if IDE_USE_STATISTICS
	mpc5200_pcmciaide_read_block_block_cnt++;
#endif
      }
      bufs_to_dma ++;
      bds_free    --;
    }
    if (is_write) {
      TaskStart( pcmcia_ide_txTaskId, TASK_AUTOSTART_DISABLE,
		 pcmcia_ide_txTaskId, TASK_INTERRUPT_DISABLE );
    }
    else {
      TaskStart( pcmcia_ide_rxTaskId, TASK_AUTOSTART_DISABLE,
		 pcmcia_ide_rxTaskId, TASK_INTERRUPT_DISABLE );
    }
    if (use_irq) {

      /*
       * enable interrupts, wait for interrupt event
       */
      pcmcia_ide_hdl_task = rtems_task_self();
      bestcomm_glue_irq_enable((is_write
				? IDE_TX_TASK_NO
				: IDE_RX_TASK_NO));

      rtems_event_receive(PCMCIA_IDE_INTERRUPT_EVENT,
			  RTEMS_WAIT | RTEMS_EVENT_ANY,
			  RTEMS_NO_TIMEOUT, &events);

      pcmcia_ide_hdl_task = 0;
    }
    else {
      /*
       * HACK: just wait some time...
       */
      /*
       * FIXME: poll, until SDMA is finished
       */
      volatile int32_t i;
      for (i = 0;i < 10000;i++) {};
    }

    do {
	  nxt_bd_idx = TaskBDRelease(is_write
	   				             ? pcmcia_ide_txTaskId
					             : pcmcia_ide_rxTaskId);
      if ((nxt_bd_idx != TASK_ERR_BD_RING_EMPTY) &&
          (nxt_bd_idx != TASK_ERR_BD_BUSY)) {
        (*cbuf)++;
        (*pos) += bufs[bufs_from_dma].length;
        bufs_from_dma++;
        bds_free++;
	  }
    } while ((nxt_bd_idx != TASK_ERR_BD_RING_EMPTY) &&
             (nxt_bd_idx != TASK_ERR_BD_BUSY)       &&
  	         (bufs_from_dma < bufs_to_dma));
  }
#endif /* IDE_USE_DMA */
}