Exemplo n.º 1
0
/*!
 * \brief Watchdog interrupt control.
 *
 * \param cmd   Control command.
 *              - NUT_IRQCTL_INIT Initialize and disable interrupt.
 *              - NUT_IRQCTL_STATUS Query interrupt status.
 *              - NUT_IRQCTL_ENABLE Enable interrupt.
 *              - NUT_IRQCTL_DISABLE Disable interrupt.
 *              - NUT_IRQCTL_GETPRIO Query interrupt priority.
 *              - NUT_IRQCTL_SETPRIO Set interrupt priority.
 *              - NUT_IRQCTL_GETCOUNT Query and clear interrupt counter.
 * \param param Pointer to optional parameter.
 *
 * \return 0 on success, -1 otherwise.
 */
static int WatchdogIrqCtl(int cmd, void *param)
{
    int rc = 0;
    unsigned int *ival = (unsigned int *)param;
    int_fast8_t enabled = inr(AIC_IMR) & _BV(WDI_ID);

    /* Disable interrupt. */
    if (enabled) {
        outr(AIC_IDCR, _BV(WDI_ID));
    }

    switch(cmd) {
    case NUT_IRQCTL_INIT:
        /* Set the vector. */
        outr(AIC_SVR(WDI_ID), (unsigned int)WatchdogIrqEntry);
        /* Initialize to edge triggered with defined priority. */
        outr(AIC_SMR(WDI_ID), AIC_SRCTYPE_INT_EDGE_TRIGGERED | NUT_IRQPRI_WDI);
        /* Clear interrupt */
        outr(AIC_ICCR, _BV(WDI_ID));
        break;
    case NUT_IRQCTL_STATUS:
        if (enabled) {
            *ival |= 1;
        }
        else {
            *ival &= ~1;
        }
        break;
    case NUT_IRQCTL_ENABLE:
        enabled = 1;
        break;
    case NUT_IRQCTL_DISABLE:
        enabled = 0;
        break;
    case NUT_IRQCTL_GETPRIO:
        *ival = inr(AIC_SMR(WDI_ID)) & AIC_PRIOR;
        break;
    case NUT_IRQCTL_SETPRIO:
        outr(AIC_SMR(WDI_ID), (inr(AIC_SMR(WDI_ID)) & ~AIC_PRIOR) | *ival);
        break;
#ifdef NUT_PERFMON
    case NUT_IRQCTL_GETCOUNT:
        *ival = (unsigned int)sig_WDI.ir_count;
        sig_WDI.ir_count = 0;
        break;
#endif
    default:
        rc = -1;
        break;
    }

    /* Enable interrupt. */
    if (enabled) {
        outr(AIC_IECR, _BV(WDI_ID));
    }
    return rc;
}
Exemplo n.º 2
0
/**
 * Timer couter setup.
 *
 * This function apply to select timer couter all needed settings.
 * Every settings are stored in stepper_timers[].
 */
