diff options
Diffstat (limited to 'sys/dev/hea/eni.c')
-rw-r--r-- | sys/dev/hea/eni.c | 697 |
1 files changed, 0 insertions, 697 deletions
diff --git a/sys/dev/hea/eni.c b/sys/dev/hea/eni.c deleted file mode 100644 index d9a7ad0..0000000 --- a/sys/dev/hea/eni.c +++ /dev/null @@ -1,697 +0,0 @@ -/* - * - * =================================== - * 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/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * Efficient ENI adapter support - * ----------------------------- - * - * Module supports PCI interface to ENI adapter - * - */ - -#include <sys/param.h> -#include <sys/kernel.h> -#include <sys/systm.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/syslog.h> -#include <sys/eventhandler.h> -#include <net/if.h> - -#include <sys/bus.h> -#include <sys/conf.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/pci/pcireg.h> -#include <dev/pci/pcivar.h> - -#include <dev/hea/eni_stats.h> -#include <dev/hea/eni.h> -#include <dev/hea/eni_var.h> - -#ifndef lint -__RCSID("@(#) $FreeBSD$"); -#endif - -/* - * Typedef local functions - */ -#if 0 -static const char *eni_pci_probe(pcici_t, pcidi_t); -static void eni_pci_attach(pcici_t, int); -#endif -static int eni_get_ack(Eni_unit *); -static int eni_get_sebyte(Eni_unit *); -void eni_read_seeprom(Eni_unit *); -#if 0 -#if BSD < 199506 -static int eni_pci_shutdown(struct kern_devconf *, int); -#else -static void eni_pci_shutdown(void *, int); -#endif -static void eni_pci_reset(Eni_unit *); -#endif - -#if 0 -/* - * Used by kernel to return number of claimed devices - */ -static u_long eni_nunits; - -static struct pci_device eni_pci_device = { - ENI_DEV_NAME, - eni_pci_probe, - eni_pci_attach, - &eni_nunits, -#if BSD < 199506 - eni_pci_shutdown -#else - NULL -#endif -}; - -COMPAT_PCI_DRIVER (eni_pci, eni_pci_device); - -/* - * Called by kernel with PCI device_id which was read from the PCI - * register set. If the identified vendor is Efficient, see if we - * recognize the particular device. If so, return an identifying string, - * if not, return null. - * - * Arguments: - * config_id PCI config token - * device_id contents of PCI device ID register - * - * Returns: - * string Identifying string if we will handle this device - * NULL unrecognized vendor/device - * - */ -static const char * -eni_pci_probe ( pcici_t config_id, pcidi_t device_id ) -{ - - if ( (device_id & 0xFFFF) == EFF_VENDOR_ID ) { - switch ( (device_id >> 16) ) { - case EFF_DEV_ID: - return ( "Efficient ENI ATM Adapter" ); -/* NOTREACHED */ - break; - } - } - - return ( NULL ); -} -#endif - -/* - * The ENI-155p adapter uses an ATMEL AT24C01 serial EEPROM to store - * configuration information. The SEEPROM is accessed via two wires, - * CLOCK and DATA, which are accessible via the PCI configuration - * registers. The following macros manipulate the lines to access the - * SEEPROM. See http://www.atmel.com/atmel/products/prod162.htm for - * a description of the AT24C01 part. Value to be read/written is - * part of the per unit structure. - */ -/* - * Write bits to SEEPROM - */ -#define WRITE_SEEPROM() ( \ - { \ - (void) pci_write_config(eup->eu_pcitag, SEEPROM, \ - eup->eu_sevar, 4); \ - DELAY(SEPROM_DELAY); \ - } \ -) -/* - * Stobe first the DATA, then the CLK lines high - */ -#define STROBE_HIGH() ( \ - { \ - eup->eu_sevar |= SEPROM_DATA; WRITE_SEEPROM(); \ - eup->eu_sevar |= SEPROM_CLK; WRITE_SEEPROM(); \ - } \ -) -/* - * Strobe first the CLK, then the DATA lines high - */ -#define INV_STROBE_HIGH() ( \ - { \ - eup->eu_sevar |= SEPROM_CLK; WRITE_SEEPROM(); \ - eup->eu_sevar |= SEPROM_DATA; WRITE_SEEPROM(); \ - } \ -) -/* - * Strobe first the CLK, then the DATA lines low - companion to - * STROBE_HIGH() - */ -#define STROBE_LOW() ( \ - { \ - eup->eu_sevar &= ~SEPROM_CLK; WRITE_SEEPROM(); \ - eup->eu_sevar &= ~SEPROM_DATA; WRITE_SEEPROM(); \ - } \ -) -/* - * Strobe first the DATA, then the CLK lines low - companion to - * INV_STROBE_HIGH() - */ -#define INV_STROBE_LOW() ( \ - { \ - eup->eu_sevar &= ~SEPROM_DATA; WRITE_SEEPROM(); \ - eup->eu_sevar &= ~SEPROM_CLK; WRITE_SEEPROM(); \ - } \ -) -/* - * Strobe the CLK line high, then low - */ -#define STROBE_CLK() ( \ - { \ - eup->eu_sevar |= SEPROM_CLK; WRITE_SEEPROM(); \ - eup->eu_sevar &= ~SEPROM_CLK; WRITE_SEEPROM(); \ - } \ -) - -/* - * Look for a positive ACK from the SEEPROM. Cycle begins by asserting - * the DATA line, then the CLK line. The DATA line is then read to - * retrieve the ACK status, and then the cycle is finished by deasserting - * the CLK line, and asserting the DATA line. - * - * Arguments: - * eup pointer to per unit structure - * - * Returns: - * 0/1 value of ACK - * - */ -static int -eni_get_ack (eup) - Eni_unit *eup; -{ - int ack; - - STROBE_HIGH(); - /* - * Read DATA line from SEPROM - */ - eup->eu_sevar = pci_read_config(eup->eu_pcitag, SEEPROM, 4); - DELAY ( SEPROM_DELAY ); - ack = eup->eu_sevar & SEPROM_DATA; - - eup->eu_sevar &= ~SEPROM_CLK; - WRITE_SEEPROM(); - eup->eu_sevar |= SEPROM_DATA; - WRITE_SEEPROM(); - - return ( ack ); -} - -/* - * Read a byte from the SEEPROM. Data is read as 8 bits. There are two types - * of read operations. The first is a single byte read, the second is - * multiple sequential bytes read. Both cycles begin with a 'START' operation, - * followed by a memory address word. Following the memory address, the - * SEEPROM will send a data byte, followed by an ACK. If the host responds - * with a 'STOP' operation, then a single byte cycle is performed. If the - * host responds with an 'ACK', then the memory address is incremented, and - * the next sequential memory byte is serialized. - * - * Arguments: - * eup pointer to per unit structure - * - * Returns: - * val value of byte read from SEEPROM - * - */ -static int -eni_get_sebyte(eup) - Eni_unit *eup; -{ - int i; - int data; - int rval; - - /* Initial value */ - rval = 0; - /* Read 8 bits */ - for ( i = 0; i < 8; i++ ) { - /* Shift bits to left so the next bit goes to position 0 */ - rval <<= 1; - /* Indicate we're ready to read bit */ - STROBE_HIGH(); - /* - * Read DATA line from SEPROM - */ - data = pci_read_config(eup->eu_pcitag, SEEPROM, 4); - DELAY ( SEPROM_DELAY ); - /* (Possibly) mask bit into accumulating value */ - if ( data & SEPROM_DATA ) - rval |= 1; /* If DATA bit '1' */ - /* Indicate we're done reading this bit */ - STROBE_LOW(); - } - - /* Return acquired byte */ - return ( rval ); -} - -/* - * The AT24C01 is a 1024 bit part organized as 128 words by 8 bits. - * We will read the entire contents into the per unit structure. Later, - * we'll retrieve the MAC address and serial number from the data read. - * - * Arguments: - * eup pointer to per unit structure - * - * Returns: - * none - * - */ -void -eni_read_seeprom ( eup ) - Eni_unit *eup; -{ - int addr; - int i, j; - - /* - * Set initial state - */ - eup->eu_sevar = SEPROM_DATA | SEPROM_CLK; - WRITE_SEEPROM (); - - /* Loop for all bytes */ - for ( i = 0; i < SEPROM_SIZE ; i++ ) { - /* Send START operation */ - STROBE_HIGH(); - INV_STROBE_LOW(); - - /* - * Send address. Addresses are sent as 7 bits plus - * last bit high. - */ - addr = ((i) << 1) + 1; - /* - * Start with high order bit first working toward low - * order bit. - */ - for ( j = 7; j >= 0; j-- ) { - /* Set current bit value */ - eup->eu_sevar = ( addr >> j ) & 1 ? - eup->eu_sevar | SEPROM_DATA : - eup->eu_sevar & ~SEPROM_DATA; - WRITE_SEEPROM (); - /* Indicate we've sent it */ - STROBE_CLK(); - } - /* - * We expect a zero ACK after sending the address - */ - if ( !eni_get_ack ( eup ) ) { - /* Address okay - read data byte */ - eup->eu_seeprom[i] = eni_get_sebyte ( eup ); - /* Grab but ignore the ACK op */ - (void) eni_get_ack ( eup ); - } else { - /* Address ACK was bad - can't retrieve data byte */ - eup->eu_seeprom[i] = 0xff; - } - } - - return; -} - -#if 0 -/* - * The kernel has found a device which we are willing to support. - * We are now being called to do any necessary work to make the - * device initially usable. In our case, this means allocating - * structure memory, configuring registers, mapping device - * memory, setting pointers, registering with the core services, - * and doing the initial PDU processing configuration. - * - * Arguments: - * config_id PCI device token - * unit instance of the unit - * - * Returns: - * none - * - */ -static void -eni_pci_attach ( pcici_t config_id, int unit ) -{ - vm_offset_t va; - vm_offset_t pa; - Eni_unit *eup; - long val; - - /* - * Just checking... - */ - if ( unit >= ENI_MAX_UNITS ) { - log ( LOG_ERR, "%s%d: too many devices\n", - ENI_DEV_NAME, unit ); - return; - } - - /* - * Make sure this isn't a duplicate unit - */ - if ( eni_units[unit] != NULL ) - return; - - /* - * Allocate a new unit structure - */ - eup = (Eni_unit *) atm_dev_alloc ( sizeof(Eni_unit), sizeof(int), 0 ); - if ( eup == NULL ) - return; - - /* - * Start initializing it - */ - eup->eu_unit = unit; - eup->eu_mtu = ENI_IFF_MTU; - eup->eu_pcitag = config_id; - 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_vcc_zone = eni_vcc_zone; - eup->eu_nif_zone = eni_nif_zone; - - /* - * Enable Memory Mapping / Bus Mastering - */ - val = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG); - val |= (PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); - pci_conf_write(config_id, PCI_COMMAND_STATUS_REG, val); - - /* - * Map in adapter RAM - */ - val = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG); - if ((val & PCIM_CMD_MEMEN) == 0) { - log(LOG_ERR, "%s%d: memory mapping not enabled\n", - ENI_DEV_NAME, unit); - goto failed; - } - if ( ( pci_map_mem ( config_id, PCI_MAP_REG_START, &va, &pa ) ) == 0 ) - { - log(LOG_ERR, "%s%d: unable to map memory\n", - ENI_DEV_NAME, unit); - goto failed; - } - /* - * Map okay - retain address assigned - */ - eup->eu_base = (Eni_mem)va; - eup->eu_ram = (Eni_mem)(eup->eu_base + RAM_OFFSET); - - /* - * 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. - */ - log(LOG_ERR, "%s%d: memory test failed\n", - ENI_DEV_NAME, unit); - goto failed; - } - - /* - * 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) ); - eup->eu_config.ac_macaddr = eup->eu_pif.pif_macaddr; - - /* - * Copy serial number into config space - */ - eup->eu_config.ac_serial = - ntohl(*(u_long *)&eup->eu_seeprom[SEPROM_SN_OFF]); - - /* - * Convert Endianess on DMA - */ - val = pci_conf_read ( config_id, PCI_CONTROL_REG ); - val |= ENDIAN_SWAP_DMA; - pci_conf_write ( config_id, PCI_CONTROL_REG, val ); - - /* - * Map interrupt in - */ - if ( !pci_map_int ( config_id, eni_intr, (void *)eup, &net_imask ) ) - { - log(LOG_ERR, "%s%d: unable to map interrupt\n", - ENI_DEV_NAME, unit); - goto failed; - } - - /* - * 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; - eup->eu_config.ac_bustype = BUS_PCI; - eup->eu_config.ac_busslot = config_id->bus << 8 | config_id->slot; - - /* - * 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 - */ - if ( atm_physif_register - ( (Cmn_unit *)eup, ENI_DEV_NAME, eni_services ) != 0 ) - { - /* - * Registration failed - back everything out - */ - log(LOG_ERR, "%s%d: atm_physif_register failed\n", - ENI_DEV_NAME, unit); - goto failed; - } - - eni_units[unit] = eup; - -#if BSD >= 199506 - /* - * Add hook to out shutdown function - */ - EVENTHANDLER_REGISTER(shutdown_post_sync, eni_pci_shutdown, eup, - SHUTDOWN_PRI_DEFAULT); - -#endif - - /* - * Initialize driver processing - */ - if ( eni_init ( eup ) ) { - log(LOG_ERR, "%s%d: adapter init failed\n", - ENI_DEV_NAME, unit); - goto failed; - } - - return; - -failed: - /* - * Attach failed - clean up - */ - eni_pci_reset(eup); - (void) pci_unmap_int(config_id); - atm_dev_free(eup); - return; -} - -/* - * Device reset routine - * - * Arguments: - * eup pointer to per unit structure - * - * Returns: - * none - * - */ -static void -eni_pci_reset ( eup ) - Eni_unit *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; -} - -#if BSD < 199506 -/* - * Device shutdown routine - * - * Arguments: - * kdc pointer to device's configuration table - * force forced shutdown flag - * - * Returns: - * none - * - */ -static int -eni_pci_shutdown ( kdc, force ) - struct kern_devconf *kdc; - int force; -{ - Eni_unit *eup = NULL; - - if ( kdc->kdc_unit < eni_nunits ) { - - eup = eni_units[kdc->kdc_unit]; - if ( eup != NULL ) { - /* Do device reset */ - eni_pci_reset ( eup ); - } - } - - (void) dev_detach ( kdc ); - return ( 0 ); -} -#else -/* - * Device shutdown routine - * - * Arguments: - * howto type of shutdown - * eup pointer to device unit structure - * - * Returns: - * none - * - */ -static void -eni_pci_shutdown ( eup, howto ) - void *eup; - int howto; -{ - - /* Do device reset */ - eni_pci_reset ( eup ); - -} -#endif /* BSD < 199506 */ -#endif |