socsvn commit: r290035 - soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve

iateaca at FreeBSD.org iateaca at FreeBSD.org
Fri Aug 21 16:41:16 UTC 2015


Author: iateaca
Date: Fri Aug 21 16:41:14 2015
New Revision: 290035
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=290035

Log:
  implement the LPC attachment for the ne2k0 and ne2k1 devices

Modified:
  soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve/pci_lpc.c
  soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve/pci_ne2000.c

Modified: soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve/pci_lpc.c
==============================================================================
--- soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve/pci_lpc.c	Fri Aug 21 16:30:37 2015	(r290034)
+++ soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve/pci_lpc.c	Fri Aug 21 16:41:14 2015	(r290035)
@@ -73,6 +73,18 @@
 
 static const char *lpc_uart_names[LPC_UART_NUM] = { "COM1", "COM2" };
 
+#define LPC_NE2000_NUM	2
+
+static struct lpc_ne2000_config {
+	const char *opts;
+	uint8_t enabled;
+} lpc_ne2000[LPC_NE2000_NUM] = {{NULL, 0}, {NULL, 0}};
+
+static const char *lpc_ne2000_names[LPC_NE2000_NUM] = {"ne2k0", "ne2k1"};
+
+extern int
+lpc_ne2000_init(struct vmctx *lpc_ctx, uint8_t unit, const char *opts);
+
 /*
  * LPC device configuration is in the following form:
  * <lpc_device_name>[,<options>]
@@ -95,6 +107,15 @@
 				goto done;
 			}
 		}
+
+		for (unit = 0; unit < LPC_NE2000_NUM; unit++) {
+			if (strcasecmp(lpcdev, lpc_ne2000_names[unit]) == 0) {
+				lpc_ne2000[unit].enabled = 1;
+				lpc_ne2000[unit].opts = str;
+				error = 0;
+				goto done;
+			}
+		}
 	}
 
 done:
@@ -197,6 +218,18 @@
 		sc->enabled = 1;
 	}
 
+	/* ne2k0 and ne2k1 */
+	for (unit = 0; unit < LPC_NE2000_NUM; unit++) {
+		if (lpc_ne2000[unit].enabled) {
+			error = lpc_ne2000_init(lpc_bridge->pi_vmctx, unit,
+					lpc_ne2000[unit].opts);
+			if (error) {
+				fprintf(stderr, "Unable to initialize the "
+						"LPC ne2k%d device\n", unit);
+			}
+		}
+	}
+
 	return (0);
 }
 
@@ -379,6 +412,8 @@
 		return (-1);
 	}
 
+	lpc_bridge = pi;
+
 	if (lpc_init() != 0)
 		return (-1);
 
@@ -388,8 +423,6 @@
 	pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_BRIDGE);
 	pci_set_cfgdata8(pi, PCIR_SUBCLASS, PCIS_BRIDGE_ISA);
 
-	lpc_bridge = pi;
-
 	return (0);
 }
 

Modified: soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve/pci_ne2000.c
==============================================================================
--- soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve/pci_ne2000.c	Fri Aug 21 16:30:37 2015	(r290034)
+++ soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve/pci_ne2000.c	Fri Aug 21 16:41:14 2015	(r290035)
@@ -1,5 +1,7 @@
 
 
+#include <sys/types.h>
+#include <machine/vmm.h>
 #include <sys/ioctl.h>
 
 #include <stdio.h>
@@ -9,9 +11,11 @@
 #include <string.h>
 #include <pthread.h>
 
+#include <vmmapi.h>
 #include <net/ethernet.h>
 
 #include "pci_emul.h"
+#include "inout.h"
 #include "mevent.h"
 #include "if_edreg.h"
 
@@ -44,6 +48,8 @@
 #define NE2000_BAR_NIC		0
 #define NE2000_BAR_ASIC		1
 
+#define LPC_NE2000_NUM		2
+
 #define ED_RTL80X9_CONFIG2	0x05
 #define ED_RTL80X9_CF2_10_T		0x40
 #define ED_RTL80X9_CONFIG3	0x06
@@ -77,7 +83,7 @@
 	uint8_t remote_read;
 	uint8_t remote_write;
 
-	/* NIC memory is 16k */
+	/* NIC memory is 32k */
 	uint8_t ram[NE2000_MEM_SIZE];
 	uint8_t rcv_buf[ETHER_MAX_FRAME_LEN];
 
@@ -95,6 +101,17 @@
 	void *intr_arg;
 };
 
+static struct lpc_ne2000_softc {
+	struct ne2000_softc *ne2000_sc;
+	struct vmctx *lpc_ctx;
+	int base_addr;
+	int irq;
+	const char *name;
+} lpc_ne2000_sc[LPC_NE2000_NUM] = {
+	{NULL, NULL, 0x310, 10, "ne2k0"},
+	{NULL, NULL, 0x330, 11, "ne2k1"}
+};
+
 /*
  * NE2000 module function declarations
  */
@@ -110,7 +127,7 @@
 
 static struct ne2000_softc *
 ne2000_init(ne2000_intr_func_t intr_assert, ne2000_intr_func_t intr_deassert,
-		void *intr_arg, char *opts);
+		void *intr_arg, const char *opts);
 
 static void
 ne2000_update_intr(struct ne2000_softc *sc);
@@ -163,7 +180,7 @@
 ne2000_ether_crc32_be(const uint8_t *buf, size_t len);
 
 static int