void stepper_tc_setup(int index, stepper_isr_t callback, struct Stepper *motor)
{
	ASSERT(index < CONFIG_TC_STEPPER_MAX_NUM);

	motor->timer = &stepper_timers[index];

	//Disable PIO controller and enable TIO function
	TIO_PIO_PDR = BV(motor->timer->tio_pin);
	TIO_PIO_ABSR = BV(motor->timer->tio_pin);

	/*
	 * Sets timer counter in waveform mode.
	 * We set as default:
	 * - Waveform mode 00 (see datasheet for more detail.)
	 * - Master clock prescaler to STEPPER_MCK_PRESCALER
	 * - Set none external event
	 * - Clear pin output on comp_reg
	 * - None effect on reg C compare
	 */
	*motor->timer->chl_mode_reg = BV(TC_WAVE);
	*motor->timer->chl_mode_reg |= motor->timer->ext_event_set;
	*motor->timer->chl_mode_reg &= ~TC_WAVSEL_MASK;
	*motor->timer->chl_mode_reg |= TC_WAVSEL_UP;
	*motor->timer->chl_mode_reg |= STEPPER_MCK_PRESCALER;
	*motor->timer->chl_mode_reg |= motor->timer->comp_effect_clear;
	*motor->timer->chl_mode_reg &= ~motor->timer->comp_effect_c_mask;

	//Reset comp_reg and C compare register
	*motor->timer->comp_reg = 0;
	*motor->timer->comp_c_reg = 0;

	//Register interrupt vector
	cpu_flags_t flags;
	IRQ_SAVE_DISABLE(flags);

	/*
	 * Warning: To guarantee a correct management of interrupt event, we must
	 * trig the interrupt on level sensitive. This becouse, we have only a common
	 * line for interrupt request, and if we have at the same time two interrupt
	 * request could be that the is service normaly but the second will never
	 *  been detected and interrupt will stay active but never serviced.
	 */
	AIC_SVR(motor->timer->timer_id) = motor->timer->isr;
	AIC_SMR(motor->timer->timer_id) = AIC_SRCTYPE_INT_LEVEL_SENSITIVE;
	AIC_IECR = BV(motor->timer->timer_id);

	// Disable interrupt on select timer counter
	stepper_tc_irq_disable(motor->timer);

	IRQ_RESTORE(flags);

	//Register callback
	motor->timer->callback = callback;
	motor->timer->motor = motor;
}
Exemplo n.º 3
0
static void __INIT__ at91_aic_init(void)
{
	int irq;

	for(irq = 0; irq < 32; irq++) {
		at91_aic_writel(AIC_SVR(irq), irq);
		at91_aic_writel(AIC_SMR(irq), (0 << 5) | 0);

		irq_assoc_intctl(irq, &at91sam926x_aic_intctrl);
		irq_set_handler(irq, irq_handle_level, 0);
	}

	//	at91_aic_writel(AIC_SPU, MAX_IRQ_NUM);
	//	at91_aic_writel(AIC_DCR, 0);

	//	at91_aic_writel(AIC_IDCR, ~0UL);
	//	at91_aic_writel(AIC_ICCR, ~0UL);
}
Exemplo n.º 4
0
int eth_init()
{
	cpu_flags_t flags;

	emac_reset();
	emac_start();

	event_initGeneric(&recv_wait);
	event_initGeneric(&send_wait);

	// Register interrupt vector
	IRQ_SAVE_DISABLE(flags);

	/* Disable all emac interrupts */
	EMAC_IDR = 0xFFFFFFFF;

#if CPU_ARM_AT91
	// TODO: define sysirq_set...
	/* Set the vector. */
	AIC_SVR(EMAC_ID) = emac_irqHandler;
	/* Initialize to edge triggered with defined priority. */
	AIC_SMR(EMAC_ID) = AIC_SRCTYPE_INT_EDGE_TRIGGERED;
	/* Clear pending interrupt */
	AIC_ICCR = BV(EMAC_ID);
	/* Enable the system IRQ */
	AIC_IECR = BV(EMAC_ID);
#else
	sysirq_setHandler(INT_EMAC, emac_irqHandler);
#endif

	/* Enable interrupts */
	EMAC_IER = EMAC_RX_INTS | EMAC_TX_INTS;

	IRQ_RESTORE(flags);

	return 0;
}
/*!
 * \brief Timer/Counter 0 interrupt control.
 *
 * \param cmd   Control command.
 *              - NUT_IRQCTL_INIT Initialize and disable interrupt.
 *              - NUT_IRQCTL_STATUS Query interrupt status.
 *              - NUT_IRQCTL_ENABLE Enable interrupt.
 *              - NUT_IRQCTL_DISABLE Disable interrupt.
 *              - NUT_IRQCTL_GETMODE Query interrupt mode.
 *              - NUT_IRQCTL_SETMODE Set interrupt mode (NUT_IRQMODE_LEVEL or NUT_IRQMODE_EDGE).
 *              - NUT_IRQCTL_GETPRIO Query interrupt priority.
 *              - NUT_IRQCTL_SETPRIO Set interrupt priority.
 *              - NUT_IRQCTL_GETCOUNT Query and clear interrupt counter.
 * \param param Pointer to optional parameter.
 *
 * \return 0 on success, -1 otherwise.
 */
