⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ne2000.c

📁 VRTX 商用嵌入式实时操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
#if EI_DEBUG > 0
    printf("\n");
#endif

    neX000 = (SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57);
    ctron =  (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
    dlink =  (SA_prom[0] == 0x00 && SA_prom[1] == 0xDE && SA_prom[2] == 0x01);
    dfi   =  (SA_prom[0] == 'D' && SA_prom[1] == 'F' && SA_prom[2] == 'I');

#if EI_DEBUG > 0
	if ( neX000 )
		printf("neX000");
#endif

    /* Set up the rest of the parameters. */
	if (neX000 || dlink || dfi) {
		if (wordlength == 2) {
			name = dlink ? "DE200" : "NE2000";
			start_page = NESM_START_PG;
			stop_page = NESM_STOP_PG;
		} else {
			name = dlink ? "DE100" : "NE1000";
			start_page = NE1SM_START_PG;
			stop_page = NE1SM_STOP_PG;
		}
	} else if (ctron) {
		name = "Cabletron";
		start_page = 0x01;
		stop_page = (wordlength == 2) ? 0x40 : 0x20;
	} else {
		printf(" not found.\n");
		return 0;
	}

    dev->base_addr = ioaddr;
    dev->name = name;
#if EI_DEBUG > 0
    printf(" %s: %s found at %x, using IRQ %x.\n",
	   dev->name, name, ioaddr, dev->irq);
#endif

    ei_status.name = name;
    ei_status.tx_start_page = start_page;
    ei_status.stop_page = stop_page;
    ei_status.word16 = (wordlength == 2);

    ei_status.rx_start_page = start_page + TX_PAGES;
#ifdef PACKETBUF_MEMSIZE
    /* Allow the packet buffer size to be overridden by know-it-alls. */
    ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
#endif

    NS8390_init(dev, 1);
    return dev->base_addr;
}

#if 0 /* not used now */
/* 
 * void ne_reset_8390(struct device *dev)
 *
 *	Resets the board associated with DEV, including a hardware 
 *	reset of the 8390.  This would only be called when there is a 
 *	transmit timeout, which is currently not implemented.
 */
void ne_reset_8390(struct device *dev)
{
    int tmp = INPB(dev->base_addr + NE_RESET);

#if EI_DEBUG > 1
    printf("resetting the 8390 ...\n");
#endif
    ei_status.txing = 0;

    OUTB(dev->base_addr + NE_RESET, tmp);
    /* This check _should_not_ be necessary, omit eventually. */
    while ((INPB(dev->base_addr+EN0_ISR) & ENISR_RESET) == 0) ;
}
#endif /* 0 */

/* 
 * int
 * block_input(struct device *dev, int count, char *buf, int ring_offset)
 *
 *	Read COUNT bytes from the packet buffer into BUF.  Start 
 *	reading from RING_OFFSET, the address as the 8390 sees it.  
 *	The first read will always be the 4 byte, page aligned 8390 
 *	header.  *If* there is a subsequent read, it will be of the 
 *	rest of the packet.
 */
int
ne_block_input(struct device *dev, int count, char *buf, int ring_offset)
{
	int xfer_count = count;
	int nic_base = dev->base_addr;

	ENTRY("ne_block_input");

	if (ei_status.dmaing) {
#if EI_DEBUG > 0
		printf("%s: DMAing conflict in ne_block_input."
		   "[DMAstat:%1x][irqlock:%1x]\n",
		   dev->name, ei_status.dmaing, ei_status.irqlock);
#endif
		EXIT("ne_block_input");
		return 0;
	}
	ei_status.dmaing |= 0x01;
	OUTB(nic_base + NE_CMD, E8390_NODMA+E8390_PAGE0+E8390_START);
	OUTB(nic_base + EN0_RCNTLO, count & 0xff);
	OUTB(nic_base + EN0_RCNTHI, count >> 8);
	OUTB(nic_base + EN0_RSARLO, ring_offset & 0xff);
	OUTB(nic_base + EN0_RSARHI, ring_offset >> 8);
	OUTB(nic_base + NE_CMD, E8390_RREAD+E8390_START);
	if (ei_status.word16) {
		_insw(nic_base + NE_DATAPORT, (short *)buf, count>>1);
		if (count & 0x01)
			buf[count-1] = INPB(nic_base + NE_DATAPORT), xfer_count++;
	} else {
		_insb(nic_base + NE_DATAPORT, buf, count);
	}

    /* This was for the ALPHA version only, but enough people have
       encountering problems that it is still here.  If you see
       this message you either 1) have an slightly imcompatible clone
       or 2) have noise/speed problems with your bus. */
	#if EI_DEBUG > 1
	{		/* DMA termination address check... */
		int addr, tries = 20;
		do {
			/* Check the DMA address. */
			int high = INPB(nic_base + EN0_RSARHI);
			int low = INPB(nic_base + EN0_RSARLO);
			addr = (high << 8) + low;
			if (((ring_offset + xfer_count) & 0xff) == low)
				break;
		} while (--tries > 0);
		if (tries <= 0)
			printf("%s: RX transfer address mismatch,"
			   "%x (expected) vs. %x (actual).\n",
			   dev->name, ring_offset + xfer_count, addr);
	}
	#endif
	ei_status.dmaing &= ~0x01;
	EXIT("ne_block_input");
	return ring_offset + count;
}

