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