static int TimerCounter0IrqCtl(int cmd, void *param)
{
    int rc = 0;
    unsigned int *ival = (unsigned int *)param;
    int_fast8_t enabled = inr(AIC_IMR) & _BV(TC0_ID);

    /* Disable interrupt. */
    if (enabled) {
        outr(AIC_IDCR, _BV(TC0_ID));
    }

    switch(cmd) {
    case NUT_IRQCTL_INIT:
        /* Set the vector. */
        outr(AIC_SVR(TC0_ID), (unsigned int)TimerCounter0IrqEntry);
        /* Initialize to edge triggered with defined priority. */
        outr(AIC_SMR(TC0_ID), AIC_SRCTYPE_INT_EDGE_TRIGGERED | NUT_IRQPRI_TC0);
        /* Clear interrupt */
        outr(AIC_ICCR, _BV(TC0_ID));
        break;
    case NUT_IRQCTL_STATUS:
        if (enabled) {
            *ival |= 1;
        }
        else {
            *ival &= ~1;
        }
        break;
    case NUT_IRQCTL_ENABLE:
        enabled = 1;
        break;
    case NUT_IRQCTL_DISABLE:
        enabled = 0;
        break;
    case NUT_IRQCTL_GETMODE:
        {
            unsigned int val = inr(AIC_SMR(TC0_ID)) & AIC_SRCTYPE;
            if (val == AIC_SRCTYPE_INT_LEVEL_SENSITIVE || val == AIC_SRCTYPE_EXT_HIGH_LEVEL) {
                *ival = NUT_IRQMODE_LEVEL;
            } else  {
                *ival = NUT_IRQMODE_EDGE;
            }
        }
        break;
    case NUT_IRQCTL_SETMODE:
        if (*ival == NUT_IRQMODE_LEVEL) {
            outr(AIC_SMR(TC0_ID), (inr(AIC_SMR(TC0_ID)) & ~AIC_SRCTYPE) | AIC_SRCTYPE_INT_LEVEL_SENSITIVE);
        } else if (*ival == NUT_IRQMODE_EDGE) {
            outr(AIC_SMR(TC0_ID), (inr(AIC_SMR(TC0_ID)) & ~AIC_SRCTYPE) | AIC_SRCTYPE_INT_EDGE_TRIGGERED);
        } else  {
            rc = -1;
        }
        break;
    case NUT_IRQCTL_GETPRIO:
        *ival = inr(AIC_SMR(TC0_ID)) & AIC_PRIOR;
        break;
    case NUT_IRQCTL_SETPRIO:
        outr(AIC_SMR(TC0_ID), (inr(AIC_SMR(TC0_ID)) & ~AIC_PRIOR) | *ival);
        break;
#ifdef NUT_PERFMON
    case NUT_IRQCTL_GETCOUNT:
        *ival = (unsigned int)sig_TC0.ir_count;
        sig_TC0.ir_count = 0;
        break;
#endif
    default:
        rc = -1;
        break;
    }

    /* Enable interrupt. */
    if (enabled) {
        outr(AIC_IECR, _BV(TC0_ID));
    }
    return rc;
}
/*!
 * \brief Initialize system timer.
 *
 * This function is automatically called by Nut/OS
 * during system initialization.
 *
 * Nut/OS uses on-chip timer 0 for its timer services.
 * Applications should not modify any registers of this
 * timer, but make use of the Nut/OS timer API. Timer 1
 * and timer 2 are available to applications.
 */
