2000-10-30 19:31:02

by Jeff Garzik

[permalink] [raw]
Subject: Re: [patch] NE2000

--- /g/g/tmp/1 Mon Oct 30 14:22:41 2000
+++ /g/g/tmp/2 Mon Oct 30 14:22:58 2000
@@ -1,60 +1,61 @@
/* Hard reset the card. This used to pause for the same period that a
8390 reset command required, but that shouldn't be necessary. */
-
-static void ne_reset_8390(struct net_device *dev)
+static void
+ne2k_pci_reset_8390(struct net_device *dev)
{
unsigned long reset_start_time = jiffies;

- if (ei_debug > 1)
- printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
+ if (debug > 1) printk("%s: Resetting the 8390 t=%ld...",
+ dev->name, jiffies);

- /* DON'T change these to inb_p/outb_p or reset will fail on clones. */
outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);

ei_status.txing = 0;
ei_status.dmaing = 0;

/* This check _should_not_ be necessary, omit eventually. */
- while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
- if (jiffies - reset_start_time > 2*HZ/100) {
- printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name);
+ while ((inb(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
+ if (jiffies - reset_start_time > 2) {
+ printk("%s: ne2k_pci_reset_8390() did not complete.\n", dev->name);
break;
}
- outb_p(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */
+ outb(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */
}

/* Grab the 8390 specific header. Similar to the block_input routine, but
we don't need to be concerned with ring wrap as the header will be at
the start of a page, so we optimize accordingly. */

-static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+static void
+ne2k_pci_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
{
- int nic_base = dev->base_addr;

- /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+ long nic_base = dev->base_addr;

- if (ei_status.dmaing)
- {
- printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr "
+ /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+ if (ei_status.dmaing) {
+ printk("%s: DMAing conflict in ne2k_pci_get_8390_hdr "
"[DMAstat:%d][irqlock:%d].\n",
dev->name, ei_status.dmaing, ei_status.irqlock);
return;
}

ei_status.dmaing |= 0x01;
- outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
- outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
- outb_p(0, nic_base + EN0_RCNTHI);
- outb_p(0, nic_base + EN0_RSARLO); /* On page boundary */
- outb_p(ring_page, nic_base + EN0_RSARHI);
- outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+ outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+ outb(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
+ outb(0, nic_base + EN0_RCNTHI);
+ outb(0, nic_base + EN0_RSARLO); /* On page boundary */
+ outb(ring_page, nic_base + EN0_RSARHI);
+ outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);

- if (ei_status.word16)
+ if (ei_status.ne2k_flags & ONLY_16BIT_IO) {
insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
- else
- insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
+ } else {
+ *(u32*)hdr = le32_to_cpu(inl(NE_BASE + NE_DATAPORT));
+ le16_to_cpus(&hdr->count);
+ }

- outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
+ outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
ei_status.dmaing &= ~0x01;
}

@@ -63,172 +64,116 @@
The NEx000 doesn't share the on-board packet memory -- you have to put
the packet out through the "remote DMA" dataport using outb. */

-static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+static void
+ne2k_pci_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
{
-#ifdef NE_SANITY_CHECK
- int xfer_count = count;
-#endif
- int nic_base = dev->base_addr;
+ long nic_base = dev->base_addr;
char *buf = skb->data;

/* This *shouldn't* happen. If it does, it's the last thing you'll see */
- if (ei_status.dmaing)
- {
- printk(KERN_EMERG "%s: DMAing conflict in ne_block_input "
+ if (ei_status.dmaing) {
+ printk("%s: DMAing conflict in ne2k_pci_block_input "
"[DMAstat:%d][irqlock:%d].\n",
dev->name, ei_status.dmaing, ei_status.irqlock);
return;
}
ei_status.dmaing |= 0x01;
- outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
- outb_p(count & 0xff, nic_base + EN0_RCNTLO);
- outb_p(count >> 8, nic_base + EN0_RCNTHI);
- outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
- outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
- outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
- if (ei_status.word16)
- {
+ if (ei_status.ne2k_flags & ONLY_32BIT_IO)
+ count = (count + 3) & 0xFFFC;
+ outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+ outb(count & 0xff, nic_base + EN0_RCNTLO);
+ outb(count >> 8, nic_base + EN0_RCNTHI);
+ outb(ring_offset & 0xff, nic_base + EN0_RSARLO);
+ outb(ring_offset >> 8, nic_base + EN0_RSARHI);
+ outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+ if (ei_status.ne2k_flags & ONLY_16BIT_IO) {
insw(NE_BASE + NE_DATAPORT,buf,count>>1);
- if (count & 0x01)
- {
+ if (count & 0x01) {
buf[count-1] = inb(NE_BASE + NE_DATAPORT);
-#ifdef NE_SANITY_CHECK
- xfer_count++;
-#endif
}
} else {
- insb(NE_BASE + NE_DATAPORT, buf, count);
+ insl(NE_BASE + NE_DATAPORT, buf, count>>2);
+ if (count & 3) {
+ buf += count & ~3;
+ if (count & 2)
+ *((u16*)buf)++ = le16_to_cpu(inw(NE_BASE + NE_DATAPORT));
+ if (count & 1)
+ *buf = inb(NE_BASE + NE_DATAPORT);
}
-
-#ifdef NE_SANITY_CHECK
- /* This was for the ALPHA version only, but enough people have
- been encountering problems so it is still here. If you see
- this message you either 1) have a slightly incompatible clone
- or 2) have noise/speed problems with your bus. */
-
- if (ei_debug > 1)
- {
- /* DMA termination address check... */
- int addr, tries = 20;
- do {
- /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
- -- it's broken for Rx on some cards! */
- int high = inb_p(nic_base + EN0_RSARHI);
- int low = inb_p(nic_base + EN0_RSARLO);
- addr = (high << 8) + low;
- if (((ring_offset + xfer_count) & 0xff) == low)
- break;
- } while (--tries > 0);
- if (tries <= 0)
- printk(KERN_WARNING "%s: RX transfer address mismatch,"
- "%#4.4x (expected) vs. %#4.4x (actual).\n",
- dev->name, ring_offset + xfer_count, addr);
}
-#endif
- outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
+
+ outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
ei_status.dmaing &= ~0x01;
}

-static void ne_block_output(struct net_device *dev, int count,
+static void
+ne2k_pci_block_output(struct net_device *dev, int count,
const unsigned char *buf, const int start_page)
{
- int nic_base = NE_BASE;
+ long nic_base = NE_BASE;
unsigned long dma_start;
-#ifdef NE_SANITY_CHECK
- int retries = 0;
-#endif

- /* Round the count up for word writes. Do we need to do this?
- What effect will an odd byte count have on the 8390?
- I should check someday. */
-
- if (ei_status.word16 && (count & 0x01))
+ /* On little-endian it's always safe to round the count up for
+ word writes. */
+ if (ei_status.ne2k_flags & ONLY_32BIT_IO)
+ count = (count + 3) & 0xFFFC;
+ else
+ if (count & 0x01)
count++;

/* This *shouldn't* happen. If it does, it's the last thing you'll see */
- if (ei_status.dmaing)
- {
- printk(KERN_EMERG "%s: DMAing conflict in ne_block_output."
+ if (ei_status.dmaing) {
+ printk("%s: DMAing conflict in ne2k_pci_block_output."
"[DMAstat:%d][irqlock:%d]\n",
dev->name, ei_status.dmaing, ei_status.irqlock);
return;
}
ei_status.dmaing |= 0x01;
/* We should already be in page 0, but to be safe... */
- outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
-
-#ifdef NE_SANITY_CHECK
-retry:
-#endif
+ outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);

#ifdef NE8390_RW_BUGFIX
/* Handle the read-before-write bug the same way as the
Crynwr packet driver -- the NatSemi method doesn't work.
Actually this doesn't always work either, but if you have
problems with your NEx000 this is better than nothing! */
-
- outb_p(0x42, nic_base + EN0_RCNTLO);
- outb_p(0x00, nic_base + EN0_RCNTHI);
- outb_p(0x42, nic_base + EN0_RSARLO);
- outb_p(0x00, nic_base + EN0_RSARHI);
- outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
- /* Make certain that the dummy read has occurred. */
- udelay(6);
+ 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_p(ENISR_RDC, nic_base + EN0_ISR);
+ outb(ENISR_RDC, nic_base + EN0_ISR);

/* Now the normal output. */
- outb_p(count & 0xff, nic_base + EN0_RCNTLO);
- outb_p(count >> 8, nic_base + EN0_RCNTHI);
- outb_p(0x00, nic_base + EN0_RSARLO);
- outb_p(start_page, nic_base + EN0_RSARHI);
-
- outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
- if (ei_status.word16) {
+ outb(count & 0xff, nic_base + EN0_RCNTLO);
+ outb(count >> 8, nic_base + EN0_RCNTHI);
+ outb(0x00, nic_base + EN0_RSARLO);
+ outb(start_page, nic_base + EN0_RSARHI);
+ outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
+ if (ei_status.ne2k_flags & ONLY_16BIT_IO) {
outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
} else {
- outsb(NE_BASE + NE_DATAPORT, buf, count);
+ outsl(NE_BASE + NE_DATAPORT, buf, count>>2);
+ if (count & 3) {
+ buf += count & ~3;
+ if (count & 2)
+ outw(cpu_to_le16(*((u16*)buf)++), NE_BASE + NE_DATAPORT);
+ }
}

dma_start = jiffies;

-#ifdef NE_SANITY_CHECK
- /* This was for the ALPHA version only, but enough people have
- been encountering problems so it is still here. */
-
- if (ei_debug > 1)
- {
- /* DMA termination address check... */
- int addr, tries = 20;
- do {
- int high = inb_p(nic_base + EN0_RSARHI);
- int low = inb_p(nic_base + EN0_RSARLO);
- addr = (high << 8) + low;
- if ((start_page << 8) + count == addr)
- break;
- } while (--tries > 0);
-
- if (tries <= 0)
- {
- printk(KERN_WARNING "%s: Tx packet transfer address mismatch,"
- "%#4.4x (expected) vs. %#4.4x (actual).\n",
- dev->name, (start_page << 8) + count, addr);
- if (retries++ == 0)
- goto retry;
- }
- }
-#endif
-
- while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
- if (jiffies - dma_start > 2*HZ/100) { /* 20ms */
- printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
- ne_reset_8390(dev);
+ while ((inb(nic_base + EN0_ISR) & ENISR_RDC) == 0)
+ if (jiffies - dma_start > 2) { /* Avoid clock roll-over. */
+ printk("%s: timeout waiting for Tx RDC.\n", dev->name);
+ ne2k_pci_reset_8390(dev);
NS8390_init(dev,1);
break;
}

- outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
+ outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
ei_status.dmaing &= ~0x01;
return;
}


Attachments:
ne2000.diff (10.65 kB)