freebsd-skq/sys/dev/hea/hea_freebsd.c
Andrew R. Reiter b6037a7953 - Turn the hea and hfa HARP storage pools into UMA zones and insert
the necesary uma_zcreate() and uma_zdestroy calls into module loading
  handler and the device attach handling.
- Change the related HARP netatm code to use UMA zone functions when
  dealing with the zones that were formerly the ATM interface (hea, hfa)
  storage pools.
- Have atm_physif_freenifs() now get passed an uma_zone_t so that we can
  properly free the allocated NIF's back to their zone.

This should be the last commit to remove any code that makes use of the
netatm storage pool api.  I will be removing the api code within the near
future.

Reviewed by:	mdodd
2002-06-14 16:59:38 +00:00

393 lines
9.5 KiB
C

/*-
* 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;
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;
eni_vcc_zone = uma_zcreate("eni vcc", sizeof(Eni_vcc), NULL,
NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
if (eni_vcc_zone == NULL)
panic("hea_attach: uma_zcreate vcc");
uma_zone_set_max(eni_vcc_zone, 100);
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("hea_attach: uma_zcreate nif");
uma_zone_set_max(eni_nif_zone, 52);
/*
* 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;
/*
* 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);
uma_zdestroy(eni_vcc_zone);
uma_zdestroy(eni_nif_zone);
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;
}