Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 35 additions & 22 deletions tlvc/arch/i86/drivers/net/ne2k-asm.S
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
//
//-----------------------------------------------------------------------------

#include <linuxmt/config.h>
#include <arch/asm-offsets.h>
#include <linuxmt/netstat.h>
#include "netbuf.h"
Expand Down Expand Up @@ -91,6 +92,7 @@ USE_AUI = ETHF_USE_AUI
.data
.extern current
.extern net_port // io-port base
.extern running_qemu

.global ne2k_next_pk
ne2k_next_pk:
Expand All @@ -107,6 +109,10 @@ ne2k_flags:
ne2k_rx_last: // PSTOP - buffer upper bound
.byte rx_last_16 // default to 16K

.global ne2k_imask
ne2k_imask: // current interrupt mask
.byte

.text

//-----------------------------------------------------------------------------
Expand All @@ -130,7 +136,7 @@ ne2k_addr_set:

// load MAC address

mov net_port,%dx
//mov net_port,%dx // Already set
add $io_ne2k_unicast,%dx
mov $6,%cx
cld
Expand Down Expand Up @@ -199,7 +205,7 @@ dma_write:

inc %cx // make byte count even
and $0xfffe,%cx
cli // Mandatory
//cli // Mandatory
call dma_init

// start DMA write
Expand Down Expand Up @@ -253,7 +259,7 @@ check_dma_w:
//mov $0x40,%al // clear DMA intr bit in ISR
out %al,%dx

sti // Mandatory
//sti // Mandatory
pop %cx
ret

Expand All @@ -276,7 +282,7 @@ dma_read:
inc %cx // make byte count even
and $0xfffe,%cx

cli // Experimental - disable INTR
//cli // Experimental - disable INTR
call dma_init

mov %ds,%bx
Expand Down Expand Up @@ -312,17 +318,18 @@ word_loop:
stosw
loop word_loop
3:
mov net_port,%dx
add $io_ne2k_int_stat,%dx
// PROABLY NOT NEEDED
//mov net_port,%dx
//add $io_ne2k_int_stat,%dx
check_dma_r:
in %dx,%al
test $0x40,%al // dma done?
jz check_dma_r
//in %dx,%al
//test $0x40,%al // dma done?
//jz check_dma_r


mov $0x40,%al // clear ISR (RDC bit only)
out %al,%dx
sti //Experimental - Enable INTR
//sti //Experimental - Enable INTR

pop %bx
pop %es
Expand Down Expand Up @@ -439,13 +446,13 @@ ne2k_pack_get:
//mov %sp,%di

// get the 4 byte header first -> arg3
mov 8(%bp),%di
mov 8(%bp),%di // arg3
mov ne2k_next_pk,%bh
xor %bl,%bl // Next pkt to read in BX

mov $4,%cx // Bytes to read
//mov %ds,%ax
//mov %ax,%es // local address space
//mov %ax,%es // local address space
xor %al,%al // indicate kernel DS
call dma_read

Expand Down Expand Up @@ -484,13 +491,16 @@ ne2k_pack_get:
// Removed when read was changed to put data directly into process address space,
// there is no longer anywhere to put the first 4 bytes.

//sub $252,%cx // Got entire packet?
//jle npg_cont
#if 0
sub $252,%cx // Got entire packet?
jle npg_cont
// If not, get rest.
//inc %bh // Point to next page
//cmp $rx_last,%bh // check wraparound
//jnz npg_cont0
//mov $rx_head,%bh
inc %bh // Point to next page
cmp $rx_last,%bh // check wraparound
jnz npg_cont0
mov $rx_head,%bh
#endif

npg_cont0:
//add $256,%di // Update destination memory address
// (keep the 4 byte NIC header)
Expand All @@ -504,7 +514,6 @@ npg_cont0:
pop %ax

// update RX_get pointer (BOUNDARY, end of ring)