-ne2000_parse_input(char *opts, char *tap_name, uint8_t *mac);
+ne2000_parse_input(const char *opts, char *tap_name, uint8_t *mac);
 
 /*
  * PCI NE2000 function declarations
@@ -183,6 +200,20 @@
 pci_ne2000_intr_deassert(void *arg);
 
 /*
+ * LPC NE2000 function declarations
+ */
+int
+lpc_ne2000_init(struct vmctx *lpc_ctx, uint8_t unit, const char *opts);
+static int
+lpc_ne2000_io_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+		uint32_t *eax, void *arg);
+
+static void
+lpc_ne2000_intr_assert(void *arg);
+static void
+lpc_ne2000_intr_deassert(void *arg);
+
+/*
  * NE2000 module function definitions
  */
 static void
@@ -526,9 +557,10 @@
 }
 
 static int
-ne2000_parse_input(char *opts, char *tap_name, uint8_t *mac)
+ne2000_parse_input(const char *opts, char *tap_name, uint8_t *mac)
 {
 	uint8_t len = 0;
+	char cp_opts[MAX_INPUT_LEN];
 	char *delim = NULL;
 	char *p_mac = NULL;
 	struct ether_addr *addr = NULL;
@@ -542,8 +574,10 @@
 		return 1;
 	}
 
+	strncpy(cp_opts, opts, MAX_INPUT_LEN);
+
 	/* search for mac address in the input string */
-	delim = strchr(opts, ',');
+	delim = strchr(cp_opts, ',');
 
 	if (delim != NULL) {
 		/* mark the end of the tap name */
@@ -563,7 +597,7 @@
 	}
 
 	/* copy the tap name */
-	strcpy(tap_name, opts);
+	strcpy(tap_name, cp_opts);
 
 	return 0;
 }
@@ -854,7 +888,7 @@
 
 static struct ne2000_softc *
 ne2000_init(ne2000_intr_func_t intr_assert, ne2000_intr_func_t intr_deassert,
-		void *intr_arg, char *opts)
+		void *intr_arg, const char *opts)
 {
 	struct ne2000_softc *sc = NULL;
 
@@ -1143,6 +1177,8 @@
 
 	pi->pi_arg = sc;
 
+	DPRINTF("PCI NE2000 initialized: ne2k,%s", opts);
+
 	return 0;
 }
 
@@ -1195,6 +1231,104 @@
 	return;
 }
 
+/*
+ * LPC NE2000 function definitions
+ */
+int
+lpc_ne2000_init(struct vmctx *lpc_ctx, uint8_t unit, const char *opts)
+{
+	struct ne2000_softc *sc = NULL;
+	struct inout_port iop;
+	int err;
+
+	assert(lpc_ctx != NULL);
+	assert(unit < LPC_NE2000_NUM);
+
+	if (lpc_ne2000_sc[unit].ne2000_sc != NULL) {
+		fprintf(stderr, "The LPC ne2k%d device is initialized\n", unit);
+		return 0;
+	}
+
+	/*
+	 * Allocate one io port for both NIC and ASIC I/O bus address offsets.
+	 * The NE2000 devices on the LPC bus generate edge triggered interrupts
+	 * so nothing more to do here
+	 */
+	bzero(&iop, sizeof(struct inout_port));
+	iop.name = lpc_ne2000_sc[unit].name;
+	iop.port = lpc_ne2000_sc[unit].base_addr;
+	iop.size = ED_NOVELL_IO_PORTS;
+	iop.flags = IOPORT_F_INOUT;
+	iop.handler = lpc_ne2000_io_handler;
+	iop.arg = &lpc_ne2000_sc[unit];
+
+	err = register_inout(&iop);
+	assert(err == 0);
+
+	/* initialize the ne2000 data structure */
+	sc = ne2000_init(lpc_ne2000_intr_assert, lpc_ne2000_intr_deassert,
+			&lpc_ne2000_sc[unit], opts);
+	if (sc == NULL)
+		return -1;
+
+	lpc_ne2000_sc[unit].ne2000_sc = sc;
+	lpc_ne2000_sc[unit].lpc_ctx = lpc_ctx;
+
+	DPRINTF("LPC NE2000 initialized: %s,%s", lpc_ne2000_sc[unit].name, opts);
+
+	return 0;
+}
+
+static int
+lpc_ne2000_io_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+		uint32_t *eax, void *arg)
+{
+	struct lpc_ne2000_softc *sc_lpc_ne2000 = (struct lpc_ne2000_softc *)arg;
+	struct ne2000_softc *sc = NULL;
+
+	uint8_t offset = 0;
+	int err;
+
+	assert(sc_lpc_ne2000 != NULL);
+
+	sc = sc_lpc_ne2000->ne2000_sc;
+	assert(sc != NULL);
+
+	offset = port - sc_lpc_ne2000->base_addr;
+
+	if (in) {
+		*eax = ne2000_read(sc, offset, bytes);
+	}
+	else {
+		err = ne2000_write(sc, offset, *eax, bytes);
+		assert(err == 0);
+	}
+
+	return 0;
+}
+
+static void
+lpc_ne2000_intr_assert(void *arg)
+{
+	struct lpc_ne2000_softc *sc_lpc_ne2000 = (struct lpc_ne2000_softc *)arg;
+	struct vmctx *lpc_ctx = sc_lpc_ne2000->lpc_ctx;
+
+	vm_isa_pulse_irq(lpc_ctx, sc_lpc_ne2000->irq, sc_lpc_ne2000->irq);
+
+	return;
+}
+
+static void
+lpc_ne2000_intr_deassert(void *arg)
+{
+	/*
+	 * The NE2000 devices on the LPC bus generate edge triggered interrupts
+	 * so nothing more to do here
+	 */
+
+	return;
+}
+
 struct pci_devemu pci_de_ne2000_net = {
 	.pe_emu         = "ne2000-net",
 	.pe_init        = pci_ne2000_init,


More information about the svn-soc-all mailing list