summaryrefslogtreecommitdiffstats
path: root/sys/dev/hea/hea_freebsd.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/hea/hea_freebsd.c')
-rw-r--r--sys/dev/hea/hea_freebsd.c425
1 files changed, 425 insertions, 0 deletions
diff --git a/sys/dev/hea/hea_freebsd.c b/sys/dev/hea/hea_freebsd.c
new file mode 100644
index 0000000..8640522
--- /dev/null
+++ b/sys/dev/hea/hea_freebsd.c
@@ -0,0 +1,425 @@
+/*-
+ * Copyright (c) 2002 Matthew N. Dodd <winter@jurai.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ *
+ * ===================================
+ * HARP | Host ATM Research Platform
+ * ===================================
+ *
+ *
+ * This Host ATM Research Platform ("HARP") file (the "Software") is
+ * made available by Network Computing Services, Inc. ("NetworkCS")
+ * "AS IS". NetworkCS does not provide maintenance, improvements or
+ * support of any kind.
+ *
+ * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
+ * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
+ * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
+ * In no event shall NetworkCS be responsible for any damages, including
+ * but not limited to consequential damages, arising from or relating to
+ * any use of the Software or related support.
+ *
+ * Copyright 1994-1998 Network Computing Services, Inc.
+ *
+ * Copies of this Software may be made, however, the above copyright
+ * notice must be reproduced on all copies.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <sys/bus.h>
+#include <sys/conf.h>
+
+#include <sys/module.h>
+#include <machine/bus_memio.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <net/if.h>
+#include <netatm/port.h>
+#include <netatm/queue.h>
+#include <netatm/atm.h>
+#include <netatm/atm_sys.h>
+#include <netatm/atm_sap.h>
+#include <netatm/atm_cm.h>
+#include <netatm/atm_if.h>
+#include <netatm/atm_stack.h>
+#include <netatm/atm_pcb.h>
+#include <netatm/atm_var.h>
+
+#include <dev/hea/eni_stats.h>
+#include <dev/hea/eni.h>
+#include <dev/hea/eni_suni.h>
+#include <dev/hea/eni_var.h>
+
+#include <dev/hea/hea_freebsd.h>
+
+devclass_t hea_devclass;
+
+static int hea_modevent(module_t, int, void *);
+
+int
+hea_alloc (device_t dev)
+{
+ struct hea_softc *sc;
+ int error;
+
+ sc = (struct hea_softc *)device_get_softc(dev);
+ error = 0;
+
+ sc->mem = bus_alloc_resource(dev, sc->mem_type, &sc->mem_rid,
+ 0, ~0, 1, RF_ACTIVE);
+ if (sc->mem == NULL) {
+ device_printf(dev, "Unable to allocate memory resource.\n");
+ error = ENXIO;
+ goto fail;
+ }
+
+ sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid,
+ 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
+ if (sc->irq == NULL) {
+ device_printf(dev, "Unable to allocate interrupt resource.\n");
+ error = ENXIO;
+ goto fail;
+ }
+
+ mtx_init(&sc->mtx, device_get_nameunit(dev), "Interrupt lock", MTX_DEF|MTX_RECURSE);
+
+fail:
+ return (error);
+}
+
+int
+hea_free (device_t dev)
+{
+ struct hea_softc *sc;
+
+ sc = (struct hea_softc *)device_get_softc(dev);
+ if (sc->mem)
+ bus_release_resource(dev, sc->mem_type, sc->mem_rid, sc->mem);
+ if (sc->irq_ih)
+ bus_teardown_intr(dev, sc->irq, sc->irq_ih);
+ if (sc->irq)
+ bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq);
+
+ /*
+ * Destroy the mutex.
+ */
+ if (mtx_initialized(&sc->mtx) != 0)
+ mtx_destroy(&sc->mtx);
+
+ return (0);
+}
+
+int
+hea_attach (device_t dev)
+{
+ struct hea_softc *sc;
+ Eni_unit *eup;
+ int error;
+ long val;
+
+ sc = (struct hea_softc *)device_get_softc(dev);
+ eup = &sc->eup;
+ error = 0;
+
+ /*
+ * Start initializing it
+ */
+ eup->eu_unit = device_get_unit(dev);
+ eup->eu_mtu = ENI_IFF_MTU;
+ eup->eu_vcc_zone = eni_vcc_zone;
+ eup->eu_nif_zone = eni_nif_zone;
+ eup->eu_ioctl = eni_atm_ioctl;
+ eup->eu_instvcc = eni_instvcc;
+ eup->eu_openvcc = eni_openvcc;
+ eup->eu_closevcc = eni_closevcc;
+ eup->eu_output = eni_output;
+
+ eup->eu_pcitag = dev;
+ eup->eu_softc = (void *)sc;
+
+ /*
+ * Map memory structures into adapter space
+ */
+ eup->eu_suni = (Eni_mem)(eup->eu_base + SUNI_OFFSET);
+ eup->eu_midway = (Eni_mem)(eup->eu_base + MIDWAY_OFFSET);
+ eup->eu_vcitbl = (VCI_Table *)(eup->eu_base + VCITBL_OFFSET);
+ eup->eu_rxdma = (Eni_mem)(eup->eu_base + RXQUEUE_OFFSET);
+ eup->eu_txdma = (Eni_mem)(eup->eu_base + TXQUEUE_OFFSET);
+ eup->eu_svclist = (Eni_mem)(eup->eu_base + SVCLIST_OFFSET);
+ eup->eu_servread = 0;
+
+ /*
+ * Reset the midway chip
+ */
+ eup->eu_midway[MIDWAY_ID] = MIDWAY_RESET;
+
+ /*
+ * Size and test adapter memory. Initialize our adapter memory
+ * allocater.
+ */
+ if (eni_init_memory(eup) < 0) {
+ /*
+ * Adapter memory test failed. Clean up and
+ * return.
+ */
+ device_printf(dev, "memory test failed.\n");
+ error = ENXIO;
+ goto fail;
+ }
+
+ if (eup->eu_type == TYPE_ADP) {
+ int i;
+#define MID_ADPMACOFF 0xffc0 /* mac address offset (adaptec only) */
+
+ for (i = 0; i < sizeof(struct mac_addr); i++) {
+ eup->eu_pif.pif_macaddr.ma_data[i] =
+ bus_space_read_1(rman_get_bustag(sc->mem),
+ rman_get_bushandle(sc->mem),
+ MID_ADPMACOFF + i);
+ }
+
+ } else
+ if (eup->eu_type == TYPE_ENI) {
+ /*
+ * Read the contents of the SEEPROM
+ */
+ eni_read_seeprom(eup);
+
+ /*
+ * Copy MAC address to PIF and config structures
+ */
+ bcopy((caddr_t)&eup->eu_seeprom[SEPROM_MAC_OFF],
+ (caddr_t)&eup->eu_pif.pif_macaddr,
+ sizeof(struct mac_addr));
+ /*
+ * Copy serial number into config space
+ */
+ eup->eu_config.ac_serial =
+ ntohl(*(u_long *)&eup->eu_seeprom[SEPROM_SN_OFF]);
+ } else {
+ device_printf(dev, "Unknown adapter type!\n");
+ error = ENXIO;
+ goto fail;
+ }
+
+ eup->eu_config.ac_macaddr = eup->eu_pif.pif_macaddr;
+
+ /*
+ * Setup some of the adapter configuration
+ */
+ /*
+ * Get MIDWAY ID
+ */
+ val = eup->eu_midway[MIDWAY_ID];
+ eup->eu_config.ac_vendor = VENDOR_ENI;
+ eup->eu_config.ac_vendapi = VENDAPI_ENI_1;
+ eup->eu_config.ac_device = DEV_ENI_155P;
+ eup->eu_config.ac_media = val & MEDIA_MASK ? MEDIA_UTP155 : MEDIA_OC3C;
+ eup->eu_pif.pif_pcr = ATM_PCR_OC3C;
+
+ /*
+ * Make a hw version number from the ID register values.
+ * Format: {Midway ID}.{Mother board ID}.{Daughter board ID}
+ */
+ snprintf(eup->eu_config.ac_hard_vers,
+ sizeof(eup->eu_config.ac_hard_vers),
+ "%ld/%ld/%ld",
+ (val >> ID_SHIFT) & ID_MASK,
+ (val >> MID_SHIFT) & MID_MASK,
+ (val >> DID_SHIFT) & DID_MASK );
+
+ /*
+ * There is no software version number
+ */
+ eup->eu_config.ac_firm_vers[0] = '\0';
+
+ /*
+ * Save device ram info for user-level programs
+ * NOTE: This really points to start of EEPROM
+ * and includes all the device registers in the
+ * lower 2 Megabytes.
+ */
+ eup->eu_config.ac_ram = (long)eup->eu_base;
+ eup->eu_config.ac_ramsize = eup->eu_ramsize + ENI_REG_SIZE;
+
+ /*
+ * Setup max VPI/VCI values
+ */
+ eup->eu_pif.pif_maxvpi = ENI_MAX_VPI;
+ eup->eu_pif.pif_maxvci = ENI_MAX_VCI;
+
+ /*
+ * Register this interface with ATM core services
+ */
+ error = atm_physif_register((Cmn_unit *)eup, ENI_DEV_NAME, eni_services);
+ if (error)
+ goto fail;
+
+ eni_units[device_get_unit(dev)] = eup;
+
+ /*
+ * Initialize driver processing
+ */
+ error = eni_init(eup);
+ if (error) {
+ device_printf(dev, "adapter init failed.\n");
+ goto fail;
+ }
+
+fail:
+ return (error);
+}
+
+int
+hea_detach (device_t dev)
+{
+ struct hea_softc *sc;
+ Eni_unit *eup;
+ int error;
+
+ sc = (struct hea_softc *)device_get_softc(dev);
+ eup = &sc->eup;
+ error = 0;
+
+ /*
+ * De-Register this interface with ATM core services
+ */
+ error = atm_physif_deregister((Cmn_unit *)eup);
+
+ /*
+ * Reset the board.
+ */
+ hea_reset(dev);
+
+ hea_free(dev);
+
+ return (error);
+}
+
+void
+hea_intr (void * arg)
+{
+ struct hea_softc *sc;
+
+ sc = (struct hea_softc *)arg;
+
+ HEA_LOCK(sc);
+ eni_intr(&sc->eup);
+ HEA_UNLOCK(sc);
+
+ return;
+}
+
+void
+hea_reset (device_t dev)
+{
+ struct hea_softc *sc;
+ Eni_unit *eup;
+
+ sc = (struct hea_softc *)device_get_softc(dev);
+ eup = &sc->eup;
+
+ /*
+ * We should really close down any open VCI's and
+ * release all memory (TX and RX) buffers. For now,
+ * we assume we're shutting the card down for good.
+ */
+
+ if (eup->eu_midway) {
+ /*
+ * Issue RESET command to Midway chip
+ */
+ eup->eu_midway[MIDWAY_ID] = MIDWAY_RESET;
+
+ /*
+ * Delay to allow everything to terminate
+ */
+ DELAY(MIDWAY_DELAY);
+ }
+
+ return;
+}
+
+static int
+hea_modevent (module_t mod, int type, void *data)
+{
+ int error;
+
+ error = 0;
+
+ switch (type) {
+ case MOD_LOAD:
+
+ eni_nif_zone = uma_zcreate("eni nif", sizeof(struct atm_nif),
+ NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
+ if (eni_nif_zone == NULL)
+ panic("%s(): uma_zcreate nif", __func__);
+ uma_zone_set_max(eni_nif_zone, 52);
+
+ eni_vcc_zone = uma_zcreate("eni vcc", sizeof(Eni_vcc),
+ NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
+ if (eni_vcc_zone == NULL)
+ panic("%s(): uma_zcreate vcc", __func__);
+ uma_zone_set_max(eni_vcc_zone, 100);
+
+ break;
+
+ case MOD_UNLOAD:
+
+ uma_zdestroy(eni_nif_zone);
+ uma_zdestroy(eni_vcc_zone);
+
+ break;
+ default:
+ break;
+ }
+
+ return (error);
+}
+
+static moduledata_t hea_moduledata = {
+ "hea",
+ hea_modevent,
+ NULL
+};
+DECLARE_MODULE(hea, hea_moduledata, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
+MODULE_VERSION(hea, 1);
OpenPOWER on IntegriCloud