/* 
 * void
 * ne_block_output(struct device *dev, int count, char *buf, int start_offset)
 *
 * 	Write COUNT bytes of BUF to the packet buffer at START_OFFSET.
 */
void
ne_block_output(struct device *dev, int count, char *buf, int start_offset)
{
#if EI_DEBUG >  1
	int retries = 0;
#endif
	int nic_base = dev->base_addr;

	ENTRY("ne_block_output");
#if EI_DEBUG >  1
	printf("ne_block_output(%x,%x,%x,%x)\n", dev, count, buf, start_offset);
	printf("    base_addr=%x\n", dev->base_addr);
	dump(buf, count);
#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))
		count++;
	if (ei_status.dmaing) {
#if EI_DEBUG > 0
		printf("%s: DMAing conflict in ne_block_output."
			"[DMAstat:%1x][irqlock:%1x]\n",
			dev->name, ei_status.dmaing, ei_status.irqlock);
#endif
		EXIT("ne_block_output");
		return;
	}
	ei_status.dmaing |= 0x02;
	/* We should already be in page 0, but to be safe... */
	OUTB(nic_base + NE_CMD, E8390_PAGE0+E8390_START+E8390_NODMA);

retry:

#define NE8390_RW_BUGFIX
#ifdef NE8390_RW_BUGFIX
 /*
  Dummy read-before-write bug fix from Linux ne.c driver.
  This appears to prevent crashes on some fast machines.
 */
	OUTB(nic_base + EN0_RCNTLO, count & 0xff);
	OUTB(nic_base + EN0_RCNTHI, count >> 8);
	OUTB(nic_base + EN0_RSARLO, start_offset & 0xff);
	OUTB(nic_base + EN0_RSARHI, start_offset >> 8);
	OUTB(nic_base + NE_CMD, E8390_RREAD+E8390_START);
 /* make sure the dummy read has enough time to complete */
	INPB(nic_base + NE_CMD);
#endif

	OUTB(nic_base + EN0_RCNTLO, count & 0xff);
	OUTB(nic_base + EN0_RCNTHI, count >> 8);
	OUTB(nic_base + EN0_RSARLO, start_offset & 0xff);
	OUTB(nic_base + EN0_RSARHI, start_offset >> 8);

#if EI_DEBUG > 1 /* debug */
	printf("block_output: reading back EN0_RSARs: %x %x\n",
		INPB(nic_base + EN0_RSARHI),
		INPB(nic_base + EN0_RSARLO));
#endif

	OUTB(nic_base + NE_CMD, E8390_RWRITE+E8390_START);
	if (ei_status.word16)
		_outsw(nic_base + NE_DATAPORT, (short *) buf, count>>1);
	else
		_outsb(nic_base + NE_DATAPORT, buf, count);

#if EI_DEBUG > 1
	{		/* DMA termination address check... */
		int addr, tries = 20;
		do {
			/* Check the DMA address. */
			int high = INPB(nic_base + EN0_RSARHI);
			int low = INPB(nic_base + EN0_RSARLO);
			addr = (high << 8) + low;
			if (((start_offset + count) & 0xff) == low)
				break;
		} while (--tries > 0);
		if (tries <= 0) {
			printf("%s: Tx packet transfer address mismatch,"
				"%x (expected) vs. %x (actual).\n",
				dev->name, start_offset + count, addr);
			if (retries++ == 0)
				goto retry;
		}
	}
#endif
	ei_status.dmaing &= ~0x02;
	EXIT("ne_block_output");
}

#if 0
/*
 * NOTE: These two functions, OUTB() and INPB() are required
 *       to guarantee adequate timing of ISA bus I/O to the
 *       ne2000. Due to the argument passing and the call/ret 
 *       instructions required to get into and exit from these 
 *       functions, sufficient delays are introduced. 
 *
 *       If these are replaced with the intrinsics OUTB() and 
 *       INPB() throughout the code, then there may not be sufficient 
 *       time between two back-to-back I/O instructions for the second 
 *       I/O to work.
 *      If you suspect a problem, use these functions
 */
