📄 macmace.c
字号:
/* reset the chip */ mace68k_reset(dev); mp->rx_done = 0; mace68k_rxdma_reset(dev); /* * The interrupt is fixed and comes off the PSC. */ if (request_irq(dev->irq, mace68k_interrupt, 0, "68K MACE", dev)) { printk(KERN_ERR "MACE: can't get irq %d\n", dev->irq); return -EAGAIN; } /* * Ditto the DMA interrupt. */ if (request_irq(IRQ_MAC_MACE_DMA, mace68k_dma_intr, 0, "68K MACE DMA", dev)) { printk(KERN_ERR "MACE: can't get irq %d\n", IRQ_MAC_MACE_DMA); return -EAGAIN; } /* Activate the Mac DMA engine */ mp->tx_slot = 0; /* Using register set 0 */ mp->tx_count = 1; /* 1 Buffer ready for use */ mace68k_txdma_reset(dev); /* turn it on! */ mb->maccc = mp->maccc; /* enable all interrupts except receive interrupts */ mb->imr = RCVINT; return 0;}/* * Shut down the mace and its interrupt channel */ static int mace68k_close(struct net_device *dev){ struct mace68k_data *mp = (struct mace68k_data *) dev->priv; volatile struct mace *mb = mp->mace; /* disable rx and tx */ mb->maccc = 0; mb->imr = 0xff; /* disable all intrs */ /* disable rx and tx dma */ mace68k_dma_off(dev); free_irq(dev->irq, dev); free_irq(IRQ_MAC_MACE_DMA, dev); return 0;}static inline void mace68k_set_timeout(struct net_device *dev){ struct mace68k_data *mp = (struct mace68k_data *) dev->priv; unsigned long flags; save_flags(flags); cli(); if (mp->timeout_active) del_timer(&mp->tx_timeout); mp->tx_timeout.expires = jiffies + TX_TIMEOUT; mp->tx_timeout.function = mace68k_tx_timeout; mp->tx_timeout.data = (unsigned long) dev; add_timer(&mp->tx_timeout); mp->timeout_active = 1; restore_flags(flags);}/* * Transmit a frame */ static int mace68k_xmit_start(struct sk_buff *skb, struct net_device *dev){ struct mace68k_data *mp = (struct mace68k_data *) dev->priv; /* * This may need atomic types ??? */ printk("mace68k_xmit_start: mp->tx_count = %d, dev->tbusy = %d, mp->tx_ring = %p (%p)\n", mp->tx_count, dev->tbusy, mp->tx_ring, virt_to_bus(mp->tx_ring)); psc_debug_dump(); if(mp->tx_count == 0) { dev->tbusy=1; mace68k_dma_intr(IRQ_MAC_MACE_DMA, dev, NULL); return 1; } mp->tx_count--; /* * FIXME: * This is hackish. The memcpy probably isnt needed but * the rules for alignment are not known. Ideally we'd like * to just blast the skb directly to ethernet. We also don't * use the ring properly - just a one frame buffer. That * also requires cache pushes ;). */ memcpy((void *)mp->tx_ring, skb, skb->len); psc_write_long(PSC_ENETWR_ADDR + mp->tx_slot, virt_to_bus(mp->tx_ring)); psc_write_long(PSC_ENETWR_LEN + mp->tx_slot, skb->len); psc_write_word(PSC_ENETWR_CMD + mp->tx_slot, 0x9800); mp->stats.tx_packets++; mp->stats.tx_bytes+=skb->len; dev_kfree_skb(skb); return 0;}static struct net_device_stats *mace68k_stats(struct net_device *dev){ struct mace68k_data *p = (struct mace68k_data *) dev->priv; return &p->stats;}/* * CRC polynomial - used in working out multicast filter bits. */#define CRC_POLY 0xedb88320static void mace68k_set_multicast(struct net_device *dev){ struct mace68k_data *mp = (struct mace68k_data *) dev->priv; volatile struct mace *mb = mp->mace; int i, j, k, b; unsigned long crc; mp->maccc &= ~PROM; if (dev->flags & IFF_PROMISC) { mp->maccc |= PROM; } else { unsigned char multicast_filter[8]; struct dev_mc_list *dmi = dev->mc_list; if (dev->flags & IFF_ALLMULTI) { for (i = 0; i < 8; i++) multicast_filter[i] = 0xff; } else { for (i = 0; i < 8; i++) multicast_filter[i] = 0; for (i = 0; i < dev->mc_count; i++) { crc = ~0; for (j = 0; j < 6; ++j) { b = dmi->dmi_addr[j]; for (k = 0; k < 8; ++k) { if ((crc ^ b) & 1) crc = (crc >> 1) ^ CRC_POLY; else crc >>= 1; b >>= 1; } } j = crc >> 26; /* bit number in multicast_filter */ multicast_filter[j >> 3] |= 1 << (j & 7); dmi = dmi->next; } }#if 0 printk("Multicast filter :"); for (i = 0; i < 8; i++) printk("%02x ", multicast_filter[i]); printk("\n");#endif mb->iac = ADDRCHG | LOGADDR; while ((mb->iac & ADDRCHG) != 0); for (i = 0; i < 8; ++i) mb->ladrf = multicast_filter[i]; } /* reset maccc */ mb->maccc = mp->maccc;}/* * Miscellaneous interrupts are handled here. We may end up * having to bash the chip on the head for bad errors */ static void mace68k_handle_misc_intrs(struct mace68k_data *mp, int intr){ volatile struct mace *mb = mp->mace; static int mace68k_babbles, mace68k_jabbers; if (intr & MPCO) mp->stats.rx_missed_errors += 256; mp->stats.rx_missed_errors += mb->mpc; /* reading clears it */ if (intr & RNTPCO) mp->stats.rx_length_errors += 256; mp->stats.rx_length_errors += mb->rntpc; /* reading clears it */ if (intr & CERR) ++mp->stats.tx_heartbeat_errors; if (intr & BABBLE) if (mace68k_babbles++ < 4) printk(KERN_DEBUG "mace: babbling transmitter\n"); if (intr & JABBER) if (mace68k_jabbers++ < 4) printk(KERN_DEBUG "mace: jabbering transceiver\n");}/* * A transmit error has occured. (We kick the transmit side from * the DMA completion) */ static void mace68k_xmit_error(struct net_device *dev){ struct mace68k_data *mp = (struct mace68k_data *) dev->priv; volatile struct mace *mb = mp->mace; u8 xmtfs, xmtrc; xmtfs = mb->xmtfs; xmtrc = mb->xmtrc; if(xmtfs & XMTSV) { if(xmtfs & UFLO) { printk("%s: DMA underrun.\n", dev->name); mp->stats.tx_errors++; mp->stats.tx_fifo_errors++; mace68k_reset(dev); } if(xmtfs & RTRY) mp->stats.collisions++; } mark_bh(NET_BH);}/* * A receive interrupt occured. */ static void mace68k_recv_interrupt(struct net_device *dev){// struct mace68k_data *mp = (struct mace68k_data *) dev->priv;// volatile struct mace *mb = mp->mace;}/* * Process the chip interrupt */ static void mace68k_interrupt(int irq, void *dev_id, struct pt_regs *regs){ struct net_device *dev = (struct net_device *) dev_id; struct mace68k_data *mp = (struct mace68k_data *) dev->priv; volatile struct mace *mb = mp->mace; u8 ir; ir = mb->ir; mace68k_handle_misc_intrs(mp, ir); if(ir&XMTINT) mace68k_xmit_error(dev); if(ir&RCVINT) mace68k_recv_interrupt(dev);}static void mace68k_tx_timeout(unsigned long data){// struct net_device *dev = (struct net_device *) data;// struct mace68k_data *mp = (struct mace68k_data *) dev->priv;// volatile struct mace *mb = mp->mace;}/* * Handle a newly arrived frame */ static void mace_dma_rx_frame(struct net_device *dev, struct mace_frame *mf){ struct mace68k_data *mp = (struct mace68k_data *) dev->priv; struct sk_buff *skb; if(mf->status&RS_OFLO) { printk("%s: fifo overflow.\n", dev->name); mp->stats.rx_errors++; mp->stats.rx_fifo_errors++; } if(mf->status&(RS_CLSN|RS_FRAMERR|RS_FCSERR)) mp->stats.rx_errors++; if(mf->status&RS_CLSN) mp->stats.collisions++; if(mf->status&RS_FRAMERR) mp->stats.rx_frame_errors++; if(mf->status&RS_FCSERR) mp->stats.rx_crc_errors++; skb = dev_alloc_skb(mf->len+2); if(skb==NULL) { mp->stats.rx_dropped++; return; } skb_reserve(skb,2); memcpy(skb_put(skb, mf->len), mf->data, mf->len); skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); mp->stats.rx_packets++; mp->stats.rx_bytes+=mf->len;}/* * The PSC has passed us a DMA interrupt event. */ static void mace68k_dma_intr(int irq, void *dev_id, struct pt_regs *regs){ struct net_device *dev = (struct net_device *) dev_id; struct mace68k_data *mp = (struct mace68k_data *) dev->priv;#if 0 u32 psc_status; /* It seems this must be allowed to stabilise ?? */ while((psc_status=psc_read_long(0x0804))!=psc_read_long(0x0804)); /* * Was this an ethernet event ? */ if(psc_status&0x60000000) {#endif /* * Process the read queue */ u16 psc_status = psc_read_word(PSC_ENETRD_CTL); printk("mace68k_dma_intr: PSC_ENETRD_CTL = %04X\n", (uint) psc_status); if (psc_status & 0x2000) { mace68k_rxdma_reset(dev); mp->rx_done = 0; } else if (psc_status & 0x100) { int left; psc_write_word(PSC_ENETRD_CMD + mp->rx_slot, 0x1100); left=psc_read_long(PSC_ENETRD_LEN + mp->rx_slot); /* read packets */ while(mp->rx_done < left) { struct mace_frame *mf=((struct mace_frame *) mp->rx_ring)+mp->rx_done++; mace_dma_rx_frame(dev, mf); } if(left == 0) /* Out of DMA room */ { psc_load_rxdma_base(mp->rx_slot, (void *)virt_to_phys(mp->rx_ring)); mp->rx_slot^=16; mp->rx_done = 0; } else { psc_write_word(PSC_ENETRD_CMD+mp->rx_slot, 0x9800); } } /* * Process the write queue */ psc_status = psc_read_word(PSC_ENETWR_CTL); printk("mace68k_dma_intr: PSC_ENETWR_CTL = %04X\n", (uint) psc_status); /* apple's driver seems to loop over this until neither */ /* condition is true. - jmt */ if (psc_status & 0x2000) { mace68k_txdma_reset(dev); } else if (psc_status & 0x0100) { psc_write_word(PSC_ENETWR_CMD + mp->tx_slot, 0x0100); mp->tx_slot ^=16; mp->tx_count++; dev->tbusy = 0; mark_bh(NET_BH); }#if 0 }#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -