Beispiel #1
0
/* Queue a division exception.  */
enum frv_dtt
frvbf_division_exception (SIM_CPU *current_cpu, enum frv_dtt dtt,
			  int target_index, int non_excepting)
{
  /* If there was an overflow and it is masked, then record it in
     ISR.AEXC.  */
  USI isr = GET_ISR ();
  if ((dtt & FRV_DTT_OVERFLOW) && GET_ISR_EDE (isr))
    {
      dtt &= ~FRV_DTT_OVERFLOW;
      SET_ISR_AEXC (isr);
      SET_ISR (isr);
    }
  if (dtt != FRV_DTT_NO_EXCEPTION)
    {
      if (non_excepting)
	{
	  /* Non excepting instruction, simply set the NE flag for the target
	     register.  */
	  SI NE_flags[2];
	  GET_NE_FLAGS (NE_flags, H_SPR_GNER0);
	  SET_NE_FLAG (NE_flags, target_index);
	  SET_NE_FLAGS (H_SPR_GNER0, NE_flags);
	}
      else
	frv_queue_division_exception_interrupt (current_cpu, dtt);
    }
  return dtt;
}
/* Record the state of a division exception in the ISR.  */
static void
set_isr_exception_fields (
  SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item
)
{
  USI isr = GET_ISR ();
  int dtt = GET_ISR_DTT (isr);
  dtt |= item->u.dtt;
  SET_ISR_DTT (isr, dtt);
  SET_ISR (isr);
}
static SI
fr400_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
{
  if (address & align_mask)
    {
      /* Make sure that this exception is not masked.  */
      USI isr = GET_ISR ();
      if (! GET_ISR_EMAM (isr))
	{
	  /* Bad alignment causes a data_access_error on fr400.  */
	  frv_queue_data_access_error_interrupt (current_cpu, address);
	}
      address &= ~align_mask;
    }
  /* Nothing to check.  */
  return address;
}
struct frv_interrupt_queue_element *
frv_queue_mem_address_not_aligned_interrupt (SIM_CPU *current_cpu, USI addr)
{
  struct frv_interrupt_queue_element *new_element;
  USI isr = GET_ISR ();

  /* Make sure that this exception is not masked.  */
  if (GET_ISR_EMAM (isr))
    return NULL;

  /* Queue the interrupt.  */
  new_element = frv_queue_program_interrupt (current_cpu,
					     FRV_MEM_ADDRESS_NOT_ALIGNED);
  new_element->eaddress = addr;
  new_element->u.data_written = frv_interrupt_state.data_written;
  frv_interrupt_state.data_written.length = 0;

  return new_element;
}
/************************
 *
 *	hwt_read
 *
 *	Stop hardware timer and read time elapsed since last start.
 *
 *	u_long hwt_read(smc) ;
 * In
 *	smc - A pointer to the SMT Context structure.
 * Out
 *	The elapsed time since last start in units of 16us.
 *
 ************************/