npg_cont:
xchg %al,%ah // get pointer to %al
mov %al,ne2k_next_pk // save 'real' next ptr
Expand Down Expand Up @@ -532,7 +541,7 @@ npg_exit:
movw $0,ne2k_has_data

npg_exit_ok:
sti // Enable interrupts
sti
pop %ax // return byte count (from %cx)
//pop %es
pop %di
Expand Down Expand Up @@ -786,6 +795,7 @@ ne2k_init:
// clear if 16bit.
// That way we get around the QEMU RXE bug too.
1: out %al,%dx
mov %al,ne2k_imask

// NOTE: The transmitter is not yet enabled, done in the _start routine.
// FIXME: Should move the int mask and status reg clearing to
Expand Down Expand Up @@ -1007,6 +1017,9 @@ ne2k_get_hw_addr:
// 001f1102602d49534138455448204242, the last 10 bytes being 'ISA8ETH BB'.
// The BB means it's an 8bit card, WW would indicate 16bit bus support.

// NOTE: This routine is called during PROBE only. Otherwise the call to dma_read
// would need irq protection.

w_reset:
call ne2k_base_init // basic initialization

Expand Down Expand Up @@ -1240,8 +1253,8 @@ ne2k_rdc:

ne2k_get_errstat:

// Currently useful only 4 debugging: Needs a regime to regularly collect
// and accumulate the numbers in order to be of statistical value.
// Currently useful only for debugging: Needs a regime to regularly collect
// and accumulate the numbers in order to be of practical value.
#if LATER
push %bp
mov %si,%bp
Expand Down
52 changes: 28 additions & 24 deletions tlvc/arch/i86/drivers/net/ne2k.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,10 @@ static byte_t dev_name[] = "ne0";
static size_t ne2k_getpkg(char *, size_t, word_t);
struct netbuf *netbuf_init(struct netbuf *, int);

extern int ne2k_next_pk;
extern int ne2k_next_pk;
extern word_t ne2k_flags;
extern word_t ne2k_has_data;
extern byte_t ne2k_imask;
extern struct eth eths[];
extern unsigned char macaddr[];

Expand All @@ -68,7 +69,7 @@ extern unsigned char macaddr[];
#endif

/*
* Read a complete packet from the NIC buffer
* Return a complete packet from buffer or directly from the NIC
*/