void
outb(int port, int data)
{
	_outb(port, data);
}

int
inb(int port)
{
	return(_inb(port));
}
#endif


#ifdef NEDEBUG
/*
 * Support for debugging macros ENTRY(), EXIT(), etc.
 */
static indent = 0;
#define INDENT_AMT 1

void
nedebug_entry(char *name)
{
	int i;

	for (i = indent; i-- > 0; printf(" ")) ;
	printf("%s\n", name);
	indent += INDENT_AMT;
}

void
nedebug_exit(char *name)
{
	int i;

	if ((indent -= INDENT_AMT) < 0)
		indent = 0;
	for (i = indent; i-- > 0; printf(" ")) ;
	printf("%s }\n", name);
}

void
nedebug_exit2(char *name, int rv)
{
	int i;

	if ((indent -= INDENT_AMT) < 0)
		indent = 0;
	for (i = indent; i-- > 0; printf(" ")) ;
	printf("%s 0x%x}\n", name, rv);
}

#endif /* NEDEBUG */

#if EI_DEBUG > 0
/*
 * DEBUG support routines 
 */
void
dump(char *d, int size)
{
     int x = 0;

     if (!size)
          return;

     while(size--) {
		  if ((x % 16) == 0)
               printf("\n%08.8x: ", d);
          printf("%02.2x ",*((unsigned char *)d));
		  d++;
		  x++;
     }
     printf("\n");
}

#endif /* NEDEBUG */

#if RWS /* debug */

#define IOLOGSZ 128
short ne2000_iolog[ IOLOGSZ + 4 ];
#define IOLOGIDX   ne2000_iolog[IOLOGSZ+1]
#define COUNTDOWN  ne2000_iolog[IOLOGSZ+2]

void
outb_log(int port, int data)
{
	ne2000_iolog[ IOLOGIDX ] = ((port & 0xf) << 8) | (data & 0xFF);
	if (++IOLOGIDX >= IOLOGSZ) IOLOGIDX = 0;
	ne2000_iolog[ IOLOGIDX ] = 0xFFFF;

	_outb(port, data);
}

int
inb_log(int port)
{
	int data = _inb(port);

	ne2000_iolog[ IOLOGIDX ] = 0x8000 | ((port & 0xf) << 8) | (data & 0xFF);
	if (++IOLOGIDX >= IOLOGSZ) IOLOGIDX = 0;
	ne2000_iolog[ IOLOGIDX ] = 0xFFFF;

	return data;
}

void
dumpiolog()
{
	int i, cnt = 0;
	short s;

	printf("\nINPB/OUTB LOG:\n");
	i = IOLOGIDX + 1;
	do {
		s = ne2000_iolog[ i ];
		printf("%s %x %02x    ",
			(s & 0x8000)? "IN:  ": "OUT: ",
			(s >> 8) & 0xF,
			s & 0xFF);
		if (++cnt % 4 == 0)
			printf("\n");
		if (++i >= IOLOGSZ)
			i = 0;
	} while (i != IOLOGIDX);
	printf("\n");
}

#define CRMASK	0x3B	/* cmd reg: RD2|RD1|RD0|STA|STP */

/*
 * Save the state of the 8390 (read) registers.
 */
void
savestate(int cmdreg, unsigned char *buf)
{
	/* NOTE: don't change _inb/_outb to INPB/OUTB! */
	int cr;
	int i = 0;

	cr = _inb(cmdreg);	/* save command reg */

	/* PAGE 0 */
	buf[i++] = (unsigned char)cr;
	_outb(cmdreg, ((cr & CRMASK) | E8390_PAGE0));
	do
		buf[i] = (unsigned char) _inb(cmdreg + i);
	while (++i < 16);

	/* PAGE 1 */
	buf[i++] = (unsigned char)cr;
	_outb(cmdreg, ((cr & CRMASK) | E8390_PAGE1));
	do
		buf[i] = (unsigned char) _inb(cmdreg + (i % 16));
	while (++i < 32);

	/* PAGE 2 */
	buf[i++] = (unsigned char)cr;
	_outb(cmdreg, ((cr & CRMASK) | E8390_PAGE2));
	do
		buf[i] = (unsigned char) _inb(cmdreg + (i % 16));
	while (++i < 48);

	_outb(cmdreg, (cr & ~E8390_TRANS));	/* restore all but TXP */
}

void
dumpstate(unsigned char *buf)
{
	int i;

	printf("\n8390 REGISTERS:\n    ");
	for (i = 0; i < 16; i++)
		printf(" %02x", i);
	for (i = 0; i < 48; i++) {
		if ((i % 16) == 0)
			printf("\n%d - ", i / 16);
		printf(" %02x", buf[i]);
	}
	printf("\n");
}

#endif /* RWS */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -