Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 8 Jun 1999 14:22:11 -0700 (PDT)
From:      pete@altadena.net
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   i386/12088: i386
Message-ID:  <199906082122.OAA00592@portable.altadena.net>

next in thread | raw e-mail | index | archive | help

>Number:         12088
>Category:       i386
>Synopsis:       Enhancement to ed driver for Linksys 10/100 or DLink DFE650
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Jun  8 14:30:01 PDT 1999
>Closed-Date:
>Last-Modified:
>Originator:     Pete Carah
>Release:        FreeBSD 3.2-STABLE i386
>Organization:
Altadena Internet
>Environment:

	3.x (the if_ed driver appears to not have changed since 3.0-stable.)
	PCMCIA 10/100 ethernet.

>Description:

	Add full functionality for Linksys 10/100 or DLink DFE650

>How-To-Repeat:

	Use either of these cards in a laptop

>Fix:
	This was made up by fitting data from the linux driver into 
	the existing if_ed.c framework.
	Apply diff: (debug stuff isn't really needed :-)

*** if_ed.c	Thu Mar 18 10:47:27 1999
--- if_ed.c.new	Thu Apr 29 10:16:46 1999
***************
*** 157,162 ****
--- 157,165 ----
  static int ed_probe_Novell_generic __P((struct ed_softc *, int, int, int));
  static int ed_probe_HP_pclanp	__P((struct isa_device *));
  
+ static int ed_probe_DL10019A	__P((struct isa_device *));
+ static int ed_probe_DL10019A_generic __P((struct ed_softc *, int, int, int));
+ 
  #include "pci.h"
  #if NPCI > 0
  void *ed_attach_NE2000_pci	__P((int, int));
***************
*** 221,229 ****
--- 224,240 ----
  	u_char  e;
  	struct ed_softc *sc = &ed_softc[devi->isahd.id_unit];
  
+ #if ED_DEBUG
+ 	printf("EDINIT called %d\n", devi->isahd.id_unit);
+ #endif
+ 
  	/* validate unit number. */
  	if (devi->isahd.id_unit >= NEDTOT)
  		return(ENODEV);
+ 
+ #if ED_DEBUG
+ 	printf("Unit valid, probing\n");
+ #endif
  	/*
  	 * Probe the device. If a value is returned, the
  	 * device was found at the location.
***************
*** 231,242 ****
--- 242,257 ----
  	sc->gone = 0;
  	if (ed_probe_pccard(&devi->isahd, devi->misc) == 0)
  		return(ENXIO);
+ #if ED_DEBUG
+ 	printf("Probed OK\n");
+ #endif
  	e = 0;
  	for (i = 0; i < ETHER_ADDR_LEN; ++i)
  		e |= devi->misc[i];
  	if (e)
  		for (i = 0; i < ETHER_ADDR_LEN; ++i)
  			sc->arpcom.ac_enaddr[i] = devi->misc[i];
+ 
  	if (ed_attach_isa(&devi->isahd) == 0)
  		return(ENXIO);
  
***************
*** 742,748 ****
  		sc->cr_proto = 0;
  	}
  
! #if 0
  	printf("starting memory performance test at 0x%x, size %d...\n",
  		sc->mem_start, memsize*16384);
  	for (i = 0; i < 16384; i++)
--- 757,763 ----
  		sc->cr_proto = 0;
  	}
  
! #if ED_DEBUG
  	printf("starting memory performance test at 0x%x, size %d...\n",
  		sc->mem_start, memsize*16384);
  	for (i = 0; i < 16384; i++)
***************
*** 1158,1164 ****
--- 1173,1181 ----
  		ed_pio_readmem(sc, 16384, test_buffer, sizeof(test_pattern));
  
  		if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)))
+ 		{
  			return (0);	/* not an NE2000 either */
+ 		}
  
  		sc->type = ED_TYPE_NE2000;
  		sc->type_str = "NE2000";
***************
*** 1288,1293 ****
--- 1305,1500 ----
  				       isa_dev->id_unit, isa_dev->id_flags);
  }
  
+ static int
+ ed_probe_DL10019A_generic(sc, port, unit, flags)
+ 	struct ed_softc *sc;
+ 	int port;
+ 	int unit;
+ 	int flags;
+ {
+ 	u_int   memsize, n;
+ 	u_char  romdata[16], tmp;
+ 	static char test_pattern[32] = "THIS is A memory TEST pattern";
+ 	char    test_buffer[32];
+ 	u_int i, sum, c;
+ 
+ 	sc->asic_addr = port + 0x10;
+ 	sc->nic_addr = port + 0x00;
+ 
+ 	/* XXX - do Novell-specific probe here */
+ 
+ 	/* Reset the board */
+ 	tmp = inb(sc->asic_addr + ED_NOVELL_RESET);
+ 
+ 	/*
+ 	 * I don't know if this is necessary; probably cruft leftover from
+ 	 * Clarkson packet driver code. Doesn't do a thing on the boards I've
+ 	 * tested. -DG [note that a outb(0x84, 0) seems to work here, and is
+ 	 * non-invasive...but some boards don't seem to reset and I don't have
+ 	 * complete documentation on what the 'right' thing to do is...so we
+ 	 * do the invasive thing for now. Yuck.]
+ 	 */
+ 	outb(sc->asic_addr + ED_NOVELL_RESET, tmp);
+ 	DELAY(5000);
+ 
+ 	/*
+ 	 * This is needed because some NE clones apparently don't reset the
+ 	 * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX
+ 	 * - this makes the probe invasive! ...Done against my better
+ 	 * judgement. -DLG
+ 	 */
+ 	outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2 | ED_CR_STP);
+ 
+ 	DELAY(5000);
+ 
+ 	/* Make sure that we really have an 8390 based board */
+ 	if (!ed_probe_generic8390(sc))
+ 		return (0);
+ 
+ 	sc->vendor = ED_VENDOR_DL10019A;
+ 	sc->mem_shared = 0;
+ 	sc->cr_proto = ED_CR_RD2;
+ 
+ 	/*
+ 	 * Test the ability to read and write to the NIC memory. This has the
+ 	 * side affect of determining if this is an NE1000 or an NE2000.
+ 	 */
+ 
+ #if ED_DEBUG
+ 	printf("Checking address - ");
+ #endif
+ 	for(sum = 0,i = 0x14; i < 0x1c; ++i)
+ 	{
+ 	    sum += (c = inb(sc->nic_addr + i));
+ #if ED_DEBUG
+ 	    printf("%02x:", c);
+ #endif
+ 	}
+ #if ED_DEBUG
+ 	printf(" - sum=%02x\n", sum);
+ #endif
+ 
+ 	if ((sum & 0xff) != 0xff)
+ 	    return 0;
+ 
+ #if ED_DEBUG
+ 	printf("Getting address\n");
+ #endif
+ 
+ 	for (n = 0; n < ETHER_ADDR_LEN; n++)
+ 		sc->arpcom.ac_enaddr[n] = inb(sc->nic_addr + 0x14 + n);
+ 
+ #if ED_DEBUG
+ 	printf("Structure address %02x:%02x:%02x:%02x:%02x:%02x\n",
+ 		sc->arpcom.ac_enaddr[0], sc->arpcom.ac_enaddr[1],
+ 		sc->arpcom.ac_enaddr[2], sc->arpcom.ac_enaddr[3],
+ 		sc->arpcom.ac_enaddr[4], sc->arpcom.ac_enaddr[5]);
+ #endif
+ 	/*
+ 	 * This prevents packets from being stored in the NIC memory when the
+ 	 * readmem routine turns on the start bit in the CR.
+ 	 */
+ 
+ 	outb(sc->nic_addr + ED_P0_RCR, ED_RCR_MON);
+ 
+ 	outb(sc->nic_addr + ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS);
+ 	outb(sc->nic_addr + ED_P0_PSTART, 0 / ED_PAGE_SIZE);
+ 	outb(sc->nic_addr + ED_P0_PSTOP, 32768 / ED_PAGE_SIZE);
+ 
+ 	sc->isa16bit = 1;
+ 
+ 	ed_pio_writemem(sc, test_pattern, 1024, sizeof(test_pattern));
+ 	ed_pio_readmem(sc, 1024, test_buffer, sizeof(test_pattern));
+ 
+ #if ED_DEBUG
+ 	printf("Test Pattern %-30.30s\n", test_pattern);
+ 	printf("Test as seen %-30.30s\n", test_buffer);
+ #endif
+ 
+ 	if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)))
+ 	{
+ 		return (0);	/* not an NE2000 either */
+ 	}
+ 
+ 	/* try top of memory - Linksys is 32k and D-Link is 64k */
+ 	ed_pio_writemem(sc, test_pattern, 32000, sizeof(test_pattern));
+ 	ed_pio_readmem(sc, 32000, test_buffer, sizeof(test_pattern));
+ 
+ #if ED_DEBUG
+ 	printf("Test Pattern %-30.30s\n", test_pattern);
+ 	printf("Test as seen %-30.30s\n", test_buffer);
+ #endif
+ 
+ 	if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)))
+ 	{
+ 		return (0);	/* not an NE2000 either */
+ 	}
+ 
+ 	/* try D-Link with 64k buffer */
+ 	outb(sc->nic_addr + ED_P0_PSTOP, 65280 / ED_PAGE_SIZE);
+ 
+ 	ed_pio_writemem(sc, test_pattern, 65200, sizeof(test_pattern));
+ 	ed_pio_readmem(sc, 65200, test_buffer, sizeof(test_pattern));
+ 
+ #if ED_DEBUG
+ 	printf("Test Pattern %-30.30s\n", test_pattern);
+ 	printf("Test as seen %-30.30s\n", test_buffer);
+ #endif
+ 
+ 	if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)))
+ 	{
+ 	    sc->type_str = "LinkSys";
+ 
+ 	    /* 8k of memory plus an additional 8k if 16bit */
+ 	    memsize = 32768;
+ 	    outb(sc->nic_addr + ED_P0_PSTOP, 32768 / ED_PAGE_SIZE);
+ 
+ 	}
+ 	else
+ 	{
+ 	    sc->type_str = "D-Link";
+ 	    /* More memory */
+ 	    memsize = 65280;
+ 	}
+ 
+ 
+ 	sc->mem_size = memsize;
+ 
+ 	/* NIC memory doesn't start at zero on an NE board */
+ 	/* The start address is tied to the bus width */
+ 	sc->mem_start = 0;
+ 	sc->mem_end = sc->mem_start + memsize;
+ 	sc->tx_page_start = 0 / ED_PAGE_SIZE;
+ 
+ 
+ 	/*
+ 	 * Use one xmit buffer if < 16k, two buffers otherwise (if not told
+ 	 * otherwise).
+ 	 */
+ 	sc->txb_cnt = 2;
+ 
+ 	sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE;
+ 	sc->rec_page_stop = sc->tx_page_start + memsize / ED_PAGE_SIZE;
+ 
+ 	sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE;
+ 
+ 	/* clear any pending interrupts that might have occurred above */
+ 	outb(sc->nic_addr + ED_P0_ISR, 0xff);
+ 
+ 	return (32);
+ }
+ 
+ static int
+ ed_probe_DL10019A(isa_dev)
+ 	struct isa_device *isa_dev;
+ {
+ 	struct ed_softc *sc = &ed_softc[isa_dev->id_unit];
+ 
+ 	isa_dev->id_maddr = 0;
+ 	return ed_probe_DL10019A_generic(sc, isa_dev->id_iobase, 
+ 				       isa_dev->id_unit, isa_dev->id_flags);
+ }
+ 
  #if NCARD > 0
  /*
   * Probe framework for pccards.  Replicates the standard framework, 
***************
*** 1301,1306 ****
--- 1508,1517 ----
  {
  	int     nports;
  
+ 	nports = ed_probe_DL10019A(isa_dev);
+ 	if (nports)
+ 		return(nports);
+ 
  	nports = ed_probe_WD80x3(isa_dev);
  	if (nports)
  		return (nports);
***************
*** 2877,2883 ****
  {
  	int     maxwait = 200;	/* about 240us */
  
! 	if (sc->vendor == ED_VENDOR_NOVELL) {
  
  		/* select page 0 registers */
  		outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2 | ED_CR_STA);
--- 3088,3095 ----
  {
  	int     maxwait = 200;	/* about 240us */
  
! 	if (sc->vendor == ED_VENDOR_NOVELL ||
! 	    sc->vendor == ED_VENDOR_DL10019A) {
  
  		/* select page 0 registers */
  		outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2 | ED_CR_STA);
*** if_edreg.h	Thu Oct  8 10:20:58 1998
--- if_edreg.h.new	Thu Apr 29 10:16:59 1999
***************
*** 571,576 ****
--- 571,578 ----
  #define ED_VENDOR_PCCARD	0x03		/* PCMCIA/PCCARD */
  #define ED_VENDOR_HP		0x04		/* Hewlett Packard */
  
+ #define ED_VENDOR_DL10019A	0x05		/* LinkSys, maybe DLINK */
+ 
  /*
   * Compile-time config flags
   */




>Release-Note:
>Audit-Trail:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199906082122.OAA00592>