u_long hwt_read(struct s_smc *smc)
{
	u_short	tr ;
	u_long	is ;

	if (smc->hw.timer_activ) {
		hwt_stop(smc) ;
		tr = (u_short)((inpd(ADDR(B2_TI_VAL))/200) & 0xffff) ;

		is = GET_ISR() ;
		/* Check if timer expired (or wraparound). */
		if ((tr > smc->hw.t_start) || (is & IS_TIMINT)) {
			hwt_restart(smc) ;
			smc->hw.t_stop = smc->hw.t_start ;
		}
		else
			smc->hw.t_stop = smc->hw.t_start - tr ;
	}
<<<<<<< HEAD
void fddi_isr(struct s_smc *smc)
{
	u_long		is ;		/* ISR source */
	u_short		stu, stl ;
	SMbuf		*mb ;

#ifdef	USE_BREAK_ISR
	int	force_irq ;
#endif

#ifdef	ODI2
	if (smc->os.hwm.rx_break) {
		mac_drv_fill_rxd(smc) ;
		if (smc->hw.fp.rx_q[QUEUE_R1].rx_used > 0) {
			smc->os.hwm.rx_break = 0 ;
			process_receive(smc) ;
		}
		else {
			smc->os.hwm.detec_count = 0 ;
			smt_force_irq(smc) ;
		}
	}
#endif
	smc->os.hwm.isr_flag = TRUE ;

#ifdef	USE_BREAK_ISR
	force_irq = TRUE ;
	if (smc->os.hwm.leave_isr) {
		smc->os.hwm.leave_isr = FALSE ;
		process_receive(smc) ;
	}
#endif

	while ((is = GET_ISR() & ISR_MASK)) {
		NDD_TRACE("CH0B",is,0,0) ;
		DB_GEN("ISA = 0x%x",is,0,7) ;

		if (is & IMASK_SLOW) {
			NDD_TRACE("CH1b",is,0,0) ;
			if (is & IS_PLINT1) {	/* PLC1 */
				plc1_irq(smc) ;
			}
			if (is & IS_PLINT2) {	/* PLC2 */
				plc2_irq(smc) ;
			}
			if (is & IS_MINTR1) {	/* FORMAC+ STU1(U/L) */
				stu = inpw(FM_A(FM_ST1U)) ;
				stl = inpw(FM_A(FM_ST1L)) ;
				DB_GEN("Slow transmit complete",0,0,6) ;
				mac1_irq(smc,stu,stl) ;
			}
			if (is & IS_MINTR2) {	/* FORMAC+ STU2(U/L) */
				stu= inpw(FM_A(FM_ST2U)) ;
				stl= inpw(FM_A(FM_ST2L)) ;
				DB_GEN("Slow receive complete",0,0,6) ;
				DB_GEN("stl = %x : stu = %x",stl,stu,7) ;
				mac2_irq(smc,stu,stl) ;
			}
			if (is & IS_MINTR3) {	/* FORMAC+ STU3(U/L) */
				stu= inpw(FM_A(FM_ST3U)) ;
				stl= inpw(FM_A(FM_ST3L)) ;
				DB_GEN("FORMAC Mode Register 3",0,0,6) ;
				mac3_irq(smc,stu,stl) ;
			}
			if (is & IS_TIMINT) {	/* Timer 82C54-2 */
				timer_irq(smc) ;
#ifdef	NDIS_OS2
				force_irq_pending = 0 ;
#endif
				/*
				 * out of RxD detection
				 */
				if (++smc->os.hwm.detec_count > 4) {
					/*
					 * check out of RxD condition
					 */
					 process_receive(smc) ;
				}
			}
			if (is & IS_TOKEN) {	/* Restricted Token Monitor */
				rtm_irq(smc) ;
			}
			if (is & IS_R1_P) {	/* Parity error rx queue 1 */
				/* clear IRQ */
				outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_P) ;
				SMT_PANIC(smc,HWM_E0004,HWM_E0004_MSG) ;
			}
			if (is & IS_R1_C) {	/* Encoding error rx queue 1 */
				/* clear IRQ */
				outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_C) ;
				SMT_PANIC(smc,HWM_E0005,HWM_E0005_MSG) ;
			}
			if (is & IS_XA_C) {	/* Encoding error async tx q */
				/* clear IRQ */
				outpd(ADDR(B5_XA_CSR),CSR_IRQ_CL_C) ;
				SMT_PANIC(smc,HWM_E0006,HWM_E0006_MSG) ;
			}
			if (is & IS_XS_C) {	/* Encoding error sync tx q */
				/* clear IRQ */
				outpd(ADDR(B5_XS_CSR),CSR_IRQ_CL_C) ;
				SMT_PANIC(smc,HWM_E0007,HWM_E0007_MSG) ;
			}
		}

		/*
		 *	Fast Tx complete Async/Sync Queue (BMU service)
		 */
		if (is & (IS_XS_F|IS_XA_F)) {
			DB_GEN("Fast tx complete queue",0,0,6) ;
			/*
			 * clear IRQ, Note: no IRQ is lost, because
			 * 	we always service both queues
			 */
			outpd(ADDR(B5_XS_CSR),CSR_IRQ_CL_F) ;
			outpd(ADDR(B5_XA_CSR),CSR_IRQ_CL_F) ;
			mac_drv_clear_txd(smc) ;
			llc_restart_tx(smc) ;
		}

		/*
		 *	Fast Rx Complete (BMU service)
		 */
		if (is & IS_R1_F) {
			DB_GEN("Fast receive complete",0,0,6) ;
			/* clear IRQ */
#ifndef USE_BREAK_ISR
			outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_F) ;
			process_receive(smc) ;
#else
			process_receive(smc) ;
			if (smc->os.hwm.leave_isr) {
				force_irq = FALSE ;
			} else {
				outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_F) ;
				process_receive(smc) ;
			}
#endif
		}

#ifndef	NDIS_OS2
		while ((mb = get_llc_rx(smc))) {
			smt_to_llc(smc,mb) ;
		}
#else
		if (offDepth)
			post_proc() ;

		while (!offDepth && (mb = get_llc_rx(smc))) {
			smt_to_llc(smc,mb) ;
		}

		if (!offDepth && smc->os.hwm.rx_break) {
			process_receive(smc) ;
		}
#endif
		if (smc->q.ev_get != smc->q.ev_put) {
			NDD_TRACE("CH2a",0,0,0) ;
			ev_dispatcher(smc) ;
		}
#ifdef	NDIS_OS2
		post_proc() ;
		if (offDepth) {		/* leave fddi_isr because */
			break ;		/* indications not allowed */
		}
#endif
#ifdef	USE_BREAK_ISR
		if (smc->os.hwm.leave_isr) {
			break ;		/* leave fddi_isr */
		}
#endif

		/* NOTE: when the isr is left, no rx is pending */
	}	/* end of interrupt source polling loop */

#ifdef	USE_BREAK_ISR
	if (smc->os.hwm.leave_isr && force_irq) {
		smt_force_irq(smc) ;
	}
#endif
	smc->os.hwm.isr_flag = FALSE ;
	NDD_TRACE("CH0E",0,0,0) ;
}