📄 xircom_cb.c
字号:
val = inl(card->io_port + CSR6); /* Operation mode */ /* If the "active" bit is set and the receiver is already active, no need to do the expensive thing */ if ((val&(1<<13)) && (transmit_active(card))) return; val = val & ~(1 << 13); /* disable the transmitter */ outl(val, card->io_port + CSR6); counter = 10; while (counter > 0) { if (!transmit_active(card)) break; /* wait a while */ udelay(50); counter--; if (counter <= 0) printk(KERN_ERR "xircom_cb: Transmitter failed to deactivate\n"); } /* enable the transmitter */ val = inl(card->io_port + CSR6); /* Operation mode */ val = val | (1 << 13); /* enable the transmitter */ outl(val, card->io_port + CSR6); /* now wait for the card to activate again */ counter = 10; while (counter > 0) { if (transmit_active(card)) break; /* wait a while */ udelay(50); counter--; if (counter <= 0) printk(KERN_ERR "xircom_cb: Transmitter failed to re-activate\n"); } leave("activate_transmitter");}/*deactivate_transmitter disables the transmitter on the card.To achieve this this code disables the transmitter first; then it waits for the transmitter to become inactive.must be called with the lock held and interrupts disabled.*/static void deactivate_transmitter(struct xircom_private *card){ unsigned int val; int counter; enter("deactivate_transmitter"); val = inl(card->io_port + CSR6); /* Operation mode */ val = val & ~2; /* disable the transmitter */ outl(val, card->io_port + CSR6); counter = 20; while (counter > 0) { if (!transmit_active(card)) break; /* wait a while */ udelay(50); counter--; if (counter <= 0) printk(KERN_ERR "xircom_cb: Transmitter failed to deactivate\n"); } leave("deactivate_transmitter");}/*enable_transmit_interrupt enables the transmit interruptmust be called with the lock held and interrupts disabled.*/static void enable_transmit_interrupt(struct xircom_private *card){ unsigned int val; enter("enable_transmit_interrupt"); val = inl(card->io_port + CSR7); /* Interrupt enable register */ val |= 1; /* enable the transmit interrupt */ outl(val, card->io_port + CSR7); leave("enable_transmit_interrupt");}/*enable_receive_interrupt enables the receive interruptmust be called with the lock held and interrupts disabled.*/static void enable_receive_interrupt(struct xircom_private *card){ unsigned int val; enter("enable_receive_interrupt"); val = inl(card->io_port + CSR7); /* Interrupt enable register */ val = val | (1 << 6); /* enable the receive interrupt */ outl(val, card->io_port + CSR7); leave("enable_receive_interrupt");}/*enable_link_interrupt enables the link status change interruptmust be called with the lock held and interrupts disabled.*/static void enable_link_interrupt(struct xircom_private *card){ unsigned int val; enter("enable_link_interrupt"); val = inl(card->io_port + CSR7); /* Interrupt enable register */ val = val | (1 << 27); /* enable the link status chage interrupt */ outl(val, card->io_port + CSR7); leave("enable_link_interrupt");}/*disable_all_interrupts disables all interruptsmust be called with the lock held and interrupts disabled.*/static void disable_all_interrupts(struct xircom_private *card){ unsigned int val; enter("enable_all_interrupts"); val = 0; /* disable all interrupts */ outl(val, card->io_port + CSR7); leave("disable_all_interrupts");}/*enable_common_interrupts enables several weird interruptsmust be called with the lock held and interrupts disabled.*/static void enable_common_interrupts(struct xircom_private *card){ unsigned int val; enter("enable_link_interrupt"); val = inl(card->io_port + CSR7); /* Interrupt enable register */ val |= (1<<16); /* Normal Interrupt Summary */ val |= (1<<15); /* Abnormal Interrupt Summary */ val |= (1<<13); /* Fatal bus error */ val |= (1<<8); /* Receive Process Stopped */ val |= (1<<7); /* Receive Buffer Unavailable */ val |= (1<<5); /* Transmit Underflow */ val |= (1<<2); /* Transmit Buffer Unavailable */ val |= (1<<1); /* Transmit Process Stopped */ outl(val, card->io_port + CSR7); leave("enable_link_interrupt");}/*enable_promisc starts promisc modemust be called with the lock held and interrupts disabled.*/static int enable_promisc(struct xircom_private *card){ unsigned int val; enter("enable_promisc"); val = inl(card->io_port + CSR6); val = val | (1 << 6); outl(val, card->io_port + CSR6); leave("enable_promisc"); return 1;}/* link_status() checks the the links status and will return 0 for no link, 10 for 10mbit link and 100 for.. guess what.Must be called in locked state with interrupts disabled*/static int link_status(struct xircom_private *card){ unsigned int val; enter("link_status"); val = inb(card->io_port + CSR12); if (!(val&(1<<2))) /* bit 2 is 0 for 10mbit link, 1 for not an 10mbit link */ return 10; if (!(val&(1<<1))) /* bit 1 is 0 for 100mbit link, 1 for not an 100mbit link */ return 100; /* If we get here -> no link at all */ leave("link_status"); return 0;}/* read_mac_address() reads the MAC address from the NIC and stores it in the "dev" structure. This function will take the spinlock itself and can, as a result, not be called with the lock helt. */static void read_mac_address(struct xircom_private *card){ unsigned char j, tuple, link, data_id, data_count; unsigned long flags; int i; enter("read_mac_address"); spin_lock_irqsave(&card->lock, flags); outl(1 << 12, card->io_port + CSR9); /* enable boot rom access */ for (i = 0x100; i < 0x1f7; i += link + 2) { outl(i, card->io_port + CSR10); tuple = inl(card->io_port + CSR9) & 0xff; outl(i + 1, card->io_port + CSR10); link = inl(card->io_port + CSR9) & 0xff; outl(i + 2, card->io_port + CSR10); data_id = inl(card->io_port + CSR9) & 0xff; outl(i + 3, card->io_port + CSR10); data_count = inl(card->io_port + CSR9) & 0xff; if ((tuple == 0x22) && (data_id == 0x04) && (data_count == 0x06)) { /* * This is it. We have the data we want. */ for (j = 0; j < 6; j++) { outl(i + j + 4, card->io_port + CSR10); card->dev->dev_addr[j] = inl(card->io_port + CSR9) & 0xff; } break; } else if (link == 0) { break; } } spin_unlock_irqrestore(&card->lock, flags);#ifdef DEBUG for (i = 0; i < 6; i++) printk("%c%2.2X", i ? ':' : ' ', card->dev->dev_addr[i]); printk("\n");#endif leave("read_mac_address");}/* transceiver_voodoo() enables the external UTP plug thingy. it's called voodoo as I stole this code and cannot cross-reference it with the specification. */static void transceiver_voodoo(struct xircom_private *card){ unsigned long flags; enter("transceiver_voodoo"); /* disable all powermanagement */ pci_write_config_dword(card->pdev, PCI_POWERMGMT, 0x0000); setup_descriptors(card); spin_lock_irqsave(&card->lock, flags); outl(0x0008, card->io_port + CSR15); udelay(25); outl(0xa8050000, card->io_port + CSR15); udelay(25); outl(0xa00f0000, card->io_port + CSR15); udelay(25); spin_unlock_irqrestore(&card->lock, flags); netif_start_queue(card->dev); leave("transceiver_voodoo");}static void xircom_up(struct xircom_private *card){ unsigned long flags; int i; enter("xircom_up"); /* disable all powermanagement */ pci_write_config_dword(card->pdev, PCI_POWERMGMT, 0x0000); setup_descriptors(card); spin_lock_irqsave(&card->lock, flags); enable_link_interrupt(card); enable_transmit_interrupt(card); enable_receive_interrupt(card); enable_common_interrupts(card); enable_promisc(card); /* The card can have received packets already, read them away now */ for (i=0;i<NUMDESCRIPTORS;i++) investigate_read_descriptor(card->dev,card,i,bufferoffsets[i]); spin_unlock_irqrestore(&card->lock, flags); trigger_receive(card); trigger_transmit(card); netif_start_queue(card->dev); leave("xircom_up");}/* Bufferoffset is in BYTES */static void investigate_read_descriptor(struct net_device *dev,struct xircom_private *card, int descnr, unsigned int bufferoffset){ int status; enter("investigate_read_descriptor"); status = card->rx_buffer[4*descnr]; if ((status > 0)) { /* packet received */ /* TODO: discard error packets */ short pkt_len = ((status >> 16) & 0x7ff) - 4; /* minus 4, we don't want the CRC */ struct sk_buff *skb; if (pkt_len > 1518) { printk(KERN_ERR "xircom_cb: Packet length %i is bogus \n",pkt_len); pkt_len = 1518; } skb = dev_alloc_skb(pkt_len + 2); if (skb == NULL) { card->stats.rx_dropped++; goto out; } skb->dev = dev; skb_reserve(skb, 2); eth_copy_and_sum(skb, (unsigned char*)&card->rx_buffer[bufferoffset / 4], pkt_len, 0); skb_put(skb, pkt_len); skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); dev->last_rx = jiffies; card->stats.rx_packets++; card->stats.rx_bytes += pkt_len; out: /* give the buffer back to the card */ card->rx_buffer[4*descnr] = 0x80000000; trigger_receive(card); } leave("investigate_read_descriptor");}/* Bufferoffset is in BYTES */static void investigate_write_descriptor(struct net_device *dev, struct xircom_private *card, int descnr, unsigned int bufferoffset){ int status; enter("investigate_write_descriptor"); status = card->tx_buffer[4*descnr];#if 0 if (status & 0x8000) { /* Major error */ printk(KERN_ERR "Major transmit error status %x \n", status); card->tx_buffer[4*descnr] = 0; netif_wake_queue (dev); }#endif if (status > 0) { /* bit 31 is 0 when done */ if (card->tx_skb[descnr]!=NULL) { card->stats.tx_bytes += card->tx_skb[descnr]->len; dev_kfree_skb_irq(card->tx_skb[descnr]); } card->tx_skb[descnr] = NULL; /* Bit 8 in the status field is 1 if there was a collision */ if (status&(1<<8)) card->stats.collisions++; card->tx_buffer[4*descnr] = 0; /* descriptor is free again */ netif_wake_queue (dev); card->stats.tx_packets++; } leave("investigate_write_descriptor"); }static int __init xircom_init(void){ pci_register_driver(&xircom_ops); return 0;}static void __exit xircom_exit(void){ pci_unregister_driver(&xircom_ops);} module_init(xircom_init) module_exit(xircom_exit)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -