PERFORCE change 153777 for review

Sam Leffler sam at FreeBSD.org
Sat Nov 29 10:41:13 PST 2008


http://perforce.freebsd.org/chv.cgi?CH=153777

Change 153777 by sam at sam_ebb on 2008/11/29 18:40:51

	Improve configuarability, add ixp435 support, and other fixups:
	o change static configation state to use NPE id's instead of
	  port #'s; this allows board descriptions to be more portable
	  and more understandable (e.g. it's simpler to compare to the
	  IAL and linux code bases)
	o add support for ixp435/Cambria boards
	o change npe init setup to be done by npeid instead of unit#
	  so npe code doesn't need to translate
	o add support for hints override of npeid and imageid
	o add some error msgs for improbable conditions
	o hack "fix rx q setup" issue; this was a reminder that if we
	  tried to map all 8 traffic classifications to our rx q the
	  npe firmware would hang; this looks to be dependent on the
	  firmware--if we're running vanilla Ethernet support it only
	  groks 4 classifications, 8 when QoS+VLAN support is present;
	  use the f/w image features id to decide how many to map
	
	NB: the 2nd port on the Cambria board doesn't work but this is
	likely because we have the wrong firmware; still working on that.

Affected files ...

.. //depot/projects/vap/sys/arm/xscale/ixp425/if_npe.c#6 edit
.. //depot/projects/vap/sys/arm/xscale/ixp425/if_npereg.h#3 edit
.. //depot/projects/vap/sys/arm/xscale/ixp425/ixp425_npe.c#3 edit
.. //depot/projects/vap/sys/arm/xscale/ixp425/ixp425_npevar.h#3 edit

Differences ...

==== //depot/projects/vap/sys/arm/xscale/ixp425/if_npe.c#6 (text+ko) ====

@@ -85,6 +85,8 @@
 #include <dev/mii/miivar.h>
 #include <arm/xscale/ixp425/if_npereg.h>
 
+#include <machine/armreg.h>
+
 #include "miibus_if.h"
 
 /* 
@@ -121,6 +123,7 @@
 	bus_space_handle_t sc_ioh;	/* MAC register window */
 	device_t	sc_mii;		/* child miibus */
 	bus_space_handle_t sc_miih;	/* MII register window */
+	int		sc_npeid;
 	struct ixpnpe_softc *sc_npe;	/* NPE support */
 	int		sc_debug;	/* DPRINTF* control */
 	int		sc_tickinterval;
@@ -143,7 +146,7 @@
 };
 
 /*
- * Per-unit static configuration for IXP425.  The tx and
+ * Static configuration for IXP425.  The tx and
  * rx free Q id's are fixed by the NPE microcode.  The
  * rx Q id's are programmed to be separate to simplify
  * multi-port processing.  It may be better to handle
@@ -154,11 +157,9 @@
  * assumptions probably need to be handled through hints.
  */
 static const struct {
-	const char	*desc;		/* device description */
-	int		npeid;		/* NPE assignment */
-	uint32_t	imageid;	/* NPE firmware image id */
-	uint32_t	regbase;
-	int		regsize;
+	uint32_t	imageid;	/* default fw image */
+	uint32_t	macbase;
+	int		macsize;
 	uint32_t	miibase;
 	int		miisize;
 	int		phy;		/* phy id */
@@ -166,12 +167,23 @@
 	uint8_t		rx_freeqid;
 	uint8_t		tx_qid;
 	uint8_t		tx_doneqid;
-} npeconfig[NPE_PORTS_MAX] = {
-	{ .desc		= "IXP NPE-B",
-	  .npeid	= NPE_B,
+} npeconfig[NPE_MAX] = {
+	[NPE_A] = {
+	  .imageid	= IXP425_NPE_A_IMAGEID,
+	  .macbase	= IXP435_MAC_A_HWBASE,
+	  .macsize	= IXP435_MAC_A_SIZE,
+	  .miibase	= IXP435_MAC_A_HWBASE,
+	  .miisize	= IXP435_MAC_A_SIZE,
+	  .phy		= 2,
+	  .rx_qid	= 4,
+	  .rx_freeqid	= 27,
+	  .tx_qid	= 24,
+	  .tx_doneqid	= 31
+	},
+	[NPE_B] = {
 	  .imageid	= IXP425_NPE_B_IMAGEID,
-	  .regbase	= IXP425_MAC_A_HWBASE,
-	  .regsize	= IXP425_MAC_A_SIZE,
+	  .macbase	= IXP425_MAC_A_HWBASE,
+	  .macsize	= IXP425_MAC_A_SIZE,
 	  .miibase	= IXP425_MAC_A_HWBASE,
 	  .miisize	= IXP425_MAC_A_SIZE,
 	  .phy		= 0,
@@ -180,11 +192,10 @@
 	  .tx_qid	= 24,
 	  .tx_doneqid	= 31
 	},
-	{ .desc		= "IXP NPE-C",
-	  .npeid	= NPE_C,
+	[NPE_C] = {
 	  .imageid	= IXP425_NPE_C_IMAGEID,
-	  .regbase	= IXP425_MAC_B_HWBASE,
-	  .regsize	= IXP425_MAC_B_SIZE,
+	  .macbase	= IXP425_MAC_B_HWBASE,
+	  .macsize	= IXP425_MAC_B_SIZE,
 	  .miibase	= IXP425_MAC_A_HWBASE,
 	  .miisize	= IXP425_MAC_A_SIZE,
 	  .phy		= 1,
@@ -219,6 +230,7 @@
 
 static devclass_t npe_devclass;
 
+static int	override_npeid(device_t, const char *resname, int *val);
 static int	npe_activate(device_t dev);
 static void	npe_deactivate(device_t dev);
 static int	npe_ifmedia_update(struct ifnet *ifp);
@@ -275,16 +287,38 @@
 TUNABLE_INT("hw.npe.txbuf", &npe_txbuf);
 
 static int
+unit2npeid(int unit)
+{
+	static const int npeidmap[2][3] = {
+		/* on 425 A is for HSS, B & C are for Ethernet */
+		{ NPE_B, NPE_C, -1 },	/* IXP425 */
+		/* 435 only has A & C, order C then A */
+		{ NPE_C, NPE_A, -1 },	/* IXP435 */
+	};
+	/* XXX check feature register instead */
+	return (unit < 3 ? npeidmap[
+	    (cpu_id() & CPU_ID_CPU_MASK) == CPU_ID_IXP435][unit] : -1);
+}
+
+static int
 npe_probe(device_t dev)
 {
-	int unit = device_get_unit(dev);
+	static const char *desc[NPE_MAX] = {
+		[NPE_A] = "IXP NPE-A",
+		[NPE_B] = "IXP NPE-B",
+		[NPE_C] = "IXP NPE-C"
+	};
+	int npeid;
 
-	if (unit >= NPE_PORTS_MAX) {
-		device_printf(dev, "unit %d not supported\n", unit);
+	npeid = -1;
+	if (!override_npeid(dev, "npeid", &npeid))
+		npeid = unit2npeid(device_get_unit(dev));
+	if (npeid == -1) {
+		device_printf(dev, "unit not supported\n");
 		return EINVAL;
 	}
 	/* XXX check feature register to see if enabled */
-	device_set_desc(dev, npeconfig[unit].desc);
+	device_set_desc(dev, desc[npeid]);
 	return 0;
 }
 
@@ -306,22 +340,27 @@
 	sc->sc_debug = npe_debug;
 	sc->sc_tickinterval = npe_tickinterval;
 
-	sc->sc_npe = ixpnpe_attach(dev);
+	if (!override_npeid(dev, "npeid", &sc->sc_npeid))
+		sc->sc_npeid = unit2npeid(device_get_unit(dev));
+	sc->sc_npe = ixpnpe_attach(dev, sc->sc_npeid);
 	if (sc->sc_npe == NULL) {
+		device_printf(dev, "cannot attach ixpnpe.\n");
 		error = EIO;		/* XXX */
 		goto out;
 	}
 
 	error = npe_activate(dev);
-	if (error)
+	if (error) {
+		device_printf(dev, "cannot activate npe.\n");
 		goto out;
+	}
 
 	npe_getmac(sc, eaddr);
 
 	/* NB: must be setup prior to invoking mii code */
 	sc->sc_ifp = ifp = if_alloc(IFT_ETHER);
 	if (mii_phy_probe(dev, &sc->sc_mii, npe_ifmedia_update, npe_ifmedia_status)) {
-		device_printf(dev, "Cannot find my PHY.\n");
+		device_printf(dev, "cannot find my PHY.\n");
 		error = ENXIO;
 		goto out;
 	}
@@ -548,6 +587,34 @@
 }
 
 static int
+npe_macaddr(int npeid, int *base, int *size)
+{
+	if (npeid == NPE_A) {
+		if ((cpu_id() & CPU_ID_CPU_MASK) == CPU_ID_IXP435) {
+			*base = IXP435_MAC_A_HWBASE;
+			*size = IXP435_MAC_A_SIZE;
+		} else {
+			*base = IXP425_MAC_A_HWBASE;
+			*size = IXP425_MAC_A_SIZE;
+		}
+		return 0;
+	} else if (npeid == NPE_B) {
+		if ((cpu_id() & CPU_ID_CPU_MASK) != CPU_ID_IXP435) {
+			*base = IXP425_MAC_B_HWBASE;
+			*size = IXP425_MAC_B_SIZE;
+			return 0;
+		}
+	} else if (npeid == NPE_C) {
+		if ((cpu_id() & CPU_ID_CPU_MASK) == CPU_ID_IXP435) {
+			*base = IXP435_MAC_C_HWBASE;
+			*size = IXP435_MAC_C_SIZE;
+			return 0;
+		}
+	}
+	return EINVAL;
+}
+
+static int
 override_addr(device_t dev, const char *resname, int *base, int *size)
 {
 	int unit = device_get_unit(dev);
@@ -558,14 +625,42 @@
 		return 0;
 	switch (resval[0]) {
 	case 'A':
-		*base = IXP425_MAC_A_HWBASE;
-		*size = IXP425_MAC_A_SIZE;
+		npe_macaddr(NPE_A, base, size);
 		break;
 	case 'B':
-		*base = IXP425_MAC_B_HWBASE;
-		*size = IXP425_MAC_B_SIZE;
+		if (npe_macaddr(NPE_B, base, size) != 0)
+			goto bad;
+		break;
+	case 'C':
+		if (npe_macaddr(NPE_C, base, size) != 0)
+			goto bad;
 		break;
 	default:
+	bad:
+		device_printf(dev, "Warning, bad value %s for "
+		    "npe.%d.%s ignored\n", resval, unit, resname);
+		return 0;
+	}
+	if (bootverbose)
+		device_printf(dev, "using npe.%d.%s=%s override\n",
+		    unit, resname, resval);
+	return 1;
+}
+
+static int
+override_npeid(device_t dev, const char *resname, int *npeid)
+{
+	int unit = device_get_unit(dev);
+	const char *resval;
+
+	/* XXX warn for wrong hint type */
+	if (resource_string_value("npe", unit, resname, &resval) != 0)
+		return 0;
+	switch (resval[0]) {
+	case 'A': *npeid = NPE_A; break;
+	case 'B': *npeid = NPE_B; break;
+	case 'C': *npeid = NPE_C; break;
+	default:
 		device_printf(dev, "Warning, bad value %s for "
 		    "npe.%d.%s ignored\n", resval, unit, resname);
 		return 0;
@@ -598,11 +693,26 @@
 }
 
 static int
+override_imageid(device_t dev, const char *resname, uint32_t *val)
+{
+	int unit = device_get_unit(dev);
+	int resval;
+
+	if (resource_int_value("npe", unit, resname, &resval) != 0)
+		return 0;
+	/* XXX validate */
+	if (bootverbose)
+		device_printf(dev, "using npe.%d.%s=0x%x override\n",
+		    unit, resname, resval);
+	*val = resval;
+	return 1;
+}
+
+static int
 npe_activate(device_t dev)
 {
 	struct npe_softc * sc = device_get_softc(dev);
-	int unit = device_get_unit(dev);
-	int error, i, regbase, regsize, miibase, miisize;
+	int error, i, macbase, macsize, miibase, miisize;
 	uint32_t imageid;
 
 	/*
@@ -611,42 +721,49 @@
 	 * the firmware image starting with the expected version
 	 * and then bump the minor version up to the max.
 	 */
-	imageid = npeconfig[unit].imageid;
+	if (!override_imageid(dev, "imageid", &imageid))
+		imageid = npeconfig[sc->sc_npeid].imageid;
 	for (;;) {
 		error = ixpnpe_init(sc->sc_npe, "npe_fw", imageid);
 		if (error == 0)
 			break;
 		/* ESRCH is returned when the requested image is not present */
-		if (error != ESRCH)
+		if (error != ESRCH) {
+			device_printf(dev, "cannot init NPE (error %d)\n",
+			    error);
 			return error;
+		}
 		/* bump the minor version up to the max possible */
-		if (NPEIMAGE_MINOR(imageid) == 0xff)
+		if (NPEIMAGE_MINOR(imageid) == 0xff) {
+			device_printf(dev, "cannot locate firmware "
+			    "(imageid 0x%08x)\n", imageid);
 			return error;
+		}
 		imageid++;
 	}
 
-	if (!override_addr(dev, "mac", &regbase, &regsize)) {
-		regbase = npeconfig[unit].regbase;
-		regbase = npeconfig[unit].regsize;
+	if (!override_addr(dev, "mac", &macbase, &macsize)) {
+		macbase = npeconfig[sc->sc_npeid].macbase;
+		macsize = npeconfig[sc->sc_npeid].macsize;
 	}
-	if (bus_space_map(sc->sc_iot, regbase, regsize, 0, &sc->sc_ioh)) {
-		device_printf(dev, "Cannot map registers 0x%x:0x%x\n",
-		    regbase, regsize);
+	if (bus_space_map(sc->sc_iot, macbase, macsize, 0, &sc->sc_ioh)) {
+		device_printf(dev, "cannot map mac registers 0x%x:0x%x\n",
+		    macbase, macsize);
 		return ENOMEM;
 	}
 
 	if (!override_addr(dev, "mii", &miibase, &miisize)) {
-		miibase = npeconfig[unit].miibase;
-		miisize = npeconfig[unit].miisize;
+		miibase = npeconfig[sc->sc_npeid].miibase;
+		miisize = npeconfig[sc->sc_npeid].miisize;
 	}
-	if (miibase != regbase) {
+	if (miibase != macbase) {
 		/*
 		 * PHY is mapped through a different MAC, setup an
 		 * additional mapping for frobbing the PHY registers.
 		 */
 		if (bus_space_map(sc->sc_iot, miibase, miisize, 0, &sc->sc_miih)) {
 			device_printf(dev,
-			    "Cannot map MII registers 0x%x:0x%x\n",
+			    "cannot map MII registers 0x%x:0x%x\n",
 			    miibase, miisize);
 			return ENOMEM;
 		}
@@ -703,22 +820,21 @@
 	 * when the rx q has at least one frame.  These setings can
 	 * changed at the time the q is configured.
 	 */
-	sc->rx_qid = npeconfig[unit].rx_qid;
+	sc->rx_qid = npeconfig[sc->sc_npeid].rx_qid;
 	ixpqmgr_qconfig(sc->rx_qid, npe_rxbuf, 0,  1,
 		IX_QMGR_Q_SOURCE_ID_NOT_E, npe_rxdone, sc);
-	sc->rx_freeqid = npeconfig[unit].rx_freeqid;
+	sc->rx_freeqid = npeconfig[sc->sc_npeid].rx_freeqid;
 	ixpqmgr_qconfig(sc->rx_freeqid,	npe_rxbuf, 0, npe_rxbuf/2, 0, NULL, sc);
-	/* tell the NPE to direct all traffic to rx_qid */
-#if 0
-	for (i = 0; i < 8; i++)
-#else
-device_printf(sc->sc_dev, "remember to fix rx q setup\n");
-	for (i = 0; i < 4; i++)
-#endif
+	/*
+	 * Setup the NPE to direct all traffic to rx_qid.
+	 * When QoS is enabled in the firmware there are
+	 * 8 traffic classes; otherwise just 4.
+	 */
+	for (i = 0; i < (imageid & 0xf0000 ? 8 : 4); i++)
 		npe_setrxqosentry(sc, i, 0, sc->rx_qid);
 
-	sc->tx_qid = npeconfig[unit].tx_qid;
-	sc->tx_doneqid = npeconfig[unit].tx_doneqid;
+	sc->tx_qid = npeconfig[sc->sc_npeid].tx_qid;
+	sc->tx_doneqid = npeconfig[sc->sc_npeid].tx_doneqid;
 	ixpqmgr_qconfig(sc->tx_qid, npe_txbuf, 0, npe_txbuf, 0, NULL, sc);
 	if (tx_doneqid == -1) {
 		ixpqmgr_qconfig(sc->tx_doneqid,	npe_txbuf, 0,  2,
@@ -731,11 +847,11 @@
 	 * to handle different board configs.
 	 */
 	if (!override_unit(dev, "phy", &sc->sc_phy, 0, MII_NPHY-1))
-		sc->sc_phy = npeconfig[unit].phy;
+		sc->sc_phy = npeconfig[sc->sc_npeid].phy;
 
-	KASSERT(npes[npeconfig[unit].npeid] == NULL,
-	    ("npe %u already setup", npeconfig[unit].npeid));
-	npes[npeconfig[unit].npeid] = sc;
+	KASSERT(npes[sc->sc_npeid] == NULL,
+	    ("npe %u already setup", sc->sc_npeid));
+	npes[sc->sc_npeid] = sc;
 
 	return 0;
 }
@@ -744,9 +860,8 @@
 npe_deactivate(device_t dev)
 {
 	struct npe_softc *sc = device_get_softc(dev);
-	int unit = device_get_unit(dev);
 
-	npes[npeconfig[unit].npeid] = NULL;
+	npes[sc->sc_npeid] = NULL;
 
 	/* XXX disable q's */
 	if (sc->sc_npe != NULL)
@@ -1470,10 +1585,9 @@
 static int
 npe_setrxqosentry(struct npe_softc *sc, int classix, int trafclass, int qid)
 {
-	int npeid = npeconfig[device_get_unit(sc->sc_dev)].npeid;
 	uint32_t msg[2];
 
-	msg[0] = (NPE_SETRXQOSENTRY << 24) | (npeid << 20) | classix;
+	msg[0] = (NPE_SETRXQOSENTRY << 24) | (sc->sc_npeid << 20) | classix;
 	msg[1] = (trafclass << 24) | (1 << 23) | (qid << 16) | (qid << 4);
 	return ixpnpe_sendandrecvmsg(sc->sc_npe, msg, msg);
 }

==== //depot/projects/vap/sys/arm/xscale/ixp425/if_npereg.h#3 (text+ko) ====

@@ -84,12 +84,6 @@
 	} ix_ne[NPE_MAXSEG];
 };
 
-/* NPE ID's */
-#define	NPE_A		0
-#define	NPE_B		1
-#define	NPE_C		2
-#define	NPE_MAX		(NPE_C+1)
-
 #define NPE_PORTS_MAX		2	/* logical ports */
 #define NPE_FRAME_SIZE_DEFAULT	1536
 #define NPE_FRAME_SIZE_MAX	(65536-64)

==== //depot/projects/vap/sys/arm/xscale/ixp425/ixp425_npe.c#3 (text+ko) ====

@@ -246,12 +246,48 @@
 }
 
 struct ixpnpe_softc *
-ixpnpe_attach(device_t dev)
+ixpnpe_attach(device_t dev, int npeid)
 {
+    struct npeconfig {
+	uint32_t	base;
+	uint32_t	size;
+	int		irq;
+	uint32_t	ins_memsize;
+	uint32_t	data_memsize;
+    };
+    static const struct npeconfig npeconfigs[NPE_MAX] = {
+	[NPE_A] = {
+	    .base = IXP425_NPE_A_HWBASE,
+	    .size = IXP425_NPE_A_SIZE,
+	    .irq = IXP425_INT_NPE_A,
+	    .ins_memsize = IX_NPEDL_INS_MEMSIZE_WORDS_NPEA,
+	    .data_memsize = IX_NPEDL_DATA_MEMSIZE_WORDS_NPEA
+	},
+	[NPE_B] = {
+	    .base = IXP425_NPE_B_HWBASE,
+	    .size = IXP425_NPE_B_SIZE,
+	    .irq = IXP425_INT_NPE_B,
+	    .ins_memsize = IX_NPEDL_INS_MEMSIZE_WORDS_NPEB,
+	    .data_memsize = IX_NPEDL_DATA_MEMSIZE_WORDS_NPEB
+	},
+	[NPE_C] = {
+	    .base = IXP425_NPE_C_HWBASE,
+	    .size = IXP425_NPE_C_SIZE,
+	    .irq = IXP425_INT_NPE_C,
+	    .ins_memsize = IX_NPEDL_INS_MEMSIZE_WORDS_NPEC,
+	    .data_memsize = IX_NPEDL_DATA_MEMSIZE_WORDS_NPEC
+	},
+    };
     struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
     struct ixpnpe_softc *sc;
-    bus_addr_t base;
-    int rid, irq;
+    const struct npeconfig *config;
+    int rid;
+
+    if (npeid >= NPE_MAX) {
+	device_printf(dev, "bad npeid %d passed to %s\n", npeid, __func__);
+	return NULL;
+    }
+    config = &npeconfigs[npeid];
 
     /* XXX M_BUS */
     sc = malloc(sizeof(struct ixpnpe_softc), M_TEMP, M_WAITOK | M_ZERO);
@@ -259,26 +295,11 @@
     sc->sc_iot = sa->sc_iot;
     mtx_init(&sc->sc_mtx, device_get_nameunit(dev), "npe driver", MTX_DEF);
 
-    if (device_get_unit(dev) == 0) {
-	base = IXP425_NPE_B_HWBASE;
-	sc->sc_size = IXP425_NPE_B_SIZE;
-	irq = IXP425_INT_NPE_B;
+    sc->sc_size = config->size;
+    sc->insMemSize = config->ins_memsize;	/* size of instruction memory */
+    sc->dataMemSize = config->data_memsize;	/* size of data memory */
 
-	/* size of instruction memory */
-	sc->insMemSize = IX_NPEDL_INS_MEMSIZE_WORDS_NPEB;
-	/* size of data memory */
-	sc->dataMemSize = IX_NPEDL_DATA_MEMSIZE_WORDS_NPEB;
-    } else {
-	base = IXP425_NPE_C_HWBASE;
-	sc->sc_size = IXP425_NPE_C_SIZE;
-	irq = IXP425_INT_NPE_C;
-
-	/* size of instruction memory */
-	sc->insMemSize = IX_NPEDL_INS_MEMSIZE_WORDS_NPEC;
-	/* size of data memory */
-	sc->dataMemSize = IX_NPEDL_DATA_MEMSIZE_WORDS_NPEC;
-    }
-    if (bus_space_map(sc->sc_iot, base, sc->sc_size, 0, &sc->sc_ioh))
+    if (bus_space_map(sc->sc_iot, config->base, sc->sc_size, 0, &sc->sc_ioh))
 	panic("%s: Cannot map registers", device_get_name(dev));
 
     /*
@@ -286,9 +307,9 @@
      */
     rid = 0;
     sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
-	irq, irq, 1, RF_ACTIVE);
+	config->irq, config->irq, 1, RF_ACTIVE);
     if (!sc->sc_irq)
-	panic("%s: Unable to allocate irq %u", device_get_name(dev), irq);
+	panic("%s: Unable to allocate irq %u", device_get_name(dev), config->irq);
     /* XXX could be a source of entropy */
     bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_NET | INTR_MPSAFE,
 	NULL, ixpnpe_intr, sc, &sc->sc_ih);
@@ -1326,7 +1347,7 @@
 	error = EIO;
 
     if (error)
-	device_printf(sc->sc_dev, "input FIFO timeout, msg [0x%x,0x%x]\n",
+	device_printf(sc->sc_dev, "input FIFO timeout, msg [0x%08x,0x%08x]\n",
 	    msg[0], msg[1]);
     return error;
 }

==== //depot/projects/vap/sys/arm/xscale/ixp425/ixp425_npevar.h#3 (text+ko) ====

@@ -95,11 +95,18 @@
 #define NPEFW_B_DMA		0x01020100 /* DMA only */
 /* XXX ... more not include */
 
+/* NPE ID's */
+#define	NPE_A		0
+#define	NPE_B		1
+#define	NPE_C		2
+#define	NPE_MAX		(NPE_C+1)
+
+#define	IXP425_NPE_A_IMAGEID	0x10800200
 #define	IXP425_NPE_B_IMAGEID	0x01000200
 #define	IXP425_NPE_C_IMAGEID	0x02000200
 
 struct ixpnpe_softc;
-struct ixpnpe_softc *ixpnpe_attach(device_t);
+struct ixpnpe_softc *ixpnpe_attach(device_t, int npeid);
 void	ixpnpe_detach(struct ixpnpe_softc *);
 int	ixpnpe_stopandreset(struct ixpnpe_softc *);
 int	ixpnpe_start(struct ixpnpe_softc *);


More information about the p4-projects mailing list