void NutRegisterTimer(void (*handler) (void *))
{
    os_handler = handler;

#if defined(MCU_AT91R40008)

    /* Disable the Clock Counter */
    outr(TC0_CCR, TC_CLKDIS);
    /* Disable all interrupts */
    outr(TC0_IDR, 0xFFFFFFFF);
    /* Clear the status register. */
    dummy = inr(TC0_SR);
    /* Select divider and compare trigger */
    outr(TC0_CMR, TC_CLKS_MCK32 | TC_CPCTRG);
    /* Enable the Clock counter */
    outr(TC0_CCR, TC_CLKEN);
    /* Validate the RC compare interrupt */
    outr(TC0_IER, TC_CPCS);

    /* Disable timer 0 interrupts. */
    outr(AIC_IDCR, _BV(TC0_ID));
    /* Set the TC0 IRQ handler address */
    outr(AIC_SVR(4), (unsigned int)Timer0Entry);
    /* Set the trigg and priority for timer 0 interrupt */
    /* Level 7 is highest, level 0 lowest. */
    outr(AIC_SMR(4), (AIC_SRCTYPE_INT_LEVEL_SENSITIVE | 0x4));
    /* Clear timer 0 interrupt */
    outr(AIC_ICCR, _BV(TC0_ID));
    /* Enable timer 0 interrupts */
    outr(AIC_IECR, _BV(TC0_ID));

    /* Set compare value for 1 ms. */
    outr(TC0_RC, 0x80F);
    /* Software trigger starts the clock. */
    outr(TC0_CCR, TC_SWTRG);

#elif defined(MCU_S3C4510B)

    INT_DISABLE(IRQ_TIMER);
    CSR_WRITE(TCNT0, 0);
    CSR_WRITE(TDATA0, CLOCK_TICK_RATE);
    CSR_WRITE(TMOD, TMOD_TIMER0_VAL);

    CLEAR_PEND_INT(IRQ_TIMER);

    NutRegisterIrqHandler(
        &InterruptHandlers[IRQ_TIMER], handler, 0);

    INT_ENABLE(IRQ_TIMER);

#elif defined(MCU_GBA)

    /* Disable master interrupt. */
    outw(REG_IME, 0);

    /* Set global interrupt vector. */
    NutRegisterIrqHandler(&sig_TMR3, Timer3Entry, 0);

    /* Enable timer and timer interrupts. */
    outdw(REG_TMR3CNT, TMR_IRQ_ENA | TMR_ENA | 48756);

    /* Enable timer 3 interrupts. */
    outw(REG_IE, inw(REG_IE) | INT_TMR3);

    /* Enable master interrupt. */
    outw(REG_IME, 1);

#else
#warning "MCU not defined"
#endif
}
Exemplo n.º 7
0
/*!
 * \brief External interrupt 0 control.
 *
 * \param cmd   Control command.
 *              - NUT_IRQCTL_INIT Initialize and disable interrupt.
 *              - NUT_IRQCTL_STATUS Query interrupt status.
 *              - NUT_IRQCTL_ENABLE Enable interrupt.
 *              - NUT_IRQCTL_DISABLE Disable interrupt.
 *              - NUT_IRQCTL_GETPRIO Query interrupt priority.
 *              - NUT_IRQCTL_SETPRIO Set interrupt priority.
 *              - NUT_IRQCTL_GETCOUNT Query and clear interrupt counter.
 * \param param Pointer to optional parameter.
 *
 * \return 0 on success, -1 otherwise.
 */
