diff options
Diffstat (limited to 'sys/dev/hea/hea_freebsd.c')
-rw-r--r-- | sys/dev/hea/hea_freebsd.c | 425 |
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); |