static size_t ne2k_read(struct inode *inode, struct file *filp, char *data, size_t len)
Expand Down Expand Up @@ -119,7 +120,7 @@ static size_t ne2k_read(struct inode *inode, struct file *filp, char *data, size

/*
* Get a packet from the NIC.
* May be called from the INTR routine and from read(),
* Called from the INTR routine and from read(),
* thus the semaphore.
*/

Expand Down Expand Up @@ -184,21 +185,21 @@ static size_t ne2k_write(struct inode *inode, struct file *file, char *data, siz
while (1) {
prepare_to_wait_interruptible(&txwait);
/* NOTE: tx_stat() checks the command reg, not the tx_status_reg! */
if (ne2k_tx_stat() != NE2K_STAT_TX) {
if (ne2k_tx_stat() != NE2K_ISR_TX) {
#if NET_BUF_STRAT != NO_BUFS
if (tnext) {
/* transmiter is busy, put the data in a buffer if available */
struct netbuf *nxt = tnext;
while (nxt->len) { /* search for available buffer */
if (nxt == tnext) break;
nxt = nxt->next;
if (nxt == tnext) break;
nxt = nxt->next;
}
if (nxt->len == 0) {
kputchar('t');
nxt->len = len;
verified_memcpy_fromfs(nxt->data, data, len);
res = len;
break;
kputchar('t');
nxt->len = len;
verified_memcpy_fromfs(nxt->data, data, len);
res = len;
break;
}
}
#endif
Expand All @@ -216,8 +217,10 @@ static size_t ne2k_write(struct inode *inode, struct file *file, char *data, siz
/* NIC is ready, send the data, no buffering */
if (len > MAX_PACKET_ETH) len = MAX_PACKET_ETH;

if (len < 64) len = 64; /* issue #133 */
if (len < 64) len = 64; /* issue #133 */
outb(0, net_port + EN0_IMR); /* block interrupts from the NIC while moving data to it */
ne2k_pack_put(data, len, BUF_IS_FAR);
outb(ne2k_imask, net_port + EN0_IMR); /* reenable int's */

res = len;
break;
Expand All @@ -237,7 +240,7 @@ int ne2k_select(struct inode *inode, struct file *filp, int sel_type)

switch (sel_type) {
case SEL_OUT:
if ((ne2k_tx_stat() == NE2K_STAT_TX)
if ((ne2k_tx_stat() == NE2K_ISR_TX)
#if NET_BUF_STRAT != NO_BUFS
|| (tnext && !tnext->len)
#endif
Expand Down Expand Up @@ -280,14 +283,15 @@ static void ne2k_int(int irq, struct pt_regs *regs)
word_t stat, page;

kputchar('I');
outb(0x20,0x20); /* EOI to primary controller */
while (1) {
stat = ne2k_int_stat();
if (!stat) break; /* If zero, we're done! */
#if 0 /* debug */
page = ne2k_getpage();
printk("$%04x.%02x$", page,ne2k_next_pk&0xff);
#endif
if (stat & NE2K_STAT_OF) {
if (stat & NE2K_ISR_OF) {
netif_stat.oflow_errors++;
if (verbose) printk(EMSG_OFLOW, dev_name, stat, netif_stat.oflow_keep);
page = ne2k_clr_oflow(netif_stat.oflow_keep);
Expand All @@ -300,7 +304,7 @@ static void ne2k_int(int irq, struct pt_regs *regs)
break;
}

if (stat & NE2K_STAT_RX) {
if (stat & NE2K_ISR_RX) {
kputchar('i');
ne2k_has_data = 1;
}
Expand All @@ -323,10 +327,10 @@ static void ne2k_int(int irq, struct pt_regs *regs)
}
#endif
wake_up(&rxwait);
outb(NE2K_STAT_RX, net_port + EN0_ISR);
outb(NE2K_ISR_RX, net_port + EN0_ISR);
}

if (stat & NE2K_STAT_TX) {
if (stat & NE2K_ISR_TX) {
kputchar('x');
#if NET_BUF_STRAT != NO_BUFS
if (tnext && tnext->len) {
Expand All @@ -335,16 +339,16 @@ static void ne2k_int(int irq, struct pt_regs *regs)
tnext = tnext->next;
}
#endif
outb(NE2K_STAT_TX, net_port + EN0_ISR); // Clear intr bit
outb(NE2K_ISR_TX, net_port + EN0_ISR); // Clear intr bit
inb(net_port + EN0_TSR); /* really needed? */
wake_up(&txwait);
}
//printk("%02X/%d/", stat, ne2k_has_data);
/* shortcut for speed */
if (!(stat&~(NE2K_STAT_TX|NE2K_STAT_RX|NE2K_STAT_OF))) continue;
if (!(stat&~(NE2K_ISR_TX|NE2K_ISR_RX|NE2K_ISR_OF))) continue;

/* These don't happen very often */
if (stat & NE2K_STAT_RDC) {
if (stat & NE2K_ISR_RDC) {
//printk("ne0: Warning - RDC intr. (0x%02x)\n", stat);
/* RDC interrupts should be masked in the low level driver.
* The dma_read, dma_write routines will fail if the RDC intr
Expand All @@ -356,7 +360,7 @@ static void ne2k_int(int irq, struct pt_regs *regs)
ne2k_rdc();
}

if (stat & NE2K_STAT_TXE) {
if (stat & NE2K_ISR_TXE) {
int k;
/* transmit error detected, this should not happen. */
/* ne2k_get_tx_stat resets this bit in the ISR */
Expand All @@ -369,15 +373,15 @@ static void ne2k_int(int irq, struct pt_regs *regs)
* A bug in QEMU will cause continuous interrupts if RXE intr is unmasked.
* Therefore the asm level code will unmask RXE intr only if the NIC is
* running in 8 bit mode */
if (stat & NE2K_STAT_RXE) {
if (stat & NE2K_ISR_RXE) {
/* Receive error detected, may happen when traffic is heavy */
/* The 8 bit interface gets lots of these, all CRC, packet dropped */
/* Don't do anything, just count, report & clr */
netif_stat.rx_errors++;
if (verbose) printk(EMSG_RXERR, dev_name, inb(net_port + EN0_RSR));
outb(NE2K_STAT_RXE, net_port + EN0_ISR); // Clear intr bit
outb(NE2K_ISR_RXE, net_port + EN0_ISR); // Clear intr bit
}
if (stat & NE2K_STAT_CNT) {
if (stat & NE2K_ISR_CNT) {
/* The tally counters will overflow on 8 bit interfaces with
* lots of overruns. Just clear the condition */
ne2k_clr_err_cnt();
Expand Down
27 changes: 20 additions & 7 deletions tlvc/arch/i86/drivers/net/ne2k.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,26 @@

/* NE2K interrupt status bits */

#define NE2K_STAT_RX 0x0001 /* packet received */
#define NE2K_STAT_TX 0x0002 /* packet sent */
#define NE2K_STAT_RXE 0x0004 /* RX error */
#define NE2K_STAT_TXE 0x0008 /* TX error */
#define NE2K_STAT_OF 0x0010 /* RX ring overflow */
#define NE2K_STAT_CNT 0x0020 /* Tally counter overflow */
#define NE2K_STAT_RDC 0x0040 /* Remote DMA complete */
#define NE2K_ISR_RX 0x0001 /* packet received */
#define NE2K_ISR_TX 0x0002 /* packet sent */
#define NE2K_ISR_RXE 0x0004 /* RX error */
#define NE2K_ISR_TXE 0x0008 /* TX error */
#define NE2K_ISR_OF 0x0010 /* RX ring overflow */
#define NE2K_ISR_CNT 0x0020 /* Tally counter overflow */
#define NE2K_ISR_RDC 0x0040 /* Remote DMA complete */

/* NE2K interrupt mask bits */

#define NE2K_IMR_PRXE 0x0001 /* Packet Received Interrupt Enable */
#define NE2K_IMR_PTXE 0x0002 /* Packet Transmitted Interrupt Enable */
#define NE2K_IMR_RXEE 0x0004 /* Receive Error Interrupt Enable */
#define NE2K_IMR_TXEE 0x0008 /* Transmit Error Interrupt Enable */
#define NE2K_IMR_OVWE 0x0010 /* Overwrite Warning Interrupt Enable */
#define NE2K_IMR_CNTE 0x0020 /* Counter Overflow Interrupt Enable */
#define NE2K_IMR_RDCE 0x0040 /* RDMA Complete Interrupt Enable */

/* 8390 Page 0 register offsets (from net_port) */

#define EN0_STARTPG 0x01U /* Starting page of ring bfr WR */
#define EN0_STOPPG 0x02U /* Ending page +1 of ring bfr WR */
#define EN0_BOUNDARY 0x03U /* Boundary page of ring bfr RD WR */
Expand All @@ -27,6 +38,7 @@
#define EN0_IMR 0x0fU /* Interrupt mask reg WR */

/* From low level NE2K MAC */
#ifndef __ASSEMBLER__

extern word_t ne2k_int_stat();

Expand Down Expand Up @@ -59,5 +71,6 @@ extern void ne2k_rdc(void);
extern void ne2k_get_errstat(byte_t *);
extern void ne2k_clr_err_cnt(void);
extern void ne2k_rx_init(void);
#endif

#endif /* !NE2K_H */