diff --git a/tlvc/arch/i86/drivers/net/ne2k-asm.S b/tlvc/arch/i86/drivers/net/ne2k-asm.S index c4f8a771..f10c999c 100644 --- a/tlvc/arch/i86/drivers/net/ne2k-asm.S +++ b/tlvc/arch/i86/drivers/net/ne2k-asm.S @@ -25,6 +25,7 @@ // //----------------------------------------------------------------------------- +#include #include #include #include "netbuf.h" @@ -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: @@ -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 //----------------------------------------------------------------------------- @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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) @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 diff --git a/tlvc/arch/i86/drivers/net/ne2k.c b/tlvc/arch/i86/drivers/net/ne2k.c index 23f4883f..518ea8c8 100644 --- a/tlvc/arch/i86/drivers/net/ne2k.c +++ b/tlvc/arch/i86/drivers/net/ne2k.c @@ -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[]; @@ -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) @@ -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. */ @@ -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 @@ -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; @@ -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 @@ -280,6 +283,7 @@ 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! */ @@ -287,7 +291,7 @@ static void ne2k_int(int irq, struct pt_regs *regs) 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); @@ -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; } @@ -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) { @@ -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 @@ -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 */ @@ -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(); diff --git a/tlvc/arch/i86/drivers/net/ne2k.h b/tlvc/arch/i86/drivers/net/ne2k.h index 338f4cc9..61823a04 100644 --- a/tlvc/arch/i86/drivers/net/ne2k.h +++ b/tlvc/arch/i86/drivers/net/ne2k.h @@ -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 */ @@ -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(); @@ -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 */