+static irqreturn_t macsonic_interrupt(int irq, void *dev_id)
+{
+ irqreturn_t result;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ result = sonic_interrupt(irq, dev_id);
+ local_irq_restore(flags);
+ return result;
+}
+
+static int macsonic_open(struct net_device* dev)
+{
+ if (request_irq(dev->irq, &sonic_interrupt, IRQ_FLG_FAST, "sonic", dev)) {
+ printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq);
+ return -EAGAIN;
+ }
+ /* Under the A/UX interrupt scheme, the onboard SONIC interrupt comes
+ * in at priority level 3. However, we sometimes get the level 2 inter-
+ * rupt as well, which must prevent re-entrance of the sonic handler.
+ */
+ if (dev->irq == IRQ_AUTO_3)
+ if (request_irq(IRQ_NUBUS_9, &macsonic_interrupt, IRQ_FLG_FAST, "sonic", dev)) {
+ printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, IRQ_NUBUS_9);
+ free_irq(dev->irq, dev);
+ return -EAGAIN;
+ }
+ return sonic_open(dev);
+}
+
+static int macsonic_close(struct net_device* dev)
+{
+ int err;
+ err = sonic_close(dev);
+ free_irq(dev->irq, dev);
+ if (dev->irq == IRQ_AUTO_3)
+ free_irq(IRQ_NUBUS_9, dev);
+ return err;
+}
+
+static const struct net_device_ops macsonic_netdev_ops = {
+ .ndo_open = macsonic_open,
+ .ndo_stop = macsonic_close,
+ .ndo_start_xmit = sonic_send_packet,
+ .ndo_set_multicast_list = sonic_multicast_list,
+ .ndo_tx_timeout = sonic_tx_timeout,
+ .ndo_get_stats = sonic_get_stats,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+};
+
+static int __init macsonic_init(struct net_device *dev)