ne2k interrupt not hanppen .

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
firekylin
Posts: 11
Joined: Thu Jun 09, 2016 11:41 pm

ne2k interrupt not hanppen .

Post by firekylin »

Recently, I want to write a ne2k driver for my hobby os. But I can't do it very well.

I try to do it , but when I send a packet it will not tigger a interrupt, and will a red blink at the bochs window on `en2k` .

also , I don't know how to test to receive a packet , because I really don't know how to send a packet to the vm (bochs or qemu) with
win7.

Thanks for your help.

Code: Select all

#include <firekylin/kernel.h>
#include <firekylin/trap.h>
#include <firekylin/lock.h>
#include <firekylin/pci.h>
#include <firekylin/mm.h>

/*
 * ne2k_pci rquipped by bochs or qemu. other unknow.
 */
#define NE2K_VENDOR	0x10EC
#define NE2K_DEVICE	0x8029

/* ne2k register offset */
#define CR		0x00

/* page 0, read */
#define CLDA0		0x01
#define CLDA1		0x02
#define BNRY		0x03    /* rw */
#define TSR		0x04
#define NCR		0x05
#define FIFO		0x06
#define ISR		0x07	/* rw */
#define CRDA0		0x08
#define CRDA1		0x09
#define RSR		0x0C
#define CNTR0		0x0D
#define CNTR1		0x0E
#define CNTR2		0x0F

/* page 0 write */
#define PSTART		0x01	/* read page 2 */
#define PSTOP		0x02	/* read page 2 */
#define TPSR		0x04	/* read page 2 */
#define TBCR0		0x05
#define TBCR1		0x06
#define RSAR0		0x08
#define RSAR1		0x09
#define RBCR0		0x0A
#define RBCR1		0x0B
#define RCR		0x0C	/* read page 2 */
#define TCR		0x0D	/* read page 2 */
#define DCR		0x0E	/* read page 2 */
#define IMR		0x0F	/* read page 2 */

/* page 1 read/write */
#define PAR0		0x01
#define PAR1		0x02
#define PAR2		0x03
#define PAR3		0x04
#define PAR4		0x05
#define PAR5		0x06
#define CURR		0x07
#define MAR0		0x08
#define MAR1		0x09
#define MAR2		0x0A
#define MAR3		0x0B
#define MAR4		0x0C
#define MAR5		0x0D
#define MAR6		0x0E
#define MAR7		0x0F

#define DATA		0x10
#define RESET		0x1F

static struct pci_device *ne2k;
static unsigned short base;
static unsigned char irq;
static unsigned char mac[6];
static unsigned short rx_next=0x47;

/*
 * ne2k reg : CR, ISR, IMR, DCR, TCR, TSR, RCR, RSR.
 *            CLDA0,1 PSTART PSTOP BNRY TPSR TBCR0,1
 *            NCR FIFO CRDA0,1 RSAR0,1 RBCR0,1 CNTR0
 *            CNTR1 CNTR2 PAR0-5 CURR MAR0-7
 */

int ne2k_send(char *data, short len)
{
	printk("wait ne2k ...\n");
	while (inb(base + CR) == 0x26)
		;

	printk("write dma ...\n");
	len = (len + 1) & ~1;

	outb(base + RSAR0, 0);
	outb(base + RSAR1, 0x40);

	outb(base + RBCR0, len & 0xff);
	outb(base + RBCR1, (len >> 8) & 0xff);

	outb(base + TBCR0, len & 0xff);
		outb(base + TBCR1, (len >> 8) & 0xff);

	outb(base + CR, 0x12); // write and start.

	/*
	 * use DMA, also need this?, really don't know.
	 */
	outs(base + DATA, data, len);
	printk("here1");
	// wait DMA end.
	while ((inb(base + ISR) & 0x40) == 0)
		;
	printk("here2");
	// clear DMA interrupt bit.
	outb(base + ISR, 0x40);
	printk(" DMA end\n start trasport\n");

	/*
	 * does need to set this evey packet, does it will change?
	 */
	outb(base + TPSR, 0x40);

	outb(base + CR, 0x06);
	printk("over");
	return 0;
}

void do_ne2k(struct trapframe *tf)
{
	printk("ne2k intrrupt happen");
	if (irq >= 8)
		outb(0xa0, 0x20);
	outb(0x20, 0x20);
}


char arpdata[] =
	"\xff\xff\xff\xff\xff\xff\xb0\xc4\x20\x00\x00\x00\x08\x06\x00\x01"
	"\x08\x00\x06\x04\x00\x01\xb0\xc4\x20\x00\x00\x00\x0a\x00\x01\x15"
	"\x00\x00\x00\x00\x00\x00\x0a\x00\x01\x08";


void ne2k_init(void)
{
	if (!(ne2k = pci_find_device(NE2K_VENDOR, NE2K_DEVICE)))
		return (void) printk("ne2k not exsit on system\n");

	base = ne2k->bar0 & ~3;
	irq = ne2k->interrput_line;

	printk("ne2k--iobase:%x\n", base);
	printk("ne2k--irq:%d\n", irq);

	set_trap_handle(irq, do_ne2k);
	if (irq >= 8)
		outb(0xa1, 0);
	else
		outb(0x21, 0);

	outb(base + RESET, inb(base + RESET));
	while ((inb(base + ISR) & 0x80) == 0)
		;
	printk("ne2k reset done");

	outb(base + CR,  0x21);
	outb(base + DCR, 0x49);
	outb(base + TCR, 0x00);
	outb(base + RCR, 0x20);
	outb(base + IMR, 0x00);
	outb(base + ISR, 0xFF);

	outb(base + TPSR, 0x40);
	outb(base + PSTART, rx_next-1);
	outb(base + PSTOP, 0x80);
	outb(base + BNRY, rx_next-1);
	outb(base + CR, 0x61);
	outb(base + CURR, rx_next);
	outb(base + CR, 0x21);

	outb(base + RSAR0, 0);
	outb(base + RSAR1, 0);
	outb(base + RBCR0, 24);
	outb(base + RBCR1, 0);
	outb(base + CR,    0x0A);
	printk("ne2k MAC: ");
	for(int i=0;i<6;i++){
		mac[i]=inb(base+DATA);
		printk("%x:",mac[i]);
	}
	printk("\b\n");

	outb(base + CR, 0x61);
	outb(base + PAR0,mac[0]);
	outb(base + PAR1,mac[1]);
	outb(base + PAR2,mac[2]);
	outb(base + PAR3,mac[3]);
	outb(base + PAR4,mac[4]);
	outb(base + PAR5,mac[5]);

	outb(base + IMR,0xFF);
	outb(base + CR, 0x22);
	
	ne2k_send(arpdata,42);
}
bochs also has a log file:

Code: Select all

vnet packetmover readable log file
TFTP root = xl0
host MAC address = b0:c4:20:12:34:55
guest MAC address = b0:c4:20:12:34:56
--
a packet from guest to host, length 42
ff ff ff ff ff ff b0 c4 20 00 00 00 08 06 00 01 
08 00 06 04 00 01 b0 c4 20 00 00 00 0a 00 01 15 
00 00 00 00 00 00 0a 00 01 08 
--
a packet from guest to host, length 42
ff ff ff ff ff ff b0 c4 20 00 00 00 08 06 00 01 
08 00 06 04 00 01 b0 c4 20 00 00 00 0a 00 01 15 
00 00 00 00 00 00 0a 00 01 08 
--
Post Reply