/* NEx000-clone boards have a Station Address (SA) PROM (SAPROM) in the packet *buffermemoryspace.By-the-specNE2000cloneshave0x57,0x57inbytes *0x0e,0x0foftheSAPROM,whileothersupposedNE2000clonesmustbe *detectedbytheirSAprefix. * *ReadingtheSAPROMfromaword-widecardwiththe8390setinbyte-wide *moderesultsindoubledvalues,whichcanbedetectedandcompensatedfor. * *Theprobeisalsoresponsibleforinitializingthecardandfilling *inthe'dev'and'ei_status'structures.
*/
/* Allocate net_device, dev->priv; fill in 8390 specific dev fields. */
dev = alloc_ei_netdev(); if (!dev) {
dev_err(&pdev->dev, "cannot allocate ethernet device\n"); goto err_out_free_res;
}
dev->netdev_ops = &ne2k_netdev_ops;
ei_local = netdev_priv(dev);
ei_local->msg_enable = netif_msg_init(ne2k_msg_enable, default_msg_level);
SET_NETDEV_DEV(dev, &pdev->dev);
/* Reset card. Who knows what dain-bramaged state it was left in. */
{ unsignedlong reset_start_time = jiffies;
outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
/* This looks like a horrible timing loop, but it should never *takemorethanafewcycles.
*/ while ((inb(ioaddr + EN0_ISR) & ENISR_RESET) == 0) /* Limit wait: '2' avoids jiffy roll-over. */ if (jiffies - reset_start_time > 2) {
dev_err(&pdev->dev, "Card failure (no reset ack).\n"); goto err_out_free_netdev;
} /* Ack all intr. */
outb(0xff, ioaddr + EN0_ISR);
}
/* Read the 16 bytes of station address PROM. *Wemustfirstinitializeregisters,similar *toNS8390_init(eifdev,0). *Wecan'treliablyreadtheSAPROMaddresswithoutthis. *(Ilearnedthehardway!).
*/
{ struct {unsignedchar value, offset; } program_seq[] = { /* Select page 0 */
{E8390_NODMA + E8390_PAGE0 + E8390_STOP, E8390_CMD}, /* Set word-wide access */
{0x49, EN0_DCFG}, /* Clear the count regs. */
{0x00, EN0_RCNTLO}, /* Mask completion IRQ */
{0x00, EN0_RCNTHI},
{0x00, EN0_IMR},
{0xFF, EN0_ISR}, /* 0x20 Set to monitor */
{E8390_RXOFF, EN0_RXCR}, /* 0x02 and loopback mode */
{E8390_TXOFF, EN0_TXCR},
{32, EN0_RCNTLO},
{0x00, EN0_RCNTHI}, /* DMA starting at 0x0000 */
{0x00, EN0_RSARLO},
{0x00, EN0_RSARHI},
{E8390_RREAD+E8390_START, E8390_CMD},
}; for (i = 0; i < ARRAY_SIZE(program_seq); i++)
outb(program_seq[i].value,
ioaddr + program_seq[i].offset);
}
/* Note: all PCI cards have at least 16 bit access, so we don't have *tocheckfor8bitcards.Mostcardspermit32bitaccess.
*/ if (flags & ONLY_32BIT_IO) { for (i = 0; i < 4 ; i++)
((u32 *)SA_prom)[i] = le32_to_cpu(inl(ioaddr + NE_DATAPORT));
} else for (i = 0; i < 32/* sizeof(SA_prom )*/; i++)
SA_prom[i] = inb(ioaddr + NE_DATAPORT);
/* We always set the 8390 registers for word mode. */
outb(0x49, ioaddr + EN0_DCFG);
start_page = NESM_START_PG;
/* Magic incantation sequence for full duplex on the supported cards.
*/ staticinlineint set_realtek_fdx(struct net_device *dev)
{ long ioaddr = dev->base_addr;
/* Hard reset the card. This used to pause for the same period that a *8390resetcommandrequired,butthatshouldn'tbenecessary.
*/ staticvoid ne2k_pci_reset_8390(struct net_device *dev)
{ unsignedlong reset_start_time = jiffies; struct ei_device *ei_local = netdev_priv(dev);
netif_dbg(ei_local, hw, dev, "resetting the 8390 t=%ld...\n",
jiffies);
/* This check _should_not_ be necessary, omit eventually. */ while ((inb(NE_BASE+EN0_ISR) & ENISR_RESET) == 0) if (jiffies - reset_start_time > 2) {
netdev_err(dev, "%s did not complete.\n", __func__); break;
} /* Ack intr. */
outb(ENISR_RESET, NE_BASE + EN0_ISR);
}
/* Grab the 8390 specific header. Similar to the block_input routine, but *wedon'tneedtobeconcernedwithringwrapastheheaderwillbeat *thestartofapage,soweoptimizeaccordingly.
*/
staticvoid ne2k_pci_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
{
long nic_base = dev->base_addr;
/* This *shouldn't* happen. If it does, it's the last thing you'll see
*/ if (ei_status.dmaing) {
netdev_err(dev, "DMAing conflict in %s [DMAstat:%d][irqlock:%d].\n",
__func__, ei_status.dmaing, ei_status.irqlock); return;
}
/* Block input and output, similar to the Crynwr packet driver. If you *areportingtoanewethercard,lookatthepacketdriversourceforhints. *TheNEx000doesn'tsharetheon-boardpacketmemory--youhavetoput *thepacketoutthroughthe"remoteDMA"dataportusingoutb.
*/
staticvoid ne2k_pci_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
{ long nic_base = dev->base_addr; char *buf = skb->data;
staticvoid ne2k_pci_block_output(struct net_device *dev, int count, constunsignedchar *buf, constint start_page)
{ long nic_base = NE_BASE; unsignedlong dma_start;
/* On little-endian it's always safe to round the count up for *wordwrites.
*/ if (ei_status.ne2k_flags & ONLY_32BIT_IO)
count = (count + 3) & 0xFFFC; else if (count & 0x01)
count++;
/* This *shouldn't* happen. *Ifitdoes,it'sthelastthingyou'llsee.
*/ if (ei_status.dmaing) {
netdev_err(dev, "DMAing conflict in %s [DMAstat:%d][irqlock:%d]\n",
__func__, ei_status.dmaing, ei_status.irqlock); return;
}
ei_status.dmaing |= 0x01; /* We should already be in page 0, but to be safe... */
outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
#ifdef NE_RW_BUGFIX /* Handle the read-before-write bug the same way as the *Crynwrpacketdriver--theNatSemimethoddoesn'twork. *Actuallythisdoesn'talwaysworkeither,butifyouhave *problemswithyourNEx000thisisbetterthannothing!
*/
outb(0x42, nic_base + EN0_RCNTLO);
outb(0x00, nic_base + EN0_RCNTHI);
outb(0x42, nic_base + EN0_RSARLO);
outb(0x00, nic_base + EN0_RSARHI);
outb(E8390_RREAD+E8390_START, nic_base + NE_CMD); #endif
outb(ENISR_RDC, nic_base + EN0_ISR);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.