static int Interrupt0Ctl(int cmd, void *param)
{
    int rc = 0;
    unsigned int *ival = (unsigned int *)param;
    int_fast8_t enabled = inr(AIC_IMR) & _BV(IRQ0_ID);

    /* Disable interrupt. */
    if (enabled) {
        outr(AIC_IDCR, _BV(IRQ0_ID));
    }

    switch(cmd) {
    case NUT_IRQCTL_INIT:
        /* Set the vector. */
        outr(AIC_SVR(IRQ0_ID), (unsigned int)Interrupt0Entry);
        /* Initialize to edge triggered with defined priority. */
        outr(AIC_SMR(IRQ0_ID), AIC_SRCTYPE_EXT_NEGATIVE_EDGE | NUT_IRQPRI_IRQ0);
        /* Clear interrupt */
        outr(AIC_ICCR, _BV(IRQ0_ID));
        break;
    case NUT_IRQCTL_STATUS:
        if (enabled) {
            *ival |= 1;
        }
        else {
            *ival &= ~1;
        }
        break;
    case NUT_IRQCTL_ENABLE:
        enabled = 1;
        break;
    case NUT_IRQCTL_DISABLE:
        enabled = 0;
        break;
    case NUT_IRQCTL_GETMODE:
        {
            unsigned int val = inr(AIC_SMR(IRQ0_ID)) & AIC_SRCTYPE;
            if (val == AIC_SRCTYPE_EXT_LOW_LEVEL) {
                *ival = NUT_IRQMODE_LOWLEVEL;
            } else if (val == AIC_SRCTYPE_EXT_HIGH_LEVEL) {
                *ival = NUT_IRQMODE_HIGHLEVEL;
            } else if (val == AIC_SRCTYPE_EXT_POSITIVE_EDGE) {
                *ival = NUT_IRQMODE_RISINGEDGE;
            } else  {
                *ival = NUT_IRQMODE_FALLINGEDGE;
            }
        }
        break;
    case NUT_IRQCTL_SETMODE:
        if (*ival == NUT_IRQMODE_LOWLEVEL) {
            outr(AIC_SMR(IRQ0_ID), (inr(AIC_SMR(IRQ0_ID)) & ~AIC_SRCTYPE) | AIC_SRCTYPE_EXT_LOW_LEVEL);
        } else if (*ival == NUT_IRQMODE_HIGHLEVEL) {
            outr(AIC_SMR(IRQ0_ID), (inr(AIC_SMR(IRQ0_ID)) & ~AIC_SRCTYPE) | AIC_SRCTYPE_EXT_HIGH_LEVEL);
        } else if (*ival == NUT_IRQMODE_FALLINGEDGE) {
            outr(AIC_SMR(IRQ0_ID), (inr(AIC_SMR(IRQ0_ID)) & ~AIC_SRCTYPE) | AIC_SRCTYPE_EXT_NEGATIVE_EDGE);
        } else  if (*ival == NUT_IRQMODE_RISINGEDGE) {
            outr(AIC_SMR(IRQ0_ID), (inr(AIC_SMR(IRQ0_ID)) & ~AIC_SRCTYPE) | AIC_SRCTYPE_EXT_POSITIVE_EDGE);
        } else  {
            rc = -1;
        }
        break;
    case NUT_IRQCTL_GETPRIO:
        *ival = inr(AIC_SMR(IRQ0_ID)) & AIC_PRIOR;
        break;
    case NUT_IRQCTL_SETPRIO:
        outr(AIC_SMR(IRQ0_ID), (inr(AIC_SMR(IRQ0_ID)) & ~AIC_PRIOR) | *ival);
        break;
#ifdef NUT_PERFMON
    case NUT_IRQCTL_GETCOUNT:
        *ival = (unsigned int)sig_INTERRUPT0.ir_count;
        sig_INTERRUPT0.ir_count = 0;
        break;
#endif
    default:
        rc = -1;
        break;
    }

    /* Enable interrupt. */
    if (enabled) {
        outr(AIC_IECR, _BV(IRQ0_ID));
#if defined(PMC_PCER)
        outr(PMC_PCER, _BV(IRQ0_ID));
#endif
    }
    return rc;
}
Exemplo n.º 8
0
/* Open/initialize the board.  This is called (in the current kernel)
   sometime after booting when the 'ifconfig' program is run.

   This routine should set everything up anew at each open, even
   registers that "should" only need to be set once at boot, so that
   there is non-reboot way to recover if something goes wrong.
   */
static int
net_open(struct net_device *dev)
{
	struct net_local *lp = (struct net_local *)dev->priv;
	int result = 0;

	write_irq(dev, lp->chip_type, 0);

/*	irq2dev_map[0] = dev;   */
	writereg(dev, PP_BusCTL, 0); /* ints off! */

#ifdef CONFIG_UCSIMM
	*(volatile unsigned short *)0xfffff302 |= 0x0080; /* +ve pol irq */
	dev->irq = IRQ5_IRQ_NUM;
        if (request_irq(dev->irq | IRQ_MACHSPEC,
                        cs8900_interrupt,
                        IRQ_FLG_STD,
                        "CrystalLAN_cs8900a", NULL))
                panic("Unable to attach cs8900 intr\n");
#endif

#ifdef CONFIG_ARCH_ATMEL
	/* Set IRQ1 with high level sensitive & priority level 6. */
	*(volatile unsigned int *) AIC_SMR(IRQ_IRQ1) = 0x46;

	/* We use IRQ_IRQ1 for the network interrupt */
	dev->irq = IRQ_IRQ1;
        if (request_irq(dev->irq,
                        cs8900_interrupt,
                        IRQ_FLG_STD,
                        "CrystalLAN_cs8900a", NULL))
                panic("Unable to attach cs8900 intr\n");                        
#endif

#if defined (CONFIG_BOARD_UCLINKII)     || \
    defined (CONFIG_BOARD_EVS3C4530LII) || \
    defined (CONFIG_BOARD_EVS3C4530HEI)
	
	*(volatile unsigned int *)IOPCON0 |= (xINTREQ0_ENABLE | xINTREQ0_ACT_HI);
	dev->irq = _IRQ0;
	if (request_irq (dev->irq, cs8900_interrupt, 0,
			 "Crystal_CS8900", dev))
 	  panic("Unable to attach cs8900 intr\n");
#endif

#ifdef CONFIG_ALMA_ANS
	/* We use positive polarity IRQ3 as a network interrupt */
	ICR |= ICR_POL3;
	dev->irq = IRQ3_IRQ_NUM;
	if (request_irq(dev->irq | IRQ_MACHSPEC,
                        cs8900_interrupt,
                        IRQ_FLG_STD,
                        "CrystalLAN_cs8900a", NULL))
                panic("Unable to attach cs8900 intr\n");                        
#endif

	/* set the Ethernet address */
	set_mac_address(dev, dev->dev_addr);

	/* Set the LineCTL */
	lp->linectl = 0;

        /* check to make sure that they have the "right" hardware available */
	switch(lp->adapter_cnf & A_CNF_MEDIA_TYPE) {
	case A_CNF_MEDIA_10B_T:
		result = lp->adapter_cnf & A_CNF_10B_T;
		break;
	case A_CNF_MEDIA_AUI:
		result = lp->adapter_cnf & A_CNF_AUI;
		break;
	case A_CNF_MEDIA_10B_2:
		result = lp->adapter_cnf & A_CNF_10B_2;
		break;
        default:
		result = lp->adapter_cnf & 
		         (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2);
        }
        if (!result) {
                printk("%s: EEPROM is configured for unavailable media\n", dev->name);
        release_irq:
                writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) & ~(SERIAL_TX_ON | SERIAL_RX_ON));
		/* so subsequent opens don't fail we release the IRQ ...MaTed--- */
		free_irq( dev->irq, dev);
/*                irq2dev_map[dev->irq] = 0;    */
		return -EAGAIN;
	}

        /* set the hardware to the configured choice */
	switch(lp->adapter_cnf & A_CNF_MEDIA_TYPE) {
	case A_CNF_MEDIA_10B_T:
                result = detect_tp(dev);
                if (!result) { 
		  printk("%s: 10Base-T (RJ-45) has no cable\n", dev->name);
		  if (lp->auto_neg_cnf & IMM_BIT) { /* check "ignore missing media" bit */
		    printk("%s: but ignore the fact.\n", dev->name);
		    result = A_CNF_MEDIA_10B_T; /* Yes! I don't care if I see a link pulse */
		  }
                }
		break;
	case A_CNF_MEDIA_AUI:
	  printk("AUI is not supported by uCcs8900\n");
		break;
	case A_CNF_MEDIA_10B_2:
	  printk("10Base2 is not supported by uCcs8900\n");
		break;
	case A_CNF_MEDIA_AUTO:
		writereg(dev, PP_LineCTL, lp->linectl | AUTO_AUI_10BASET);
		if (lp->adapter_cnf & A_CNF_10B_T)
			if ((result = detect_tp(dev)) != 0)
				break;

		printk("%s: no media detected\n", dev->name);
                goto release_irq;
	}
	switch(result) {
	case 0: printk("%s: no network cable attached to configured media\n", dev->name);
                goto release_irq;
	case A_CNF_MEDIA_10B_T: printk("%s: using 10Base-T (RJ-45)\n", dev->name);break;
	case A_CNF_MEDIA_AUI:   printk("%s: using 10Base-5 (AUI)\n", dev->name);break;
	case A_CNF_MEDIA_10B_2: printk("%s: using 10Base-2 (BNC)\n", dev->name);break;
	default: printk("%s: unexpected result was %x\n", dev->name, result); goto release_irq;
	}

	/* Turn on both receive and transmit operations */
	writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON);

	/* Receive only error free packets addressed to this card */
	lp->rx_mode = 0;
	writereg(dev, PP_RxCTL, DEF_RX_ACCEPT);

	lp->curr_rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL;
	if (lp->isa_config & STREAM_TRANSFER)
		lp->curr_rx_cfg |= RX_STREAM_ENBL;

	writereg(dev, PP_RxCFG, lp->curr_rx_cfg);

	writereg(dev, PP_TxCFG, TX_LOST_CRS_ENBL | TX_SQE_ERROR_ENBL | TX_OK_ENBL |
	       TX_LATE_COL_ENBL | TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL);

	writereg(dev, PP_BufCFG, READY_FOR_TX_ENBL | RX_MISS_COUNT_OVRFLOW_ENBL |
		 TX_COL_COUNT_OVRFLOW_ENBL | TX_UNDERRUN_ENBL);

	/* now that we've got our act together, enable everything */
	writereg(dev, PP_BusCTL, ENABLE_IRQ );
	
	netif_start_queue(dev);
	
	return 0;
}