diff --git a/src/arch/i386/drivers/net/undinet.c b/src/arch/i386/drivers/net/undinet.c index e6c08464..7571574d 100644 --- a/src/arch/i386/drivers/net/undinet.c +++ b/src/arch/i386/drivers/net/undinet.c @@ -43,6 +43,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); /** An UNDI NIC */ struct undi_nic { + /** Device supports IRQs */ + int irq_supported; /** Assigned IRQ number */ unsigned int irq; /** Currently processing ISR */ @@ -251,8 +253,10 @@ static void undinet_poll ( struct net_device *netdev ) { int rc; if ( ! undinic->isr_processing ) { - /* Do nothing unless ISR has been triggered */ - if ( ! undinet_isr_triggered() ) { + /* If interrupts are supported, then do nothing unless + * the ISR has been triggered. + */ + if ( undinic->irq_supported && ( ! undinet_isr_triggered() ) ){ /* Allow interrupt to occur */ __asm__ __volatile__ ( REAL_CODE ( "sti\n\t" "nop\n\t" @@ -357,10 +361,12 @@ static int undinet_open ( struct net_device *netdev ) { struct s_PXENV_UNDI_OPEN undi_open; int rc; - /* Hook interrupt service routine and enable interrupt */ - undinet_hook_isr ( undinic->irq ); - enable_irq ( undinic->irq ); - send_eoi ( undinic->irq ); + /* Hook interrupt service routine and enable interrupt if supported */ + if ( undinic->irq_supported ) { + undinet_hook_isr ( undinic->irq ); + enable_irq ( undinic->irq ); + send_eoi ( undinic->irq ); + } /* Set station address. Required for some PXE stacks; will * spuriously fail on others. Ignore failures. We only ever @@ -425,9 +431,11 @@ static void undinet_close ( struct net_device *netdev ) { pxeparent_call ( undinet_entry, PXENV_UNDI_CLOSE, &undi_close, sizeof ( undi_close ) ); - /* Disable interrupt and unhook ISR */ - disable_irq ( undinic->irq ); - undinet_unhook_isr ( undinic->irq ); + /* Disable interrupt and unhook ISR if supported */ + if ( undinic->irq_supported ) { + disable_irq ( undinic->irq ); + undinet_unhook_isr ( undinic->irq ); + } DBGC ( undinic, "UNDINIC %p closed\n", undinic ); } @@ -524,13 +532,8 @@ int undinet_probe ( struct undi_device *undi ) { goto err_undi_get_information; memcpy ( netdev->hw_addr, undi_info.PermNodeAddress, ETH_ALEN ); undinic->irq = undi_info.IntNumber; - if ( undinic->irq > IRQ_MAX ) { - DBGC ( undinic, "UNDINIC %p invalid IRQ %d\n", - undinic, undinic->irq ); - goto err_bad_irq; - } - DBGC ( undinic, "UNDINIC %p is %s on IRQ %d\n", - undinic, eth_ntoa ( netdev->hw_addr ), undinic->irq ); + DBGC ( undinic, "UNDINIC %p has MAC address %s\n", + undinic, eth_ntoa ( netdev->hw_addr ) ); /* Get interface information */ memset ( &undi_iface, 0, sizeof ( undi_iface ) ); @@ -541,6 +544,17 @@ int undinet_probe ( struct undi_device *undi ) { DBGC ( undinic, "UNDINIC %p has type %s, speed %d, flags %08x\n", undinic, undi_iface.IfaceType, undi_iface.LinkSpeed, undi_iface.ServiceFlags ); + if ( undi_iface.ServiceFlags & SUPPORTED_IRQ ) { + if ( undinic->irq > IRQ_MAX ) { + DBGC ( undinic, "UNDINIC %p has invalid IRQ %d\n", + undinic, undinic->irq ); + rc = -EINVAL; + goto err_bad_irq; + } + undinic->irq_supported = 1; + DBGC ( undinic, "UNDINIC %p uses IRQ %d\n", + undinic, undinic->irq ); + } if ( strncmp ( ( ( char * ) undi_iface.IfaceType ), "Etherboot", sizeof ( undi_iface.IfaceType ) ) == 0 ) { DBGC ( undinic, "UNDINIC %p Etherboot 5.4 workaround enabled\n", @@ -559,8 +573,8 @@ int undinet_probe ( struct undi_device *undi ) { return 0; err_register: - err_undi_get_iface_info: err_bad_irq: + err_undi_get_iface_info: err_undi_get_information: err_undi_initialize: /* Shut down UNDI stack */