Index: head/sys/dev/hea/eni.c =================================================================== --- head/sys/dev/hea/eni.c (revision 98222) +++ head/sys/dev/hea/eni.c (revision 98223) @@ -1,695 +1,695 @@ /* * * =================================== * 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. * * @(#) $FreeBSD$ * */ /* * Efficient ENI adapter support * ----------------------------- * * Module supports PCI interface to ENI adapter * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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_pool = &eni_vcc_pool; - eup->eu_nif_pool = &eni_nif_pool; + 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 Index: head/sys/dev/hea/eni.h =================================================================== --- head/sys/dev/hea/eni.h (revision 98222) +++ head/sys/dev/hea/eni.h (revision 98223) @@ -1,503 +1,503 @@ /* * * =================================== * 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. * * @(#) $FreeBSD$ * */ /* * Efficient ENI Adapter Support * * Protocol and implementation definitions * */ #ifndef _ENI_ENI_H #define _ENI_ENI_H #include #include /* * Physical device name - used to configure HARP devices */ #ifndef ENI_DEV_NAME #define ENI_DEV_NAME "hea" /* HARP Efficient ATM */ #endif #define ENI_MAX_UNITS 4 #define ENI_IFF_MTU 9188 #define ENI_MAX_VCI 1023 /* 0 - 1023 */ #define ENI_MAX_VPI 0 #define ENI_IFQ_MAXLEN 1000 /* rx/tx queue lengths */ #ifdef BSD /* * Size of small and large receive buffers */ #define ENI_SMALL_BSIZE 64 #define ENI_LARGE_BSIZE MCLBYTES #endif /* BSD */ /* * ENI memory map offsets IN WORDS, not bytes * * The Efficient Adapter implements a 4 MB address space. The lower * 2 MB are used by bootprom (E)EPROM and by chipset registers such * as the MIDWAY and SUNI chips. The (upto) upper 2 MB is used for * RAM. Of the RAM, the lower 28 KB is used for fixed tables - the * VCI table, the RX and TX DMA queues, and the Service List queue. * Memory above the 28 KB range is available for RX and TX buffers. * * NOTE: Access to anything other then the (E)EPROM MUST be as a 32 bit * access. Also note that Efficient uses both byte addresses and word * addresses when describing offsets. BE CAREFUL or you'll get confused! */ /* * Size of memory space reserved for registers and expansion (e)eprom. */ #define ENI_REG_SIZE 0x200000 /* Two megabytes */ #define SUNI_OFFSET 0x008000 /* SUNI chip registers */ #define MIDWAY_OFFSET 0x010000 /* MIDWAY chip registers */ #define RAM_OFFSET 0x080000 /* Adapter RAM */ #define VCITBL_OFFSET 0x080000 /* VCI Table offset */ #define RXQUEUE_OFFSET 0x081000 /* RX DMA Queue offset */ #define TXQUEUE_OFFSET 0x081400 /* TX DMA Queue offset */ #define SVCLIST_OFFSET 0x081800 /* SVC List Queue offset */ #define SEGBUF_BASE 0x007000 /* Base from start of RAM */ #define DMA_LIST_SIZE 512 /* 1024 words / 2 words per entry */ #define SVC_LIST_SIZE 1024 /* 1024 words / 1 word per entry */ /* * Values for testing size of RAM on adapter * * Efficient has (at least) two different memory sizes available. One * is a client card which has either 128 KB or 512 KB RAM, the other * is a server card which has 2 MB RAM. The driver will size and test * the memory to correctly determine what's available. */ #define MAX_ENI_MEM 0x200000 /* 2 MB - max. mem supported */ #define TEST_STEP 0x000400 /* Look at 1 KB steps */ #define TEST_PAT 0xA5A5A5A5 /* Test pattern */ /* * Values for memory allocator */ #define ENI_BUF_PGSZ 1024 /* Allocation unit of buffers */ #define ENI_BUF_NBIT 8 /* Number of bits to get from */ /* min buffer (1KB) to max (128KB) */ /* * Values for allocating TX buffers */ #define MAX_CLIENT_RAM 512 /* Most RAM a client card will have */ #define TX_SMALL_BSIZE 32 /* Small buffer - 32KB */ #define TX_LARGE_BSIZE 128 /* Large buffer - 128KB */ /* * Values for allocating RX buffers */ #define RX_SIG_BSIZE 4 /* Signalling buffer - 4KB */ #define RX_CLIENT_BSIZE 16 /* Client buffer - 16KB */ #define RX_SERVER_BSIZE 32 /* Server buffer - 32KB */ /* * Adapter bases all addresses off of some power from 1KB. Thus, it * only needs to store the most sigificant bits and can drop the lower * 10 bits. */ #define ENI_LOC_PREDIV 10 /* Bits location is shifted */ /* Location is prescaled by 1KB */ /* before use in various places */ #define MIDWAY_DELAY 10 /* Time to wait for Midway finish */ /* * Define the MIDWAY register offsets and any interesting bits within * the register */ #define MIDWAY_ID 0x00 /* ID/Reset register */ #define MIDWAY_RESET 0 /* iWrite of any value */ #define ID_SHIFT 27 /* Midway ID version */ #define ID_MASK 0x1F /* ID mask */ #define MID_SHIFT 7 /* Mother board ID */ #define MID_MASK 0x7 /* MID mask */ #define DID_SHIFT 0 /* Daughter board ID */ #define DID_MASK 0x1F /* DID mask */ /* * Efficient defines the following IDs for their adapters: * 0x420/0x620 - SONET MMF, client memory size * 0x430/0x630 - SONET MMF, server memory size * 0x424/0x624 - UTP-5, client memory size * 0x434/0x634 - UTP-5, server memory size */ #define MEDIA_MASK 0x04 /* Mask off UTP-5/MMF media */ #define MIDWAY_ISA 0x01 /* Interrupt Status Ack. */ /* Reading this register */ /* also acknowledges the */ /* posted interrupt(s) */ #define MIDWAY_IS 0x02 /* Interrupt Status */ /* Reading this register */ /* does NOT acknowledge the */ /* posted interrupt(s) */ /* Interrupt names */ #define ENI_INT_STAT 0x00000001 #define ENI_INT_SUNI 0x00000002 #define ENI_INT_SERVICE 0x00000004 #define ENI_INT_TX_DMA 0x00000008 #define ENI_INT_RX_DMA 0x00000010 #define ENI_INT_DMA_ERR 0x00000020 #define ENI_INT_DMA_LERR 0x00000040 #define ENI_INT_IDEN 0x00000080 #define ENI_INT_DMA_OVFL 0x00000100 #define ENI_INT_TX_MASK 0x0001FE00 #define MIDWAY_IE 0x03 /* Interrupt Enable register */ /* Interrupt enable bits are the same as the Interrupt names */ #define MIDWAY_MASTER 0x04 /* Master Control */ /* Master control bits */ #define ENI_M_WAIT500 0x00000001 /* Disable interrupts .5 ms */ #define ENI_M_WAIT1 0x00000002 /* Disable interrupts 1 ms */ #define ENI_M_RXENABLE 0x00000004 /* Enable RX engine */ #define ENI_M_TXENABLE 0x00000008 /* Enable TX engine */ #define ENI_M_DMAENABLE 0x00000010 /* Enable DMA */ #define ENI_M_TXLOCK 0x00000020 /* 0: Streaming, 1: Lock */ #define ENI_M_INTSEL 0x000001C0 /* Int Select mask */ #define ENI_ISEL_SHIFT 6 /* Bits to shift ISEL value */ #define MIDWAY_STAT 0x05 /* Statistics register */ #define MIDWAY_SVCWR 0x06 /* Svc List write pointer */ #define SVC_SIZE_MASK 0x3FF /* Valid bits in svc pointer */ #define MIDWAY_DMAADDR 0x07 /* Current virtual DMA addr */ #define MIDWAY_RX_WR 0x08 /* Write ptr to RX DMA queue */ #define MIDWAY_RX_RD 0x09 /* Read ptr to RX DMA queue */ #define MIDWAY_TX_WR 0x0A /* Write ptr to TX DMA queue */ #define MIDWAY_TX_RD 0x0B /* Read ptr to TX DMA queue */ /* * Registers 0x0C - 0x0F are unused */ /* * MIDWAY supports 8 transmit channels. Each channel has 3 registers * to control operation. Each new channel starts on N * 4 set. Thus, * channel 0 uses register 0x10 - 0x13, channel 1 uses 0x14 - 0x17, etc. * Register 0x13 + N * 4 is unused. */ #define MIDWAY_TXPLACE 0x10 /* Channel N TX location */ #define TXSIZE_SHIFT 11 /* Bits to shift size by */ #define TX_PLACE_MASK 0x7FF /* Valid bits in TXPLACE */ #define MIDWAY_RDPTR 0x11 /* Channel N Read ptr */ #define MIDWAY_DESCR 0x12 /* Channel N Descr ptr */ /* * Register 0x30 on up are unused */ /* * Part of PCI configuration registers but not defined in */ #define PCI_CONTROL_REG 0x60 #define ENDIAN_SWAP_DMA 0x80 /* Enable endian swaps on DMA */ /* * The Efficient adapter references adapter RAM through the use of * location and size values. Eight sizes are defined. When allocating * buffers, there size must be rounded up to the next size which will * hold the requested size. Buffers are allocated on 'SIZE' boundaries. * See eni_buffer.c for more info. */ /* * Buffer SIZE definitions - in words, so from 1 KB to 128 KB */ #define SIZE_256 0x00 #define SIZE_512 0x01 #define SIZE_1K 0x02 #define SIZE_2K 0x03 #define SIZE_4K 0x04 #define SIZE_8K 0x05 #define SIZE_16K 0x06 #define SIZE_32K 0x07 /* * Define values for DMA type - DMA descriptors include a type field and a * count field except in the special case of JK (just-kidding). With type JK, * the count field should be set to the address which will be loaded * into the pointer, ie. where the pointer should next point to, since * JK doesn't have a "size" associated with it. JK DMA is used to skip * over descriptor words, and to strip off padding of AAL5 PDUs. The * DMA_nWORDM types will do a n word DMA burst, but the count field * does not have to equal n. Any difference results in garbage filling * the remaining words of the DMA. These types could be used where a * particular burst size yields better DMA performance. */ #define DMA_WORD 0x00 #define DMA_BYTE 0x01 #define DMA_HWORD 0x02 #define DMA_JK 0x03 #define DMA_4WORD 0x04 #define DMA_8WORD 0x05 #define DMA_16WORD 0x06 #define DMA_2WORD 0x07 #define DMA_4WORDM 0x0C #define DMA_8WORDM 0x0D #define DMA_16WORDM 0x0E #define DMA_2WORDM 0x0F /* * Define the size of the local DMA list we'll build before * giving up on the PDU. */ #define TEMP_DMA_SIZE 120 /* Enough for 58/59 buffers */ #define DMA_COUNT_SHIFT 16 /* Number of bits to shift count */ /* in DMA descriptor word */ #define DMA_VCC_SHIFT 6 /* Number of bits to shift RX VCC or */ /* TX channel in DMA descriptor word */ #define DMA_END_BIT 0x20 /* Signal end of DMA list */ /* * Defines for VCI table * * The VCI table is a 1K by 4 word table allowing up to 1024 (0-1023) * VCIs. Entries into the table use the VCI number as the index. */ struct vci_table { u_long vci_control; /* Control word */ u_long vci_descr; /* Descr/ReadPtr */ u_long vci_write; /* WritePtr/State/Cell count */ u_long vci_crc; /* ongoing CRC calculation */ }; typedef volatile struct vci_table VCI_Table; #define VCI_MODE_SHIFT 30 /* Shift to get MODE field */ #define VCI_MODE_MASK 0x3FFFFFFF /* Bits to strip MODE off */ #define VCI_PTI_SHIFT 29 /* Shift to get PTI mode field */ #define VCI_LOC_SHIFT 18 /* Shift to get location field */ #define VCI_LOC_MASK 0x7FF /* Valid bits in location field */ #define VCI_SIZE_SHIFT 15 /* Shift to get size field */ #define VCI_SIZE_MASK 7 /* Valid bits in size field */ #define VCI_IN_SERVICE 1 /* Mask for IN_SERVICE field */ /* * Defines for VC mode */ #define VCI_MODE_TRASH 0x00 /* Trash all cells for this VC */ #define VCI_MODE_AAL0 0x01 /* Reassemble as AAL_0 PDU */ #define VCI_MODE_AAL5 0x02 /* Reassemble as AAL_5 PDU */ /* * Defines for handling cells with PTI(2) set to 1. */ #define PTI_MODE_TRASH 0x00 /* Trash cell */ #define PTI_MODE_PRESV 0x01 /* Send cell to OAM channel */ /* * Current state of VC */ #define VCI_STATE_IDLE 0x00 /* VC is idle */ #define VCI_STATE_REASM 0x01 /* VC is reassembling PDU */ #define VCI_STATE_TRASH 0x03 /* VC is trashing cells */ /* * RX Descriptor word values */ #define DESCR_TRASH_BIT 0x1000 /* VCI was trashing cells */ #define DESCR_CRC_ERR 0x0800 /* PDU has CRC error */ #define DESCR_CELL_COUNT 0x07FF /* Mask to get cell count */ /* * TX Descriptor word values */ #define TX_IDEN_SHIFT 28 /* Unique identifier location */ #define TX_MODE_SHIFT 27 /* AAL5 or AAL0 */ #define TX_VCI_SHIFT 4 /* Bits to shift VCI value */ /* * When setting up descriptor words (at head of segmentation queues), there * is a unique identifier used to help detect sync problems. */ #define MIDWAY_UNQ_ID 0x0B /* * Defines for cell sizes */ #define BYTES_PER_CELL 48 /* Number of data bytes per cell */ #define WORDS_PER_CELL 12 /* Number of data words per cell */ /* * Access to Serial EEPROM [as opposed to expansion (E)PROM]. * * This is a ATMEL AT24C01 serial EEPROM part. * See http://www.atmel.com/atmel/products/prod162.htm for timimg diagrams * for START/STOP/ACK/READ cycles. */ #define SEEPROM PCI_CONTROL_REG /* Serial EEPROM is accessed thru */ /* PCI control register */ #define SEPROM_DATA 0x02 /* SEEPROM DATA line */ #define SEPROM_CLK 0x01 /* SEEPROM CLK line */ #define SEPROM_SIZE 128 /* Size of Serial EEPROM */ #define SEPROM_MAC_OFF 64 /* Offset to MAC address */ #define SEPROM_SN_OFF 112 /* Offset to serial number */ #define SEPROM_DELAY 10 /* Delay when strobing CLK/DATA lines */ /* * Host protocol control blocks * */ /* * Device VCC Entry * * Contains the common and ENI-specific information for each VCC * which is opened through a ENI device. */ struct eni_vcc { struct cmn_vcc ev_cmn; /* Common VCC stuff */ caddr_t ev_rxbuf; /* Receive buffer */ u_long ev_rxpos; /* Adapter buffer read pointer */ }; typedef struct eni_vcc Eni_vcc; #define ev_next ev_cmn.cv_next #define ev_toku ev_cmn.cv_toku #define ev_upper ev_cmn.cv_upper #define ev_connvc ev_cmn.cv_connvc #define ev_state ev_cmn.cv_state typedef volatile unsigned long * Eni_mem; /* * Define the ID's we'll look for in the PCI config * register when deciding if we'll support this device. * The DEV_ID will need to be turned into an array of * ID's in order to support multiple adapters with * the same driver. */ #define EFF_VENDOR_ID 0x111A #define EFF_DEV_ID 0x0002 /* * Memory allocator defines and buffer descriptors */ #define MEM_FREE 0 #define MEM_INUSE 1 typedef struct mbd Mbd; struct mbd { Mbd *prev; Mbd *next; caddr_t base; /* Adapter base address */ int size; /* Size of buffer */ int state; /* INUSE or FREE */ }; /* * We use a hack to allocate a smaller RX buffer for signalling * channels as they tend to have small MTU lengths. */ #define UNI_SIG_VCI 5 /* * Device Unit Structure * * Contains all the information for a single device (adapter). */ struct eni_unit { Cmn_unit eu_cmn; /* Common unit stuff */ void * eu_pcitag; /* PCI tag */ Eni_mem eu_base; /* Adapter memory base */ Eni_mem eu_ram; /* Adapter RAM */ u_long eu_ramsize; Eni_mem eu_suni; /* SUNI registers */ Eni_mem eu_midway; /* MIDWAY registers */ VCI_Table *eu_vcitbl; /* VCI Table */ Eni_mem eu_rxdma; /* Receive DMA queue */ Eni_mem eu_txdma; /* Transmit DMA queue */ Eni_mem eu_svclist; /* Service list */ u_long eu_servread; /* Read pointer into Service list */ caddr_t eu_txbuf; /* One large TX buff for everything */ u_long eu_txsize; /* Size of TX buffer */ u_long eu_txpos; /* Current word being stored in RAM */ u_long eu_txfirst; /* First word of unack'ed data */ u_long eu_trash; u_long eu_ovfl; struct ifqueue eu_txqueue; u_long eu_txdmawr; struct ifqueue eu_rxqueue; u_long eu_rxdmawr; /* DMA list write pointer */ u_char eu_seeprom[SEPROM_SIZE]; /* Serial EEPROM contents */ u_int eu_sevar; /* Unique (per unit) seeprom var. */ Mbd *eu_memmap; /* Adapter RAM memory allocator map */ int eu_memclicks[ENI_BUF_NBIT];/* Count of INUSE buffers */ Eni_stats eu_stats; /* Statistics */ int eu_type; #define TYPE_UNKNOWN 0 #define TYPE_ENI 1 #define TYPE_ADP 2 }; typedef struct eni_unit Eni_unit; #define eu_pif eu_cmn.cu_pif #define eu_unit eu_cmn.cu_unit #define eu_flags eu_cmn.cu_flags #define eu_mtu eu_cmn.cu_mtu #define eu_open_vcc eu_cmn.cu_open_vcc #define eu_vcc eu_cmn.cu_vcc -#define eu_vcc_pool eu_cmn.cu_vcc_pool -#define eu_nif_pool eu_cmn.cu_nif_pool +#define eu_vcc_zone eu_cmn.cu_vcc_zone +#define eu_nif_zone eu_cmn.cu_nif_zone #define eu_ioctl eu_cmn.cu_ioctl #define eu_instvcc eu_cmn.cu_instvcc #define eu_openvcc eu_cmn.cu_openvcc #define eu_closevcc eu_cmn.cu_closevcc #define eu_output eu_cmn.cu_output #define eu_config eu_cmn.cu_config #endif /* _ENI_ENI_H */ Index: head/sys/dev/hea/eni_globals.c =================================================================== --- head/sys/dev/hea/eni_globals.c (revision 98222) +++ head/sys/dev/hea/eni_globals.c (revision 98223) @@ -1,114 +1,104 @@ /* * * =================================== * 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. * * @(#) $FreeBSD$ * */ /* * Efficient ENI Adapter Support * ----------------------------- * * Global variable definitions * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include + #ifndef lint __RCSID("@(#) $FreeBSD$"); #endif /* * Device unit table */ Eni_unit *eni_units[ENI_MAX_UNITS] = {NULL}; /* * ATM Interface services */ /* * AAL5 service stack */ static struct stack_defn eni_svaal5 = { NULL, SAP_CPCS_AAL5, SDF_TERM, atm_dev_inst, atm_dev_lower, NULL, 0, }; /* * Efficient hardware doesn't support AAL3/4. Don't define * an AAL3/4 stack. */ /* * AAL0 service stack */ static struct stack_defn eni_svaal0 = { &eni_svaal5, SAP_ATM, SDF_TERM, atm_dev_inst, atm_dev_lower, NULL, 0, }; struct stack_defn *eni_services = &eni_svaal0; /* * Storage pools */ -struct sp_info eni_nif_pool = { - "eni nif pool", /* si_name */ - sizeof(struct atm_nif), /* si_blksiz */ - 5, /* si_blkcnt */ - 52 /* si_maxallow */ -}; - -struct sp_info eni_vcc_pool = { - "eni vcc pool", /* si_name */ - sizeof(Eni_vcc), /* si_blksiz */ - 10, /* si_blkcnt */ - 100 /* si_maxallow */ -}; - +uma_zone_t eni_nif_zone; +uma_zone_t eni_vcc_zone; Index: head/sys/dev/hea/eni_var.h =================================================================== --- head/sys/dev/hea/eni_var.h (revision 98222) +++ head/sys/dev/hea/eni_var.h (revision 98223) @@ -1,85 +1,85 @@ /* * * =================================== * 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. * * @(#) $FreeBSD$ * */ /* * Efficient ENI Adapter Support * ----------------------------- * * Local driver include files and global declarations * */ #ifndef _ENI_ENI_VAR_H #define _ENI_ENI_VAR_H /* * Global function declarations */ /* eni_buffer.c */ int eni_init_memory(Eni_unit *); caddr_t eni_allocate_buffer(Eni_unit *, u_long *); void eni_free_buffer(Eni_unit *, caddr_t); /* eni_if.c */ int eni_atm_ioctl(int, caddr_t, caddr_t); void eni_zero_stats(Eni_unit *); /* eni_init.c */ int eni_init(Eni_unit *); /* eni_intr.c */ #if defined(BSD) && BSD < 199506 int eni_intr(void *); #else void eni_intr(void *); #endif /* eni_receive.c */ void eni_do_service(Eni_unit *); void eni_recv_drain(Eni_unit *); /* eni_transmit.c */ int eni_set_dma(Eni_unit *, int, u_long *, int, long *, int, u_long, int ); void eni_output(Cmn_unit *, Cmn_vcc *, KBuffer *); void eni_xmit_drain(Eni_unit *); /* eni_vcm.c */ int eni_instvcc(Cmn_unit *, Cmn_vcc *); int eni_openvcc(Cmn_unit *, Cmn_vcc *); int eni_closevcc(Cmn_unit *, Cmn_vcc *); /* * Global variable declarations */ extern Eni_unit *eni_units[]; extern struct stack_defn *eni_services; -extern struct sp_info eni_nif_pool; -extern struct sp_info eni_vcc_pool; +extern uma_zone_t eni_nif_zone; +extern uma_zone_t eni_vcc_zone; #endif /* _ENI_ENI_VAR_H */ Index: head/sys/dev/hea/hea_freebsd.c =================================================================== --- head/sys/dev/hea/hea_freebsd.c (revision 98222) +++ head/sys/dev/hea/hea_freebsd.c (revision 98223) @@ -1,377 +1,392 @@ /*- * Copyright (c) 2002 Matthew N. Dodd * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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_pool = &eni_vcc_pool; - eup->eu_nif_pool = &eni_nif_pool; + 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; } Index: head/sys/dev/hfa/fore_globals.c =================================================================== --- head/sys/dev/hfa/fore_globals.c (revision 98222) +++ head/sys/dev/hfa/fore_globals.c (revision 98223) @@ -1,126 +1,116 @@ /* * * =================================== * 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. * * @(#) $FreeBSD$ * */ /* * FORE Systems 200-Series Adapter Support * --------------------------------------- * * Global variable definitions * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include + #ifndef lint __RCSID("@(#) $FreeBSD$"); #endif /* * Device unit table */ Fore_unit *fore_units[FORE_MAX_UNITS] = {NULL}; int fore_nunits = 0; /* * ATM Interface services */ static struct stack_defn fore_svaal5 = { NULL, SAP_CPCS_AAL5, SDF_TERM, atm_dev_inst, atm_dev_lower, NULL, 0, }; static struct stack_defn fore_svaal4 = { &fore_svaal5, SAP_CPCS_AAL3_4, SDF_TERM, atm_dev_inst, atm_dev_lower, NULL, 0, }; static struct stack_defn fore_svaal0 = { &fore_svaal4, SAP_ATM, SDF_TERM, atm_dev_inst, atm_dev_lower, NULL, 0, }; struct stack_defn *fore_services = &fore_svaal0; /* * Storage pools */ -struct sp_info fore_nif_pool = { - "fore nif pool", /* si_name */ - sizeof(struct atm_nif), /* si_blksiz */ - 5, /* si_blkcnt */ - 52 /* si_maxallow */ -}; - -struct sp_info fore_vcc_pool = { - "fore vcc pool", /* si_name */ - sizeof(Fore_vcc), /* si_blksiz */ - 10, /* si_blkcnt */ - 100 /* si_maxallow */ -}; - +uma_zone_t fore_nif_zone; +uma_zone_t fore_vcc_zone; /* * Watchdog timer */ struct atm_time fore_timer = {0, 0}; Index: head/sys/dev/hfa/fore_include.h =================================================================== --- head/sys/dev/hfa/fore_include.h (revision 98222) +++ head/sys/dev/hfa/fore_include.h (revision 98223) @@ -1,108 +1,108 @@ /* * * =================================== * 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. * * @(#) $FreeBSD$ * */ /* * FORE Systems 200-Series Adapter Support * --------------------------------------- * * Local driver include files and global declarations * */ #ifndef _FORE_INCLUDE_H #define _FORE_INCLUDE_H /* * Global function declarations */ /* fore_buffer.c */ int fore_buf_allocate(Fore_unit *); void fore_buf_initialize(Fore_unit *); void fore_buf_supply(Fore_unit *); void fore_buf_free(Fore_unit *); /* fore_command.c */ int fore_cmd_allocate(Fore_unit *); void fore_cmd_initialize(Fore_unit *); void fore_cmd_drain(Fore_unit *); void fore_cmd_free(Fore_unit *); /* fore_if.c */ int fore_atm_ioctl(int, caddr_t, caddr_t); void fore_interface_free(Fore_unit *); /* fore_init.c */ void fore_initialize(Fore_unit *); void fore_initialize_complete(Fore_unit *); /* fore_intr.c */ void fore_intr(void *); void fore_watchdog(Fore_unit *); /* fore_load.c */ /* fore_output.c */ void fore_output(Cmn_unit *, Cmn_vcc *, KBuffer *); /* fore_receive.c */ int fore_recv_allocate(Fore_unit *); void fore_recv_initialize(Fore_unit *); void fore_recv_drain(Fore_unit *); void fore_recv_free(Fore_unit *); /* fore_stats.c */ int fore_get_stats(Fore_unit *); /* fore_timer.c */ void fore_timeout(struct atm_time *); /* fore_transmit.c */ int fore_xmit_allocate(Fore_unit *); void fore_xmit_initialize(Fore_unit *); void fore_xmit_drain(Fore_unit *); void fore_xmit_free(Fore_unit *); /* fore_vcm.c */ int fore_instvcc(Cmn_unit *, Cmn_vcc *); int fore_openvcc(Cmn_unit *, Cmn_vcc *); int fore_closevcc(Cmn_unit *, Cmn_vcc *); /* * Global variable declarations */ extern Fore_device fore_devices[]; extern Fore_unit *fore_units[]; extern int fore_nunits; extern struct stack_defn *fore_services; -extern struct sp_info fore_nif_pool; -extern struct sp_info fore_vcc_pool; +extern uma_zone_t fore_nif_zone; +extern uma_zone_t fore_vcc_zone; extern struct atm_time fore_timer; #endif /* _FORE_INCLUDE_H */ Index: head/sys/dev/hfa/fore_load.c =================================================================== --- head/sys/dev/hfa/fore_load.c (revision 98222) +++ head/sys/dev/hfa/fore_load.c (revision 98223) @@ -1,615 +1,615 @@ /* * * =================================== * 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. * * @(#) $FreeBSD$ * */ #ifdef COMPILING_LINT #warning "The fore pci driver is broken and is not compiled with LINT" #else /* * FORE Systems 200-Series Adapter Support * --------------------------------------- * * Loadable kernel module and device identification support * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef lint __RCSID("@(#) $FreeBSD$"); #endif static int fore_probe(device_t); static int fore_attach(device_t); static int fore_detach(device_t); static int fore_shutdown(device_t); #ifndef COMPAT_OLDPCI #error "The fore device requires the old pci compatibility shims" #endif static int fore_inited = 0; static u_long fore_pci_count = 0; static device_method_t fore_methods[] = { DEVMETHOD(device_probe, fore_probe), DEVMETHOD(device_attach, fore_attach), DEVMETHOD(device_detach, fore_detach), DEVMETHOD(device_shutdown, fore_shutdown), { 0, 0 } }; static struct fore_ident fore_ident_table[] = { { 0x0200, "FORE Systems PCA-200 ATM ForeRunner" }, { 0x0210, "FORE Systems PCA-200PC" }, { 0x0250, "FORE Systems ATM" }, { 0x0300, "FORE Systems PCA-200E" }, { 0x0310, "FORE Systems ATM" }, { 0x0400, "FORE Systems PCA-200HE ATM ForeRunner" }, { 0, NULL }, }; /* * Initialize driver processing * * This will be called during module loading. Not much to do here, as * we must wait for our identify/attach routines to get called before * we know what we're in for. * * Arguments: * none * * Returns: * 0 startup was successful * errno startup failed - reason indicated * */ static int fore_start() { /* * Verify software version */ if (atm_version != ATM_VERSION) { log(LOG_ERR, "version mismatch: fore=%d.%d kernel=%d.%d\n", ATM_VERS_MAJ(ATM_VERSION), ATM_VERS_MIN(ATM_VERSION), ATM_VERS_MAJ(atm_version), ATM_VERS_MIN(atm_version)); return (EINVAL); } /* * Initialize DMA mapping */ DMA_INIT(); /* * Start up watchdog timer */ atm_timeout(&fore_timer, ATM_HZ * FORE_TIME_TICK, fore_timeout); fore_inited = 1; return (0); } /* * Device probe routine * * Determine if this driver will support the identified device. If we claim * to support the device, our attach routine will (later) be called for the * device. */ static int fore_probe(device_t dev) { struct fore_ident *ident; u_int16_t devid; if (pci_get_vendor(dev) == FORE_VENDOR_ID) { devid = pci_get_device(dev); for (ident = fore_ident_table; ident->name != NULL; ident++) if (ident->devid == devid) { device_set_desc(dev, ident->name); return (0); } } return (ENXIO); } /* * Device attach routine * * Attach a device we've previously claimed to support. Walk through its * register set and map, as required. Determine what level the device will * be interrupting at and then register an interrupt handler for it. If we * succeed, then reset the adapter and initialize the microcode. * Last, register the interface with the kernel ATM services. * * Arguments: * config_id device's PCI configuration ID * unit device unit number * * Returns: * none * */ static void fore_pci_attach(config_id, unit) pcici_t config_id; int unit; { Fore_unit *fup; vm_offset_t va; vm_offset_t pa; pcidi_t device_id; long val; int err_count = BOOT_LOOPS; /* * Check that unit is not >= FORE_MAX_UNITS */ /* * Make sure this isn't a duplicate unit */ if (fore_units[unit] != NULL) return; /* * Allocate a new unit structure */ fup = (Fore_unit *) atm_dev_alloc(sizeof(Fore_unit), sizeof(int), 0); if (fup == NULL) return; /* * Start initializing it */ fup->fu_unit = unit; fup->fu_mtu = FORE_IFF_MTU; fup->fu_pcitag = config_id; - fup->fu_vcc_pool = &fore_vcc_pool; - fup->fu_nif_pool = &fore_nif_pool; + fup->fu_vcc_zone = fore_vcc_zone; + fup->fu_nif_zone = &fore_nif_zone; fup->fu_ioctl = fore_atm_ioctl; fup->fu_instvcc = fore_instvcc; fup->fu_openvcc = fore_openvcc; fup->fu_closevcc = fore_closevcc; fup->fu_output = fore_output; callout_handle_init(&fup->fu_thandle); /* * Get our device type */ device_id = pci_conf_read ( config_id, PCI_ID_REG ); switch ((device_id >> 16) & 0xffff) { case FORE_PCA200E_ID: fup->fu_config.ac_device = DEV_FORE_PCA200E; break; default: fup->fu_config.ac_device = DEV_UNKNOWN; } /* * 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 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", FORE_DEV_NAME, unit); goto failed; } if ((pci_map_mem(config_id, PCA200E_PCI_MEMBASE, &va, &pa)) == 0) { log(LOG_ERR, "%s%d: unable to map memory\n", FORE_DEV_NAME, unit); goto failed; } fup->fu_ram = (Fore_mem *)va; fup->fu_ramsize = PCA200E_RAM_SIZE; fup->fu_mon = (Mon960 *)(fup->fu_ram + MON960_BASE); fup->fu_ctlreg = (Fore_reg *)(va + PCA200E_HCR_OFFSET); fup->fu_imask = (Fore_reg *)(va + PCA200E_IMASK_OFFSET); fup->fu_psr = (Fore_reg *)(va + PCA200E_PSR_OFFSET); /* * Convert Endianess of Slave RAM accesses */ val = pci_conf_read(config_id, PCA200E_PCI_MCTL); val |= PCA200E_MCTL_SWAP; pci_conf_write(config_id, PCA200E_PCI_MCTL, val); /* * Map interrupt in */ if ( !pci_map_int( config_id, fore_intr, fup, &net_imask ) ) { log(LOG_ERR, "%s%d: unable to map interrupt\n", FORE_DEV_NAME, unit); goto failed; } /* * Poke the hardware - boot the CP and prepare it for downloading */ fore_reset(fup); /* * Wait for the monitor to perform self-test */ while (CP_READ(fup->fu_mon->mon_bstat) != BOOT_MONREADY) { if (CP_READ(fup->fu_mon->mon_bstat) == BOOT_FAILTEST) { log(LOG_ERR, "%s%d: failed self-test\n", FORE_DEV_NAME, unit); goto failed; } else if ( --err_count == 0 ) { log(LOG_ERR, "%s%d: unable to boot - status=0x%lx\n", FORE_DEV_NAME, unit, (u_long)CP_READ(fup->fu_mon->mon_bstat)); goto failed; } DELAY ( BOOT_DELAY ); } /* * Setup the adapter config info - at least as much as we can */ fup->fu_config.ac_vendor = VENDOR_FORE; fup->fu_config.ac_vendapi = VENDAPI_FORE_1; fup->fu_config.ac_media = MEDIA_OC3C; fup->fu_pif.pif_pcr = ATM_PCR_OC3C; fup->fu_config.ac_bustype = BUS_PCI; fup->fu_config.ac_busslot = config_id->bus << 8 | config_id->slot; /* * Save device ram info for user-level programs */ fup->fu_config.ac_ram = (long)fup->fu_ram; fup->fu_config.ac_ramsize = fup->fu_ramsize; /* * Set device capabilities */ fup->fu_pif.pif_maxvpi = FORE_MAX_VPI; fup->fu_pif.pif_maxvci = FORE_MAX_VCI; /* * Register this interface with ATM core services */ if ( atm_physif_register ((Cmn_unit *)fup, FORE_DEV_NAME, fore_services) != 0 ) { /* * Registration failed - back everything out */ goto failed; } fore_units[unit] = fup; fore_nunits++; /* * Add hook to our shutdown function */ EVENTHANDLER_REGISTER(shutdown_post_sync, fore_pci_shutdown, fup, SHUTDOWN_PRI_DEFAULT); /* * Initialize the CP microcode program. */ fore_initialize(fup); return; failed: /* * Unattach the device from the system */ fore_unattach(fup); /* * Free any Fore-specific device resources */ fore_interface_free(fup); atm_dev_free(fup); return; } /* * Device shutdown routine * * Arguments: * howto type of shutdown * fup pointer to device unit structure * * Returns: * none * */ static void fore_pci_shutdown(fup, howto) void *fup; int howto; { fore_reset((Fore_unit *) fup); return; } /* * Device unattach routine * * Reset the physical device, remove any pending timeouts, * unmap any register sets, and unregister any interrupts. * * Arguments: * fup pointer to device unit structure * * Returns: * none */ static void fore_unattach(fup) Fore_unit *fup; { /* * Reset the board and return it to cold_start state. * Hopefully, this will prevent use of resources as * we're trying to free things up. */ fore_reset(fup); /* * Lock out all device interrupts */ DEVICE_LOCK((Cmn_unit *)fup); /* * Remove any pending timeout()'s */ (void)untimeout((KTimeout_ret(*)(void *))fore_initialize, (void *)fup, fup->fu_thandle); /* * Unmap the device interrupt */ (void) pci_unmap_int(fup->fu_pcitag); /* * Unmap memory */ #ifdef notdef (void) pci_unmap_mem(fup->fu_pcitag, PCA200E_PCI_MEMBASE); #endif DEVICE_UNLOCK((Cmn_unit *)fup); } /* * Device reset routine * * Reset the physical device * * Arguments: * fup pointer to device unit structure * * Returns: * none */ static void fore_reset(fup) Fore_unit *fup; { int s = splimp(); /* * Reset the board and return it to cold_start state */ if (fup->fu_mon) fup->fu_mon->mon_bstat = CP_WRITE(BOOT_COLDSTART); if (fup->fu_ctlreg) { if (fup->fu_config.ac_device == DEV_FORE_PCA200E) { /* * Reset i960 by setting and clearing RESET */ PCA200E_HCR_INIT(*fup->fu_ctlreg, PCA200E_RESET); DELAY(10000); PCA200E_HCR_CLR(*fup->fu_ctlreg, PCA200E_RESET); } } (void) splx(s); return; } #ifndef ATM_LINKED /* ******************************************************************* * * Loadable Module Support * ******************************************************************* */ #ifdef notdef /* * Driver entry points */ static struct cdevsw fore_cdev = { /* open */ noopen, /* close */ noclose, /* read */ noread, /* write */ nowrite, /* ioctl */ noioctl, /* poll */ nopoll, /* mmap */ nommap, /* strategy */ nostrategy, /* name */ noname, /* maj */ -1, /* dump */ nodump, /* psize */ nopsize, /* flags */ 0, }; /* * Loadable device driver module description */ MOD_DEV(fore, LM_DT_CHAR, -1, (void *)&fore_cdev); /* * Loadable module support "load" entry point * * This is the routine called by the lkm driver whenever the * modload(1) command is issued for this module. * * Arguments: * lkmtp pointer to lkm drivers's structure * cmd lkm command code * * Returns: * 0 command was successful * errno command failed - reason indicated * */ static int fore_load(lkmtp, cmd) struct lkm_table *lkmtp; int cmd; { return(fore_doload()); } /* * Loadable module support "unload" entry point * * This is the routine called by the lkm driver whenever the * modunload(1) command is issued for this module. * * Arguments: * lkmtp pointer to lkm drivers's structure * cmd lkm command code * * Returns: * 0 command was successful * errno command failed - reason indicated * */ static int fore_unload(lkmtp, cmd) struct lkm_table *lkmtp; int cmd; { return(fore_dounload()); } /* * Loadable module support entry point * * This is the routine called by the lkm driver for all loadable module * functions for this driver. This routine name must be specified * on the modload(1) command. This routine will be called whenever the * modload(1), modunload(1) or modstat(1) commands are issued for this * module. * * Arguments: * lkmtp pointer to lkm drivers's structure * cmd lkm command code * ver lkm version * * Returns: * 0 command was successful * errno command failed - reason indicated * */ int fore_mod(lkmtp, cmd, ver) struct lkm_table *lkmtp; int cmd; int ver; { DISPATCH(lkmtp, cmd, ver, fore_load, fore_unload, lkm_nullcmd); } #endif /* notdef */ #endif /* ATM_LINKED */ #endif Index: head/sys/dev/hfa/fore_var.h =================================================================== --- head/sys/dev/hfa/fore_var.h (revision 98222) +++ head/sys/dev/hfa/fore_var.h (revision 98223) @@ -1,261 +1,261 @@ /* * * =================================== * 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. * * @(#) $FreeBSD$ * */ /* * FORE Systems 200-Series Adapter Support * --------------------------------------- * * Host protocol control blocks * */ #ifndef _FORE_VAR_H #define _FORE_VAR_H /* * Device VCC Entry * * Contains the common and Fore-specific information for each VCC * which is opened through a Fore device. */ struct fore_vcc { struct cmn_vcc fv_cmn; /* Common VCC stuff */ Fore_aal fv_aal; /* CP version of AAL */ }; typedef struct fore_vcc Fore_vcc; #define fv_next fv_cmn.cv_next #define fv_toku fv_cmn.cv_toku #define fv_upper fv_cmn.cv_upper #define fv_connvc fv_cmn.cv_connvc #define fv_state fv_cmn.cv_state #define fv_flags fv_cmn.cv_flags /* * VCC Flags */ #define FVF_ACTCMD 0x01 /* Activate command issued */ /* * Host Transmit Queue Element * * Defines the host's view of the CP PDU Transmit Queue */ struct h_xmit_queue { struct h_xmit_queue *hxq_next; /* Next element in queue */ Xmit_queue *hxq_cpelem; /* CP queue element */ Q_status *hxq_status; /* Element status word */ Xmit_descr *hxq_descr; /* Element's transmit descriptor */ Xmit_descr *hxq_descr_dma; /* Element's transmit descriptor */ Fore_vcc *hxq_vcc; /* Data's VCC */ KBuffer *hxq_buf; /* Data's buffer chain head */ H_dma hxq_dma[XMIT_MAX_SEGS]; /* DMA addresses for segments */ }; typedef struct h_xmit_queue H_xmit_queue; /* * Host Receive Queue Element * * Defines the host's view of the CP PDU Receive Queue */ struct h_recv_queue { struct h_recv_queue *hrq_next; /* Next element in queue */ Recv_queue *hrq_cpelem; /* CP queue element */ Q_status *hrq_status; /* Element status word */ Recv_descr *hrq_descr; /* Element's receive descriptor */ Recv_descr *hrq_descr_dma; /* Element's receive descriptor */ }; typedef struct h_recv_queue H_recv_queue; /* * Host Buffer Supply Queue Element * * Defines the host's view of the CP Buffer Supply Queue */ struct h_buf_queue { struct h_buf_queue *hbq_next; /* Next element in queue */ Buf_queue *hbq_cpelem; /* CP queue element */ Q_status *hbq_status; /* Element status word */ Buf_descr *hbq_descr; /* Element's buffer descriptor array */ Buf_descr *hbq_descr_dma; /* Element's buffer descriptor array */ }; typedef struct h_buf_queue H_buf_queue; /* * Host Command Queue Element * * Defines the host's view of the CP Command Queue */ struct h_cmd_queue { struct h_cmd_queue *hcq_next; /* Next element in queue */ Cmd_queue *hcq_cpelem; /* CP queue element */ Q_status *hcq_status; /* Element status word */ Cmd_code hcq_code; /* Command code */ void *hcq_arg; /* Command-specific argument */ }; typedef struct h_cmd_queue H_cmd_queue; /* * Host Buffer Handle * * For each buffer supplied to the CP, there will be one of these structures * embedded into the non-data portion of the buffer. This will allow us to * track which buffers are currently "controlled" by the CP. The address of * this structure will supplied to/returned from the CP as the buffer handle. */ struct buf_handle { Qelem_t bh_qelem; /* Queuing element */ u_int bh_type; /* Buffer type (see below) */ H_dma bh_dma; /* Buffer DMA address */ }; typedef struct buf_handle Buf_handle; #define SIZEOF_Buf_handle 16 /* * Buffer Types */ #define BHT_S1_SMALL 1 /* Buffer strategy 1, small */ #define BHT_S1_LARGE 2 /* Buffer strategy 1, large */ #define BHT_S2_SMALL 3 /* Buffer strategy 2, small */ #define BHT_S2_LARGE 4 /* Buffer strategy 2, large */ /* * Device Unit Structure * * Contains all the information for a single device (adapter). */ struct fore_unit { Cmn_unit fu_cmn; /* Common unit stuff */ Fore_reg *fu_ctlreg; /* Device control register */ Fore_reg *fu_imask; /* Interrupt mask register */ Fore_reg *fu_psr; /* PCI specific register */ #ifdef COMPAT_OLDPCI pcici_t fu_pcitag; /* PCI tag */ #endif Fore_mem *fu_ram; /* Device RAM */ u_int fu_ramsize; /* Size of device RAM */ Mon960 *fu_mon; /* Monitor program interface */ Aali *fu_aali; /* Microcode program interface */ u_int fu_timer; /* Watchdog timer value */ /* Transmit Queue */ H_xmit_queue fu_xmit_q[XMIT_QUELEN]; /* Host queue */ H_xmit_queue *fu_xmit_head; /* Queue head */ H_xmit_queue *fu_xmit_tail; /* Queue tail */ Q_status *fu_xmit_stat; /* Status array (host) */ Q_status *fu_xmit_statd; /* Status array (DMA) */ /* Receive Queue */ H_recv_queue fu_recv_q[RECV_QUELEN]; /* Host queue */ H_recv_queue *fu_recv_head; /* Queue head */ Q_status *fu_recv_stat; /* Status array (host) */ Q_status *fu_recv_statd; /* Status array (DMA) */ Recv_descr *fu_recv_desc; /* Descriptor array (host) */ Recv_descr *fu_recv_descd; /* Descriptor array (DMA) */ /* Buffer Supply Queue - Strategy 1 Small */ H_buf_queue fu_buf1s_q[BUF1_SM_QUELEN]; /* Host queue */ H_buf_queue *fu_buf1s_head; /* Queue head */ H_buf_queue *fu_buf1s_tail; /* Queue tail */ Q_status *fu_buf1s_stat; /* Status array (host) */ Q_status *fu_buf1s_statd;/* Status array (DMA) */ Buf_descr *fu_buf1s_desc; /* Descriptor array (host) */ Buf_descr *fu_buf1s_descd;/* Descriptor array (DMA) */ Queue_t fu_buf1s_bq; /* Queue of supplied buffers */ u_int fu_buf1s_cnt; /* Count of supplied buffers */ /* Buffer Supply Queue - Strategy 1 Large */ H_buf_queue fu_buf1l_q[BUF1_LG_QUELEN]; /* Host queue */ H_buf_queue *fu_buf1l_head; /* Queue head */ H_buf_queue *fu_buf1l_tail; /* Queue tail */ Q_status *fu_buf1l_stat; /* Status array (host) */ Q_status *fu_buf1l_statd;/* Status array (DMA) */ Buf_descr *fu_buf1l_desc; /* Descriptor array (host) */ Buf_descr *fu_buf1l_descd;/* Descriptor array (DMA) */ Queue_t fu_buf1l_bq; /* Queue of supplied buffers */ u_int fu_buf1l_cnt; /* Count of supplied buffers */ /* Command Queue */ H_cmd_queue fu_cmd_q[CMD_QUELEN]; /* Host queue */ H_cmd_queue *fu_cmd_head; /* Queue head */ H_cmd_queue *fu_cmd_tail; /* Queue tail */ Q_status *fu_cmd_stat; /* Status array (host) */ Q_status *fu_cmd_statd; /* Status array (DMA) */ Fore_stats *fu_stats; /* Device statistics buffer */ Fore_stats *fu_statsd; /* Device statistics buffer (DMA) */ time_t fu_stats_time; /* Last stats request timestamp */ int fu_stats_ret; /* Stats request return code */ Fore_prom *fu_prom; /* Device PROM buffer */ Fore_prom *fu_promd; /* Device PROM buffer (DMA) */ struct callout_handle fu_thandle; /* Timer handle */ }; typedef struct fore_unit Fore_unit; #define fu_pif fu_cmn.cu_pif #define fu_unit fu_cmn.cu_unit #define fu_flags fu_cmn.cu_flags #define fu_mtu fu_cmn.cu_mtu #define fu_open_vcc fu_cmn.cu_open_vcc #define fu_vcc fu_cmn.cu_vcc #define fu_intrpri fu_cmn.cu_intrpri #define fu_savepri fu_cmn.cu_savepri -#define fu_vcc_pool fu_cmn.cu_vcc_pool -#define fu_nif_pool fu_cmn.cu_nif_pool +#define fu_vcc_zone fu_cmn.cu_vcc_zone +#define fu_nif_zone fu_cmn.cu_nif_zone #define fu_ioctl fu_cmn.cu_ioctl #define fu_instvcc fu_cmn.cu_instvcc #define fu_openvcc fu_cmn.cu_openvcc #define fu_closevcc fu_cmn.cu_closevcc #define fu_output fu_cmn.cu_output #define fu_config fu_cmn.cu_config /* * Device flags (in addition to CUF_* flags) */ #define FUF_STATCMD 0x80 /* Statistics request in progress */ /* * Macros to access CP memory */ #define CP_READ(x) ntohl((u_long)(x)) #define CP_WRITE(x) htonl((u_long)(x)) #endif /* _FORE_VAR_H */ Index: head/sys/dev/hfa/hfa_freebsd.c =================================================================== --- head/sys/dev/hfa/hfa_freebsd.c (revision 98222) +++ head/sys/dev/hfa/hfa_freebsd.c (revision 98223) @@ -1,416 +1,432 @@ /*- * Copyright (c) 2002 Matthew N. Dodd * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include devclass_t hfa_devclass; static int hfa_modevent(module_t, int, void *); int hfa_alloc (device_t dev) { struct hfa_softc *sc; int error; sc = (struct hfa_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 hfa_free (device_t dev) { struct hfa_softc *sc; sc = (struct hfa_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 hfa_attach (device_t dev) { struct hfa_softc *sc; Fore_unit *fup; int error; int err_count; sc = (struct hfa_softc *)device_get_softc(dev); fup = &sc->fup; error = 0; err_count = BOOT_LOOPS; /* * Start initializing it */ fup->fu_unit = device_get_unit(dev); fup->fu_mtu = FORE_IFF_MTU; - fup->fu_vcc_pool = &fore_vcc_pool; - fup->fu_nif_pool = &fore_nif_pool; + fup->fu_vcc_zone = fore_vcc_zone; + fup->fu_nif_zone = fore_nif_zone; fup->fu_ioctl = fore_atm_ioctl; fup->fu_instvcc = fore_instvcc; fup->fu_openvcc = fore_openvcc; fup->fu_closevcc = fore_closevcc; fup->fu_output = fore_output; callout_handle_init(&fup->fu_thandle); /* * Poke the hardware - boot the CP and prepare it for downloading */ hfa_reset(dev); /* * Wait for the monitor to perform self-test */ while (CP_READ(fup->fu_mon->mon_bstat) != BOOT_MONREADY) { if (CP_READ(fup->fu_mon->mon_bstat) == BOOT_FAILTEST) { device_printf(dev, "failed self-test\n"); goto fail; } else if ( --err_count == 0 ) { device_printf(dev, "unable to boot - status=0x%lx\n", (u_long)CP_READ(fup->fu_mon->mon_bstat)); goto fail; } DELAY ( BOOT_DELAY ); } /* * Setup the adapter config info - at least as much as we can */ fup->fu_config.ac_vendor = VENDOR_FORE; fup->fu_config.ac_vendapi = VENDAPI_FORE_1; fup->fu_config.ac_media = MEDIA_OC3C; fup->fu_pif.pif_pcr = ATM_PCR_OC3C; /* * Save device ram info for user-level programs */ fup->fu_config.ac_ram = (long)fup->fu_ram; fup->fu_config.ac_ramsize = fup->fu_ramsize; /* * Set device capabilities */ fup->fu_pif.pif_maxvpi = FORE_MAX_VPI; fup->fu_pif.pif_maxvci = FORE_MAX_VCI; /* * Register this interface with ATM core services */ error = atm_physif_register((Cmn_unit *)fup, FORE_DEV_NAME, fore_services); if (error) goto fail; fore_units[device_get_unit(dev)] = fup; fore_nunits++; /* * Initialize the CP microcode program. */ fore_initialize(fup); fail: return (error); } int hfa_detach (device_t dev) { struct hfa_softc *sc; Fore_unit *fup; int error; sc = (struct hfa_softc *)device_get_softc(dev); fup = &sc->fup; error = 0; /* * De-Register this interface with ATM core services */ error = atm_physif_deregister((Cmn_unit *)fup); /* * Reset the board and return it to cold_start state. * Hopefully, this will prevent use of resources as * we're trying to free things up. */ hfa_reset(dev); /* * Lock out all device interrupts */ DEVICE_LOCK((Cmn_unit *)fup); /* * Remove any pending timeout()'s */ (void)untimeout((KTimeout_ret(*)(void *))fore_initialize, (void *)fup, fup->fu_thandle); hfa_free(dev); DEVICE_UNLOCK((Cmn_unit *)fup); /* * Free any Fore-specific device resources */ fore_interface_free(fup); return (error); } void hfa_intr (void * arg) { struct hfa_softc *sc; sc = (struct hfa_softc *)arg; HFA_LOCK(sc); fore_intr(&sc->fup); HFA_UNLOCK(sc); return; } void hfa_reset (device_t dev) { struct hfa_softc *sc; Fore_unit *fup; sc = (struct hfa_softc *)device_get_softc(dev); fup = &sc->fup; HFA_LOCK(sc); /* * Reset the board and return it to cold_start state */ if (fup->fu_mon) fup->fu_mon->mon_bstat = CP_WRITE(BOOT_COLDSTART); if (fup->fu_ctlreg) { switch (fup->fu_config.ac_device) { case DEV_FORE_ESA200E: break; case DEV_FORE_SBA200E: /* * Reset i960 by setting and clearing RESET */ SBA200E_HCR_INIT(*fup->fu_ctlreg, SBA200E_RESET); SBA200E_HCR_CLR(*fup->fu_ctlreg, SBA200E_RESET); break; case DEV_FORE_SBA200: /* * Reset i960 by setting and clearing RESET * * SBA200 will NOT reset if bit is OR'd in! */ *fup->fu_ctlreg = SBA200_RESET; *fup->fu_ctlreg = SBA200_RESET_CLR; break; case DEV_FORE_PCA200E: /* * Reset i960 by setting and clearing RESET */ PCA200E_HCR_INIT(*fup->fu_ctlreg, PCA200E_RESET); DELAY(10000); PCA200E_HCR_CLR(*fup->fu_ctlreg, PCA200E_RESET); break; default: break; } } HFA_UNLOCK(sc); return; } static int hfa_modevent (module_t mod, int what, void *arg) { int error; error = 0; switch (what) { case MOD_LOAD: /* * Verify software version */ if (atm_version != ATM_VERSION) { printf("hfa: version mismatch: fore=%d.%d kernel=%d.%d\n", ATM_VERS_MAJ(ATM_VERSION), ATM_VERS_MIN(ATM_VERSION), ATM_VERS_MAJ(atm_version), ATM_VERS_MIN(atm_version)); error = EINVAL; break; } + + fore_nif_zone = uma_zcreate("fore nif", sizeof(struct atm_nif), NULL, + NULL, NULL, NULL, UMA_ALIGN_PTR, 0); + if (fore_nif_zone == NULL) + panic("hfa_modevent:uma_zcreate nif"); + uma_zone_set_max(fore_nif_zone, 52); + + fore_vcc_zone = uma_zcreate("fore vcc", sizeof(Fore_vcc), NULL, + NULL, NULL, NULL, UMA_ALIGN_PTR, 0); + if (fore_vcc_zone == NULL) + panic("hfa_modevent: uma_zcreate vcc"); + uma_zone_set_max(fore_vcc_zone, 100); + /* * Initialize DMA mapping */ DMA_INIT(); /* * Start up watchdog timer */ atm_timeout(&fore_timer, ATM_HZ * FORE_TIME_TICK, fore_timeout); break; case MOD_UNLOAD: /* * Release DMA mapping */ DMA_RELEASE(); /* * Stop watchdog timer */ atm_untimeout(&fore_timer); + + uma_zdestroy(fore_nif_zone); + uma_zdestroy(fore_vcc_zone); break; default: break; } return (error); } static moduledata_t hfa_moduledata = { "hfa", hfa_modevent, NULL }; DECLARE_MODULE(hfa, hfa_moduledata, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); MODULE_VERSION(hfa, 1); Index: head/sys/netatm/atm_device.c =================================================================== --- head/sys/netatm/atm_device.c (revision 98222) +++ head/sys/netatm/atm_device.c (revision 98223) @@ -1,813 +1,814 @@ /* * * =================================== * 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. * * @(#) $FreeBSD$ * */ /* * Core ATM Services * ----------------- * * ATM device support functions * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef lint __RCSID("@(#) $FreeBSD$"); #endif /* * Private structures for managing allocated kernel memory resources * * For each allocation of kernel memory, one Mem_ent will be used. * The Mem_ent structures will be allocated in blocks inside of a * Mem_blk structure. */ #define MEM_NMEMENT 10 /* How many Mem_ent's in a Mem_blk */ struct mem_ent { void *me_kaddr; /* Allocated memory address */ u_int me_ksize; /* Allocated memory length */ void *me_uaddr; /* Memory address returned to caller */ u_int me_flags; /* Flags (see below) */ }; typedef struct mem_ent Mem_ent; /* * Memory entry flags */ #define MEF_NONCACHE 1 /* Memory is noncacheable */ struct mem_blk { struct mem_blk *mb_next; /* Next block in chain */ Mem_ent mb_mement[MEM_NMEMENT]; /* Allocated memory entries */ }; typedef struct mem_blk Mem_blk; static Mem_blk *atm_mem_head = NULL; static struct t_atm_cause atm_dev_cause = { T_ATM_ITU_CODING, T_ATM_LOC_USER, T_ATM_CAUSE_VPCI_VCI_ASSIGNMENT_FAILURE, {0, 0, 0, 0} }; /* * ATM Device Stack Instantiation * * Called at splnet. * * Arguments * ssp pointer to array of stack definition pointers * for connection * ssp[0] points to upper layer's stack definition * ssp[1] points to this layer's stack definition * ssp[2] points to lower layer's stack definition * cvcp pointer to connection vcc for this stack * * Returns * 0 instantiation successful * err instantiation failed - reason indicated * */ int atm_dev_inst(ssp, cvcp) struct stack_defn **ssp; Atm_connvc *cvcp; { Cmn_unit *cup = (Cmn_unit *)cvcp->cvc_attr.nif->nif_pif; Cmn_vcc *cvp; int err; /* * Check to see if device has been initialized */ if ((cup->cu_flags & CUF_INITED) == 0) return ( EIO ); /* * Validate lower SAP */ /* * Device driver is the lowest layer - no need to validate */ /* * Validate PVC vpi.vci */ if (cvcp->cvc_attr.called.addr.address_format == T_ATM_PVC_ADDR) { /* * Look through existing circuits - return error if found */ Atm_addr_pvc *pp; pp = (Atm_addr_pvc *)cvcp->cvc_attr.called.addr.address; if (atm_dev_vcc_find(cup, ATM_PVC_GET_VPI(pp), ATM_PVC_GET_VCI(pp), 0)) return ( EADDRINUSE ); } /* * Validate our SAP type */ switch ((*(ssp+1))->sd_sap) { case SAP_CPCS_AAL3_4: case SAP_CPCS_AAL5: case SAP_ATM: break; default: return (EINVAL); } /* * Allocate a VCC control block */ - if ( ( cvp = (Cmn_vcc *)atm_allocate(cup->cu_vcc_pool) ) == NULL ) - return ( ENOMEM ); + cvp = uma_zalloc(cup->cu_vcc_zone, M_WAITOK); + if (cvp == NULL) + return (ENOMEM); cvp->cv_state = CVS_INST; cvp->cv_toku = (*ssp)->sd_toku; cvp->cv_upper = (*ssp)->sd_upper; cvp->cv_connvc = cvcp; /* * Let device have a look at the connection request */ err = (*cup->cu_instvcc)(cup, cvp); if (err) { - atm_free((caddr_t)cvp); + uma_zfree(cup->cu_vcc_zone, cvp); return (err); } /* * Looks good so far, so link in device VCC */ LINK2TAIL ( cvp, Cmn_vcc, cup->cu_vcc, cv_next ); /* * Save my token */ (*++ssp)->sd_toku = cvp; /* * Pass instantiation down the stack */ /* * No need - we're the lowest point. */ /* err = (*(ssp + 1))->sd_inst(ssp, cvcp); */ /* * Save the lower layer's interface info */ /* * No need - we're the lowest point */ /* cvp->cv_lower = (*++ssp)->sd_lower; */ /* cvp->cv_tok1 = (*ssp)->sd_toku; */ return (0); } /* * ATM Device Stack Command Handler * * Arguments * cmd stack command code * tok session token (Cmn_vcc) * arg1 command specific argument * arg2 command specific argument * * Returns * none * */ /*ARGSUSED*/ void atm_dev_lower(cmd, tok, arg1, arg2) int cmd; void *tok; int arg1; int arg2; { Cmn_vcc *cvp = (Cmn_vcc *)tok; Atm_connvc *cvcp = cvp->cv_connvc; Cmn_unit *cup = (Cmn_unit *)cvcp->cvc_attr.nif->nif_pif; struct vccb *vcp; u_int state; int s; switch ( cmd ) { case CPCS_INIT: /* * Sanity check */ if ( cvp->cv_state != CVS_INST ) { log ( LOG_ERR, "atm_dev_lower: INIT: tok=%p, state=%d\n", tok, cvp->cv_state ); break; } vcp = cvp->cv_connvc->cvc_vcc; /* * Validate SVC vpi.vci */ if ( vcp->vc_type & VCC_SVC ) { if (atm_dev_vcc_find(cup, vcp->vc_vpi, vcp->vc_vci, vcp->vc_type & (VCC_IN | VCC_OUT)) != cvp){ log ( LOG_ERR, "atm_dev_lower: dup SVC (%d,%d) tok=%p\n", vcp->vc_vpi, vcp->vc_vci, tok ); atm_cm_abort(cvp->cv_connvc, &atm_dev_cause); break; } } /* * Tell the device to open the VCC */ cvp->cv_state = CVS_INITED; s = splimp(); if ((*cup->cu_openvcc)(cup, cvp)) { atm_cm_abort(cvp->cv_connvc, &atm_dev_cause); (void) splx(s); break; } (void) splx(s); break; case CPCS_TERM: { KBuffer *m, *prev, *next; int *ip; s = splimp(); /* * Disconnect the VCC - ignore return code */ if ((cvp->cv_state == CVS_INITED) || (cvp->cv_state == CVS_ACTIVE)) { (void) (*cup->cu_closevcc)(cup, cvp); } cvp->cv_state = CVS_TERM; /* * Remove from interface list */ UNLINK ( cvp, Cmn_vcc, cup->cu_vcc, cv_next ); /* * Free any buffers from this VCC on the ATM interrupt queue */ prev = NULL; IF_LOCK(&atm_intrq); for (m = atm_intrq.ifq_head; m; m = next) { next = KB_QNEXT(m); /* * See if this entry is for the terminating VCC */ KB_DATASTART(m, ip, int *); ip++; if (*ip == (int)cvp) { /* * Yep, so dequeue the entry */ if (prev == NULL) atm_intrq.ifq_head = next; else KB_QNEXT(prev) = next; if (next == NULL) atm_intrq.ifq_tail = prev; atm_intrq.ifq_len--; /* * Free the unwanted buffers */ KB_FREEALL(m); } else { prev = m; } } IF_UNLOCK(&atm_intrq); (void) splx(s); /* * Free VCC resources */ - (void) atm_free((caddr_t)cvp); + uma_zfree(cup->cu_vcc_zone, cvp); break; } case CPCS_UNITDATA_INV: /* * Sanity check * * Use temp state variable since we dont want to lock out * interrupts, but initial VC activation interrupt may * happen here, changing state somewhere in the middle. */ state = cvp->cv_state; if ((state != CVS_ACTIVE) && (state != CVS_INITED)) { log ( LOG_ERR, "atm_dev_lower: UNITDATA: tok=%p, state=%d\n", tok, state ); KB_FREEALL((KBuffer *)arg1); break; } /* * Hand the data off to the device */ (*cup->cu_output)(cup, cvp, (KBuffer *)arg1); break; case CPCS_UABORT_INV: log ( LOG_ERR, "atm_dev_lower: unimplemented stack cmd 0x%x, tok=%p\n", cmd, tok ); break; default: log ( LOG_ERR, "atm_dev_lower: unknown stack cmd 0x%x, tok=%p\n", cmd, tok ); } return; } /* * Allocate kernel memory block * * This function will allocate a kernel memory block of the type specified * in the flags parameter. The returned address will point to a memory * block of the requested size and alignment. The memory block will also * be zeroed. The alloc/free functions will manage/mask both the OS-specific * kernel memory management requirements and the bookkeeping required to * deal with data alignment issues. * * This function should not be called from interrupt level. * * Arguments: * size size of memory block to allocate * align data alignment requirement * flags allocation flags (ATM_DEV_*) * * Returns: * uaddr pointer to aligned memory block * NULL unable to allocate memory * */ void * atm_dev_alloc(size, align, flags) u_int size; u_int align; u_int flags; { Mem_blk *mbp; Mem_ent *mep; u_int kalign, ksize; int s, i; s = splimp(); /* * Find a free Mem_ent */ mep = NULL; for (mbp = atm_mem_head; mbp && mep == NULL; mbp = mbp->mb_next) { for (i = 0; i < MEM_NMEMENT; i++) { if (mbp->mb_mement[i].me_uaddr == NULL) { mep = &mbp->mb_mement[i]; break; } } } /* * If there are no free Mem_ent's, then allocate a new Mem_blk * and link it into the chain */ if (mep == NULL) { mbp = malloc(sizeof(Mem_blk), M_DEVBUF, M_NOWAIT|M_ZERO); if (mbp == NULL) { log(LOG_ERR, "atm_dev_alloc: Mem_blk failure\n"); (void) splx(s); return (NULL); } mbp->mb_next = atm_mem_head; atm_mem_head = mbp; mep = mbp->mb_mement; } /* * Now we need to get the kernel's allocation alignment minimum * * This is obviously very OS-specific stuff */ kalign = MINALLOCSIZE; /* * Figure out how much memory we must allocate to satify the * user's size and alignment needs */ if (align <= kalign) ksize = size; else ksize = size + align - kalign; /* * Finally, go get the memory */ if (flags & ATM_DEV_NONCACHE) { mep->me_kaddr = malloc(ksize, M_DEVBUF, M_NOWAIT); } else { mep->me_kaddr = malloc(ksize, M_DEVBUF, M_NOWAIT); } if (mep->me_kaddr == NULL) { log(LOG_ERR, "atm_dev_alloc: %skernel memory unavailable\n", (flags & ATM_DEV_NONCACHE) ? "non-cacheable " : ""); (void) splx(s); return (NULL); } /* * Calculate correct alignment address to pass back to user */ mep->me_uaddr = (void *) roundup((u_int)mep->me_kaddr, align); mep->me_ksize = ksize; mep->me_flags = flags; /* * Clear memory for user */ bzero(mep->me_uaddr, size); ATM_DEBUG4("atm_dev_alloc: size=%d, align=%d, flags=%d, uaddr=%p\n", size, align, flags, mep->me_uaddr); (void) splx(s); return (mep->me_uaddr); } /* * Free kernel memory block * * This function will free a kernel memory block previously allocated by * the atm_dev_alloc function. * * This function should not be called from interrupt level. * * Arguments: * uaddr pointer to allocated aligned memory block * * Returns: * none * */ void atm_dev_free(uaddr) volatile void *uaddr; { Mem_blk *mbp; Mem_ent *mep; int s, i; ATM_DEBUG1("atm_dev_free: uaddr=%p\n", uaddr); s = splimp(); /* * Protect ourselves... */ if (uaddr == NULL) panic("atm_dev_free: trying to free null address"); /* * Find our associated entry */ mep = NULL; for (mbp = atm_mem_head; mbp && mep == NULL; mbp = mbp->mb_next) { for (i = 0; i < MEM_NMEMENT; i++) { if (mbp->mb_mement[i].me_uaddr == uaddr) { mep = &mbp->mb_mement[i]; break; } } } /* * If we didn't find our entry, then unceremoniously let the caller * know they screwed up (it certainly couldn't be a bug here...) */ if (mep == NULL) panic("atm_dev_free: trying to free unknown address"); /* * Give the memory space back to the kernel */ if (mep->me_flags & ATM_DEV_NONCACHE) { free(mep->me_kaddr, M_DEVBUF); } else { free(mep->me_kaddr, M_DEVBUF); } /* * Free our entry */ mep->me_uaddr = NULL; (void) splx(s); return; } /* * Compress buffer chain * * This function will compress a supplied buffer chain into a minimum number * of kernel buffers. Typically, this function will be used because the * number of buffers in an output buffer chain is too large for a device's * DMA capabilities. This should only be called as a last resort, since * all the data copying will surely kill any hopes of decent performance. * * Arguments: * m pointer to source buffer chain * * Returns: * n pointer to compressed buffer chain * */ KBuffer * atm_dev_compress(m) KBuffer *m; { KBuffer *n, *n0, **np; int len, space; caddr_t src, dst; n = n0 = NULL; np = &n0; dst = NULL; space = 0; /* * Copy each source buffer into compressed chain */ while (m) { if (space == 0) { /* * Allocate another buffer for compressed chain */ KB_ALLOCEXT(n, ATM_DEV_CMPR_LG, KB_F_NOWAIT, KB_T_DATA); if (n) { space = ATM_DEV_CMPR_LG; } else { KB_ALLOC(n, ATM_DEV_CMPR_SM, KB_F_NOWAIT, KB_T_DATA); if (n) { space = ATM_DEV_CMPR_SM; } else { /* * Unable to get any new buffers, so * just return the partially compressed * chain and hope... */ *np = m; break; } } KB_HEADSET(n, 0); KB_LEN(n) = 0; KB_BFRSTART(n, dst, caddr_t); *np = n; np = &KB_NEXT(n); } /* * Copy what we can from source buffer */ len = MIN(space, KB_LEN(m)); KB_DATASTART(m, src, caddr_t); bcopy(src, dst, len); /* * Adjust for copied data */ dst += len; space -= len; KB_HEADADJ(m, -len); KB_TAILADJ(n, len); /* * If we've exhausted our current source buffer, free it * and move to the next one */ if (KB_LEN(m) == 0) { KB_FREEONE(m, m); } } return (n0); } /* * Locate VCC entry * * This function will return the VCC entry for a specified interface and * VPI/VCI value. * * Arguments: * cup pointer to interface unit structure * vpi VPI value * vci VCI value * type VCC type * * Returns: * vcp pointer to located VCC entry matching * NULL no VCC found * */ Cmn_vcc * atm_dev_vcc_find(cup, vpi, vci, type) Cmn_unit *cup; u_int vpi; u_int vci; u_int type; { Cmn_vcc *cvp; int s = splnet(); /* * Go find VCC * * (Probably should stick in a hash table some time) */ for (cvp = cup->cu_vcc; cvp; cvp = cvp->cv_next) { struct vccb *vcp; vcp = cvp->cv_connvc->cvc_vcc; if ((vcp->vc_vci == vci) && (vcp->vc_vpi == vpi) && ((vcp->vc_type & type) == type)) break; } (void) splx(s); return (cvp); } #ifdef notdef /* * Module unloading notification * * This function must be called just prior to unloading the module from * memory. All allocated memory will be freed here and anything else that * needs cleaning up. * * Arguments: * none * * Returns: * none * */ void atm_unload() { Mem_blk *mbp; Mem_ent *mep; int s, i; s = splimp(); /* * Free up all of our memory management storage */ while (mbp = atm_mem_head) { /* * Make sure users have freed up all of their memory */ for (i = 0; i < MEM_NMEMENT; i++) { if (mbp->mb_mement[i].me_uaddr != NULL) { panic("atm_unload: unfreed memory"); } } atm_mem_head = mbp->mb_next; /* * Hand this block back to the kernel */ free((caddr_t)mbp, M_DEVBUF); } (void) splx(s); return; } #endif /* notdef */ /* * Print a PDU * * Arguments: * cup pointer to device unit * cvp pointer to VCC control block * m pointer to pdu buffer chain * msg pointer to message string * * Returns: * none * */ void atm_dev_pdu_print(cup, cvp, m, msg) Cmn_unit *cup; Cmn_vcc *cvp; KBuffer *m; char *msg; { char buf[128]; snprintf(buf, sizeof(buf), "%s vcc=(%d,%d)", msg, cvp->cv_connvc->cvc_vcc->vc_vpi, cvp->cv_connvc->cvc_vcc->vc_vci); atm_pdu_print(m, buf); } Index: head/sys/netatm/atm_if.c =================================================================== --- head/sys/netatm/atm_if.c (revision 98222) +++ head/sys/netatm/atm_if.c (revision 98223) @@ -1,1209 +1,1208 @@ /* * * =================================== * 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. * * @(#) $FreeBSD$ * */ /* * Core ATM Services * ----------------- * * ATM interface management * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef lint __RCSID("@(#) $FreeBSD$"); #endif /* * Local functions */ static int atm_physif_ioctl(int, caddr_t, caddr_t); static int atm_netif_rtdel(struct radix_node *, void *); static int atm_if_ioctl(struct ifnet *, u_long, caddr_t); static int atm_ifparse(char *, char *, int, int *); /* * Local variables */ static int (*atm_ifouttbl[AF_MAX+1]) (struct ifnet *, KBuffer *, struct sockaddr *) = {NULL}; /* * Register an ATM physical interface * * Each ATM device interface must register itself here upon completing * its internal initialization. This applies to both linked and loaded * device drivers. The interface must be registered before a signalling * manager can be attached. * * Arguments: * cup pointer to interface's common unit structure * name pointer to device name string * sdp pointer to interface's stack services * * Returns: * 0 registration successful * errno registration failed - reason indicated * */ int atm_physif_register(cup, name, sdp) Cmn_unit *cup; char *name; struct stack_defn *sdp; { struct atm_pif *pip; int s; /* * See if we need to be initialized */ if (!atm_init) atm_initialize(); /* * Make sure we're not already registered */ if (cup->cu_flags & CUF_REGISTER) { return (EALREADY); } s = splnet(); /* * Make sure an interface is only registered once */ for (pip = atm_interface_head; pip != NULL; pip = pip->pif_next) { if ((cup->cu_unit == pip->pif_unit) && (strcmp(name, pip->pif_name) == 0)) { (void) splx(s); return (EEXIST); } } /* * Fill in physical interface parameters */ pip = &cup->cu_pif; pip->pif_name = name; pip->pif_unit = cup->cu_unit; pip->pif_flags = PIF_UP; pip->pif_services = sdp; pip->pif_ioctl = atm_physif_ioctl; /* * Link in the interface and mark us registered */ LINK2TAIL(pip, struct atm_pif, atm_interface_head, pif_next); cup->cu_flags |= CUF_REGISTER; (void) splx(s); return (0); } /* * De-register an ATM physical interface * * Each ATM interface must de-register itself before downing the interface. * The interface's signalling manager will be detached and any network * interface and VCC control blocks will be freed. * * Arguments: * cup pointer to interface's common unit structure * * Returns: * 0 de-registration successful * errno de-registration failed - reason indicated * */ int atm_physif_deregister(cup) Cmn_unit *cup; { struct atm_pif *pip = (struct atm_pif *)&cup->cu_pif; Cmn_vcc *cvp; int err; int s = splnet(); /* * Detach and deregister, if needed */ if ((cup->cu_flags & CUF_REGISTER)) { /* * Detach from signalling manager */ if (pip->pif_sigmgr != NULL) { err = atm_sigmgr_detach(pip); if (err && (err != ENOENT)) { (void) splx(s); return (err); } } /* * Make sure signalling manager is detached */ if (pip->pif_sigmgr != NULL) { (void) splx(s); return (EBUSY); } /* * Unlink interface */ UNLINK(pip, struct atm_pif, atm_interface_head, pif_next); cup->cu_flags &= ~CUF_REGISTER; } /* * Free all of our network interfaces */ - atm_physif_freenifs(pip); + atm_physif_freenifs(pip, cup->cu_nif_zone); /* * Free unit's vcc information */ cvp = cup->cu_vcc; while (cvp) { - atm_free(cvp); + uma_zfree(cup->cu_vcc_zone, cvp); cvp = cvp->cv_next; } cup->cu_vcc = (Cmn_vcc *)NULL; (void) splx(s); return (0); } /* * Free all network interfaces on a physical interface * * Arguments * pip pointer to physical interface structure * * Returns * none * */ void -atm_physif_freenifs(pip) +atm_physif_freenifs(pip, zone) struct atm_pif *pip; + uma_zone_t zone; { struct atm_nif *nip = pip->pif_nif; int s = splnet(); while ( nip ) { /* * atm_nif_detach zeros pointers - save so we can * walk the chain. */ struct atm_nif *nipp = nip->nif_pnext; /* * Clean up network i/f trails */ - atm_nif_detach ( nip ); - atm_free ((caddr_t)nip); + atm_nif_detach(nip); + uma_zfree(zone, nip); nip = nipp; } pip->pif_nif = (struct atm_nif *)NULL; (void) splx(s); return; } - /* * Handle physical interface ioctl's * * See for definitions. * * Called at splnet. * * Arguments: * code Ioctl function (sub)code * data Data block. On input contains command, * on output, contains results * arg Optional code specific arguments * * Returns: * 0 Request processed successfully * errno Request failed - reason code * */ static int atm_physif_ioctl(code, data, arg) int code; caddr_t data; caddr_t arg; { struct atminfreq *aip = (struct atminfreq *)data; struct atmsetreq *asr = (struct atmsetreq *)data; struct atm_pif *pip; struct atm_nif *nip; struct sigmgr *smp; struct siginst *sip; struct ifnet *ifp; Cmn_unit *cup; Atm_config *acp; caddr_t buf = aip->air_buf_addr; struct air_phy_stat_rsp *apsp; struct air_int_rsp apr; struct air_netif_rsp anr; struct air_cfg_rsp acr; int count, len, buf_len = aip->air_buf_len; int err = 0; char ifname[2*IFNAMSIZ]; struct ifaddr *ifa; struct in_ifaddr *ia; struct sockaddr_dl *sdl; switch ( aip->air_opcode ) { case AIOCS_INF_INT: /* * Get physical interface information */ aip = (struct atminfreq *)data; pip = (struct atm_pif *)arg; /* * Make sure there's room in user buffer */ if (aip->air_buf_len < sizeof(apr)) { err = ENOSPC; break; } /* * Fill in info to be returned */ bzero((caddr_t)&apr, sizeof(apr)); smp = pip->pif_sigmgr; sip = pip->pif_siginst; (void) snprintf(apr.anp_intf, sizeof(apr.anp_intf), "%s%d", pip->pif_name, pip->pif_unit ); if ( pip->pif_nif ) { strcpy(apr.anp_nif_pref, pip->pif_nif->nif_if.if_name); nip = pip->pif_nif; while ( nip ) { apr.anp_nif_cnt++; nip = nip->nif_pnext; } } if (sip) { ATM_ADDR_COPY(&sip->si_addr, &apr.anp_addr); ATM_ADDR_COPY(&sip->si_subaddr, &apr.anp_subaddr); apr.anp_sig_proto = smp->sm_proto; apr.anp_sig_state = sip->si_state; } /* * Copy data to user buffer */ err = copyout((caddr_t)&apr, aip->air_buf_addr, sizeof(apr)); if (err) break; /* * Update buffer pointer/count */ aip->air_buf_addr += sizeof(apr); aip->air_buf_len -= sizeof(apr); break; case AIOCS_INF_NIF: /* * Get network interface information */ aip = (struct atminfreq *)data; nip = (struct atm_nif *)arg; ifp = &nip->nif_if; pip = nip->nif_pif; /* * Make sure there's room in user buffer */ if (aip->air_buf_len < sizeof(anr)) { err = ENOSPC; break; } /* * Fill in info to be returned */ bzero((caddr_t)&anr, sizeof(anr)); (void) snprintf(anr.anp_intf, sizeof(anr.anp_intf), "%s%d", ifp->if_name, ifp->if_unit); IFP_TO_IA(ifp, ia); if (ia) { anr.anp_proto_addr = *ia->ia_ifa.ifa_addr; } (void) snprintf(anr.anp_phy_intf, sizeof(anr.anp_phy_intf), "%s%d", pip->pif_name, pip->pif_unit); /* * Copy data to user buffer */ err = copyout((caddr_t)&anr, aip->air_buf_addr, sizeof(anr)); if (err) break; /* * Update buffer pointer/count */ aip->air_buf_addr += sizeof(anr); aip->air_buf_len -= sizeof(anr); break; case AIOCS_INF_PIS: /* * Get per interface statistics */ pip = (struct atm_pif *)arg; if ( pip == NULL ) return ( ENXIO ); snprintf ( ifname, sizeof(ifname), "%s%d", pip->pif_name, pip->pif_unit ); /* * Cast response into users buffer */ apsp = (struct air_phy_stat_rsp *)buf; /* * Sanity check */ len = sizeof ( struct air_phy_stat_rsp ); if ( buf_len < len ) return ( ENOSPC ); /* * Copy interface name into response */ if ((err = copyout ( ifname, apsp->app_intf, IFNAMSIZ)) != 0) break; /* * Copy counters */ if ((err = copyout(&pip->pif_ipdus, &apsp->app_ipdus, len - sizeof(apsp->app_intf))) != 0) break; /* * Adjust buffer elements */ buf += len; buf_len -= len; aip->air_buf_addr = buf; aip->air_buf_len = buf_len; break; case AIOCS_SET_NIF: /* * Set NIF - allow user to configure 1 or more logical * interfaces per physical interface. */ /* * Get pointer to physical interface structure from * ioctl argument. */ pip = (struct atm_pif *)arg; cup = (Cmn_unit *)pip; /* * Sanity check - are we already connected to something? */ if ( pip->pif_sigmgr ) { err = EBUSY; break; } /* * Free any previously allocated NIFs */ - atm_physif_freenifs(pip); + atm_physif_freenifs(pip, cup->cu_nif_zone); /* * Add list of interfaces */ for ( count = 0; count < asr->asr_nif_cnt; count++ ) { - nip = (struct atm_nif *)atm_allocate(cup->cu_nif_pool); + nip = uma_zalloc(cup->cu_nif_zone, M_WAITOK | M_ZERO); if ( nip == NULL ) { /* * Destroy any successful nifs */ - atm_physif_freenifs(pip); + atm_physif_freenifs(pip, cup->cu_nif_zone); err = ENOMEM; break; } nip->nif_pif = pip; ifp = &nip->nif_if; strcpy ( nip->nif_name, asr->asr_nif_pref ); nip->nif_sel = count; ifp->if_name = nip->nif_name; ifp->if_unit = count; ifp->if_mtu = ATM_NIF_MTU; ifp->if_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING; ifp->if_output = atm_ifoutput; ifp->if_ioctl = atm_if_ioctl; ifp->if_snd.ifq_maxlen = ifqmaxlen; /* * Set if_type and if_baudrate */ ifp->if_type = IFT_ATM; switch ( cup->cu_config.ac_media ) { case MEDIA_TAXI_100: ifp->if_baudrate = 100000000; break; case MEDIA_TAXI_140: ifp->if_baudrate = 140000000; break; case MEDIA_OC3C: case MEDIA_OC12C: case MEDIA_UTP155: ifp->if_baudrate = 155000000; break; case MEDIA_UNKNOWN: ifp->if_baudrate = 9600; break; } if ((err = atm_nif_attach(nip)) != 0) { - atm_free ( (caddr_t)nip ); - + uma_zfree(cup->cu_nif_zone, nip); /* * Destroy any successful nifs */ - atm_physif_freenifs(pip); + atm_physif_freenifs(pip, cup->cu_nif_zone); break; } /* * Set macaddr in address */ ifp->if_addrlen = 6; ifa = ifaddr_byindex(ifp->if_index); if ( ifa ) { sdl = (struct sockaddr_dl *) ifa->ifa_addr; sdl->sdl_type = IFT_ETHER; sdl->sdl_alen = ifp->if_addrlen; bcopy ( (caddr_t)&cup->cu_config.ac_macaddr, LLADDR(sdl), ifp->if_addrlen ); } } break; case AIOCS_INF_CFG: /* * Get adapter configuration information */ aip = (struct atminfreq *)data; pip = (struct atm_pif *)arg; cup = (Cmn_unit *)pip; acp = &cup->cu_config; /* * Make sure there's room in user buffer */ if (aip->air_buf_len < sizeof(acr)) { err = ENOSPC; break; } /* * Fill in info to be returned */ bzero((caddr_t)&acr, sizeof(acr)); (void) snprintf(acr.acp_intf, sizeof(acr.acp_intf), "%s%d", pip->pif_name, pip->pif_unit); bcopy((caddr_t)acp, (caddr_t)&acr.acp_cfg, sizeof(Atm_config)); /* * Copy data to user buffer */ err = copyout((caddr_t)&acr, aip->air_buf_addr, sizeof(acr)); if (err) break; /* * Update buffer pointer/count */ aip->air_buf_addr += sizeof(acr); aip->air_buf_len -= sizeof(acr); break; case AIOCS_INF_VST: /* * Pass off to device-specific handler */ cup = (Cmn_unit *)arg; if (cup == NULL) err = ENXIO; else err = (*cup->cu_ioctl)(code, data, arg); break; default: err = ENOSYS; } return ( err ); } /* * Register a Network Convergence Module * * Each ATM network convergence module must register itself here before * it will receive network interface status notifications. * * Arguments: * ncp pointer to network convergence definition structure * * Returns: * 0 registration successful * errno registration failed - reason indicated * */ int atm_netconv_register(ncp) struct atm_ncm *ncp; { struct atm_ncm *tdp; int s = splnet(); /* * See if we need to be initialized */ if (!atm_init) atm_initialize(); /* * Validate protocol family */ if (ncp->ncm_family > AF_MAX) { (void) splx(s); return (EINVAL); } /* * Ensure no duplicates */ for (tdp = atm_netconv_head; tdp != NULL; tdp = tdp->ncm_next) { if (tdp->ncm_family == ncp->ncm_family) { (void) splx(s); return (EEXIST); } } /* * Add module to list */ LINK2TAIL(ncp, struct atm_ncm, atm_netconv_head, ncm_next); /* * Add new interface output function */ atm_ifouttbl[ncp->ncm_family] = ncp->ncm_ifoutput; (void) splx(s); return (0); } /* * De-register an ATM Network Convergence Module * * Each ATM network convergence provider must de-register its registered * service(s) before terminating. Specifically, loaded kernel modules * must de-register their services before unloading themselves. * * Arguments: * ncp pointer to network convergence definition structure * * Returns: * 0 de-registration successful * errno de-registration failed - reason indicated * */ int atm_netconv_deregister(ncp) struct atm_ncm *ncp; { int found, s = splnet(); /* * Remove module from list */ UNLINKF(ncp, struct atm_ncm, atm_netconv_head, ncm_next, found); if (!found) { (void) splx(s); return (ENOENT); } /* * Remove module's interface output function */ atm_ifouttbl[ncp->ncm_family] = NULL; (void) splx(s); return (0); } /* * Attach an ATM Network Interface * * Before an ATM network interface can be used by the system, the owning * device interface must attach the network interface using this function. * The physical interface for this network interface must have been previously * registered (using atm_interface_register). The network interface will be * added to the kernel's interface list and to the physical interface's list. * The caller is responsible for initializing the control block fields. * * Arguments: * nip pointer to atm network interface control block * * Returns: * 0 attach successful * errno attach failed - reason indicated * */ int atm_nif_attach(nip) struct atm_nif *nip; { struct atm_pif *pip, *pip2; struct ifnet *ifp; struct atm_ncm *ncp; int s; ifp = &nip->nif_if; pip = nip->nif_pif; s = splimp(); /* * Verify physical interface is registered */ for (pip2 = atm_interface_head; pip2 != NULL; pip2 = pip2->pif_next) { if (pip == pip2) break; } if ((pip == NULL) || (pip2 == NULL)) { (void) splx(s); return (EFAULT); } /* * Add to system interface list */ if_attach(ifp); /* * Add to physical interface list */ LINK2TAIL(nip, struct atm_nif, pip->pif_nif, nif_pnext); /* * Notify network convergence modules of new network i/f */ for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) { int err; err = (*ncp->ncm_stat)(NCM_ATTACH, nip, 0); if (err) { atm_nif_detach(nip); (void) splx(s); return (err); } } (void) splx(s); return (0); } /* * Detach an ATM Network Interface * * Before an ATM network interface control block can be freed, all kernel * references to/from this block must be released. This function will delete * all routing references to the interface and free all interface addresses * for the interface. The network interface will then be removed from the * kernel's interface list and from the owning physical interface's list. * The caller is responsible for free'ing the control block. * * Arguments: * nip pointer to atm network interface control block * * Returns: * none * */ void atm_nif_detach(nip) struct atm_nif *nip; { struct atm_ncm *ncp; int s, i; struct ifnet *ifp = &nip->nif_if; struct ifaddr *ifa; struct in_ifaddr *ia; struct radix_node_head *rnh; s = splimp(); /* * Notify convergence modules of network i/f demise */ for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) { (void) (*ncp->ncm_stat)(NCM_DETACH, nip, 0); } /* * Mark interface down */ if_down(ifp); /* * Free all interface routes and addresses */ while (1) { IFP_TO_IA(ifp, ia); if (ia == NULL) break; /* Delete interface route */ in_ifscrub(ifp, ia); /* Remove interface address from queues */ ifa = &ia->ia_ifa; TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link); TAILQ_REMOVE(&in_ifaddrhead, ia, ia_link); /* Free interface address */ IFAFREE(ifa); } /* * Delete all remaining routes using this interface * Unfortuneatly the only way to do this is to slog through * the entire routing table looking for routes which point * to this interface...oh well... */ for (i = 1; i <= AF_MAX; i++) { if ((rnh = rt_tables[i]) == NULL) continue; (void) rnh->rnh_walktree(rnh, atm_netif_rtdel, ifp); } /* * Remove from system interface list (ie. if_detach()) */ TAILQ_REMOVE(&ifnet, ifp, if_link); /* * Remove from physical interface list */ UNLINK(nip, struct atm_nif, nip->nif_pif->pif_nif, nif_pnext); (void) splx(s); } /* * Delete Routes for a Network Interface * * Called for each routing entry via the rnh->rnh_walktree() call above * to delete all route entries referencing a detaching network interface. * * Arguments: * rn pointer to node in the routing table * arg argument passed to rnh->rnh_walktree() - detaching interface * * Returns: * 0 successful * errno failed - reason indicated * */ static int atm_netif_rtdel(rn, arg) struct radix_node *rn; void *arg; { struct rtentry *rt = (struct rtentry *)rn; struct ifnet *ifp = arg; int err; if (rt->rt_ifp == ifp) { /* * Protect (sorta) against walktree recursion problems * with cloned routes */ if ((rt->rt_flags & RTF_UP) == 0) return (0); err = rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt), rt->rt_flags, (struct rtentry **) NULL); if (err) { log(LOG_WARNING, "atm_netif_rtdel: error %d\n", err); } } return (0); } /* * Set an ATM Network Interface address * * This is called from a device interface when processing an SIOCSIFADDR * ioctl request. We just notify all convergence modules of the new address * and hope everyone has non-overlapping interests, since if someone reports * an error we don't go back and tell everyone to undo the change. * * Arguments: * nip pointer to atm network interface control block * ifa pointer to new interface address * * Returns: * 0 set successful * errno set failed - reason indicated * */ int atm_nif_setaddr(nip, ifa) struct atm_nif *nip; struct ifaddr *ifa; { struct atm_ncm *ncp; int err = 0, s = splnet(); /* * Notify convergence modules of network i/f change */ for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) { err = (*ncp->ncm_stat)(NCM_SETADDR, nip, (int)ifa); if (err) break; } (void) splx(s); return (err); } /* * ATM Interface Packet Output * * All ATM network interfaces must have their ifnet if_output address set to * this function. Since no existing network layer code is to be modified * for ATM support, this function serves as the hook to allow network output * packets to be assigned to their proper outbound VCC. Each network address * family which is to be supported over ATM must be assigned an output * packet processing function via atm_netconv_register(). * * Arguments: * ifp pointer to ifnet structure * m pointer to packet buffer chain to be output * dst pointer to packet's network destination address * * Returns: * 0 packet queued to interface * errno output failed - reason indicated * */ int atm_ifoutput(ifp, m, dst, rt) struct ifnet *ifp; KBuffer *m; struct sockaddr *dst; struct rtentry *rt; { u_short fam = dst->sa_family; int (*func)(struct ifnet *, KBuffer *, struct sockaddr *); /* * Validate address family */ if (fam > AF_MAX) { KB_FREEALL(m); return (EAFNOSUPPORT); } /* * Hand packet off for dst-to-VCC mapping */ func = atm_ifouttbl[fam]; if (func == NULL) { KB_FREEALL(m); return (EAFNOSUPPORT); } return ((*func)(ifp, m, dst)); } /* * Handle interface ioctl requests. * * Arguments: * ifp pointer to network interface structure * cmd IOCTL cmd * data arguments to/from ioctl * * Returns: * error errno value */ static int atm_if_ioctl(ifp, cmd, data) struct ifnet *ifp; u_long cmd; caddr_t data; { register struct ifreq *ifr = (struct ifreq *)data; struct atm_nif *nip = (struct atm_nif *)ifp; int error = 0; int s = splnet(); switch ( cmd ) { case SIOCGIFADDR: bcopy ( (caddr_t)&(nip->nif_pif->pif_macaddr), (caddr_t)ifr->ifr_addr.sa_data, sizeof(struct mac_addr) ); break; case SIOCSIFADDR: error = atm_nif_setaddr ( nip, (struct ifaddr *)data); ifp->if_flags |= IFF_UP | IFF_RUNNING | IFF_BROADCAST; break; case SIOCGIFFLAGS: *(short *)data = ifp->if_flags; break; case SIOCSIFFLAGS: break; default: error = EINVAL; break; } (void) splx(s); return ( error ); } /* * Parse interface name * * Parses an interface name string into a name and a unit component. * * Arguments: * name pointer to interface name string * namep address to store interface name * size size available at namep * unitp address to store interface unit number * * Returns: * 0 name parsed * else parse error * */ static int atm_ifparse(name, namep, size, unitp) char *name; char *namep; int size; int *unitp; { char *cp, *np; int len = 0, unit = 0; /* * Separate supplied string into name and unit parts. */ cp = name; np = namep; while (*cp) { if (*cp >= '0' && *cp <= '9') break; if (++len >= size) return (-1); *np++ = *cp++; } *np = '\0'; while (*cp && *cp >= '0' && *cp <= '9') unit = 10 * unit + *cp++ - '0'; *unitp = unit; return (0); } /* * Locate ATM physical interface via name * * Uses the supplied interface name string to locate a registered * ATM physical interface. * * Arguments: * name pointer to interface name string * * Returns: * 0 interface not found * else pointer to atm physical interface structure * */ struct atm_pif * atm_pifname(name) char *name; { struct atm_pif *pip; char n[IFNAMSIZ]; int unit; /* * Break down name */ if (atm_ifparse(name, n, sizeof(n), &unit)) return ((struct atm_pif *)0); /* * Look for the physical interface */ for (pip = atm_interface_head; pip; pip = pip->pif_next) { if ((pip->pif_unit == unit) && (strcmp(pip->pif_name, n) == 0)) break; } return (pip); } /* * Locate ATM network interface via name * * Uses the supplied interface name string to locate an ATM network interface. * * Arguments: * name pointer to interface name string * * Returns: * 0 interface not found * else pointer to atm network interface structure * */ struct atm_nif * atm_nifname(name) char *name; { struct atm_pif *pip; struct atm_nif *nip; char n[IFNAMSIZ]; int unit; /* * Break down name */ if (atm_ifparse(name, n, sizeof(n), &unit)) return ((struct atm_nif *)0); /* * Search thru each physical interface */ for (pip = atm_interface_head; pip; pip = pip->pif_next) { /* * Looking for network interface */ for (nip = pip->pif_nif; nip; nip = nip->nif_pnext) { struct ifnet *ifp = (struct ifnet *)nip; if ((ifp->if_unit == unit) && (strcmp(ifp->if_name, n) == 0)) return (nip); } } return (NULL); } Index: head/sys/netatm/atm_if.h =================================================================== --- head/sys/netatm/atm_if.h (revision 98222) +++ head/sys/netatm/atm_if.h (revision 98223) @@ -1,350 +1,353 @@ /* * * =================================== * 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. * * @(#) $FreeBSD$ * */ /* * Core ATM Services * ----------------- * * ATM Physical and Network Interface definitions * */ #ifndef _NETATM_ATM_IF_H #define _NETATM_ATM_IF_H /* * Handy constants */ #define ATM_NIF_MTU 9180 /* Default network interface MTU */ #define ATM_PCR_TAXI100 227273 /* Peak Cell Rate for 100 Mbs TAXI */ #define ATM_PCR_TAXI140 318181 /* Peak Cell Rate for 140 Mbs TAXI */ #define ATM_PCR_OC3C 353207 /* Peak Cell Rate for OC3c */ #define ATM_PCR_OC12C 1416905 /* Peak Cell Rate for OC12c */ /* * Media Access Control (MAC) address */ struct mac_addr { u_char ma_data[6]; /* MAC address */ }; typedef struct mac_addr Mac_addr; /* * Adapter vendor identifiers */ enum atm_vendor { VENDOR_UNKNOWN, /* Unknown vendor */ VENDOR_FORE, /* FORE Systems, Inc. */ VENDOR_ENI, /* Efficient Networks, Inc. */ VENDOR_IDT /* Integrated Device Technology, Inc. */ }; typedef enum atm_vendor Atm_vendor; /* * Adapter vendor interface identifiers */ enum atm_vendapi { VENDAPI_UNKNOWN, /* Unknown interface */ VENDAPI_FORE_1, /* FORE - 200 Series */ VENDAPI_ENI_1, /* ENI - Midway */ VENDAPI_IDT_1 /* IDT - NICStAR */ }; typedef enum atm_vendapi Atm_vendapi; /* * Adapter device model identifiers */ enum atm_device { DEV_UNKNOWN, /* Unknown device */ DEV_FORE_SBA200E, /* FORE SBA-200E */ DEV_FORE_SBA200, /* FORE SBA-200 */ DEV_FORE_PCA200E, /* FORE PCA-200E */ DEV_FORE_ESA200E, /* FORE ESA-200E */ DEV_ENI_155P, /* ENI-155p */ DEV_IDT_155 /* IDT NICStAR */ }; typedef enum atm_device Atm_device; /* * Adapter media identifiers */ enum atm_media { MEDIA_UNKNOWN, /* Unknown media type */ MEDIA_TAXI_100, /* TAXI - 100 Mbps */ MEDIA_TAXI_140, /* TAXI - 140 Mbps */ MEDIA_OC3C, /* OC-3C */ MEDIA_OC12C, /* OC-12C */ MEDIA_UTP155 /* UTP-155 */ }; typedef enum atm_media Atm_media; /* * Bus type identifiers */ enum atm_bus { BUS_UNKNOWN, /* Unknown bus type */ BUS_SBUS_B16, /* SBus: 16 byte (4 word) max burst */ BUS_SBUS_B32, /* SBus: 32 byte (8 word) max burst */ BUS_PCI, /* PCI */ BUS_EISA /* EISA */ }; typedef enum atm_bus Atm_bus; #define VERSION_LEN 16 /* Length of version info string */ /* * ATM adapter configuration information structure */ struct atm_config { Atm_vendor ac_vendor; /* Vendor */ Atm_vendapi ac_vendapi; /* Vendor interface */ Atm_device ac_device; /* Device model */ Atm_media ac_media; /* Media type */ u_long ac_serial; /* Serial number */ Atm_bus ac_bustype; /* Bus type */ u_long ac_busslot; /* Bus slot info (bus type dependent) */ u_long ac_ram; /* Device ram offset */ u_long ac_ramsize; /* Device ram size */ Mac_addr ac_macaddr; /* MAC address */ char ac_hard_vers[VERSION_LEN]; /* Hardware version */ char ac_firm_vers[VERSION_LEN]; /* Firmware version */ }; typedef struct atm_config Atm_config; #ifdef _KERNEL + +#include + /* * Common structure used to define each physical ATM device interface. * This structure will (normally) be embedded at the top of each driver's * device-specific interface structure. */ struct atm_pif { struct atm_pif *pif_next; /* Next registered atm interface */ char *pif_name; /* Device name */ short pif_unit; /* Device unit number */ u_char pif_flags; /* Interface flags (see below) */ struct sigmgr *pif_sigmgr; /* Signalling Manager for interface */ struct siginst *pif_siginst; /* Signalling protocol instance */ struct stack_defn *pif_services; /* Interface's stack services */ struct mac_addr pif_macaddr; /* Interface's MAC address */ struct atm_nif *pif_nif; /* List of network interfaces */ struct atm_pif *pif_grnext; /* Next atm device in group */ /* Exported functions */ int (*pif_ioctl) /* Interface ioctl handler */ (int, caddr_t, caddr_t); /* Interface statistics */ u_quad_t pif_ipdus; /* PDUs received from interface */ u_quad_t pif_opdus; /* PDUs sent to interface */ u_quad_t pif_ibytes; /* Bytes received from interface */ u_quad_t pif_obytes; /* Bytes sent to interface */ u_quad_t pif_ierrors; /* Errors receiving from interface */ u_quad_t pif_oerrors; /* Errors sending to interface */ u_quad_t pif_cmderrors; /* Interface command errors */ caddr_t pif_cardstats; /* Card specific statistics */ /* Interface capabilities */ u_short pif_maxvpi; /* Maximum VPI value supported */ u_short pif_maxvci; /* Maximum VCI value supported */ u_int pif_pcr; /* Peak Cell Rate */ }; /* * Physical interface flags */ #define PIF_UP 0x01 /* Interface is up */ #define PIF_LOOPBACK 0x02 /* Loopback local packets */ /* * Structure defining an ATM network interface. This structure is used as * the hook between the standard BSD network layer interface mechanism and * the ATM device layer. There may be one or more network interfaces for * each physical ATM interface. */ struct atm_nif { struct ifnet nif_if; /* Network interface */ struct atm_pif *nif_pif; /* Our physical interface */ char nif_name[IFNAMSIZ];/* Network interface name */ u_char nif_sel; /* Interface's address selector */ struct atm_nif *nif_pnext; /* Next net interface on phys i/f */ /* Interface statistics (in addition to ifnet stats) */ long nif_ibytes; /* Bytes received from interface */ long nif_obytes; /* Bytes sent to interface */ }; /* * Common Device VCC Entry * * Contains the common information for each VCC which is opened * through a particular device. */ struct cmn_vcc { struct cmn_vcc *cv_next; /* Next in list */ void *cv_toku; /* Upper layer's token */ void (*cv_upper) /* Upper layer's interface */ (int, void *, int, int); Atm_connvc *cv_connvc; /* Associated connection VCC */ u_char cv_state; /* VCC state (see below) */ u_char cv_flags; /* VCC flags (see below) */ }; typedef struct cmn_vcc Cmn_vcc; /* * VCC States */ #define CVS_FREE 0 /* Not allocated */ #define CVS_INST 1 /* Instantiated, waiting for INIT */ #define CVS_INITED 2 /* Initialized, waiting for driver */ #define CVS_ACTIVE 3 /* Device activated by driver */ #define CVS_PTERM 4 /* Waiting for TERM */ #define CVS_TERM 5 /* Terminated */ /* * VCC Flags */ #define CVF_RSVD 0x0f /* Reserved for device-specific use */ /* * Common Device Unit Structure * * Contains the common information for a single device (adapter). */ struct cmn_unit { struct atm_pif cu_pif; /* Physical interface */ u_int cu_unit; /* Local unit number */ u_char cu_flags; /* Device flags (see below) */ u_int cu_mtu; /* Interface MTU */ u_int cu_open_vcc; /* Open VCC count */ Cmn_vcc *cu_vcc; /* List of VCC's on interface */ u_int cu_intrpri; /* Highest unit interrupt priority */ int cu_savepri; /* Saved priority for locking device */ - struct sp_info *cu_vcc_pool; /* Device VCC pool */ - struct sp_info *cu_nif_pool; /* Device NIF pool */ + uma_zone_t cu_vcc_zone; /* Device VCC zone */ + uma_zone_t cu_nif_zone; /* Device NIF zone */ int (*cu_ioctl) /* Interface ioctl handler */ (int, caddr_t, caddr_t); int (*cu_instvcc) /* VCC stack instantion handler */ (struct cmn_unit *, Cmn_vcc *); int (*cu_openvcc) /* Open VCC handler */ (struct cmn_unit *, Cmn_vcc *); int (*cu_closevcc) /* Close VCC handler */ (struct cmn_unit *, Cmn_vcc *); void (*cu_output) /* Data output handler */ (struct cmn_unit *, Cmn_vcc *, KBuffer *); Atm_config cu_config; /* Device configuration data */ }; typedef struct cmn_unit Cmn_unit; /* * Device flags */ #define CUF_REGISTER 0x01 /* Device is registered */ #define CUF_INITED 0x02 /* Device is initialized */ /* * Structure used to define a network convergence module and its associated * entry points. A convergence module is used to provide the interface * translations necessary between the ATM system and the BSD network layer * interface mechanism. There will be one network convergence module for * each protocol address family supporting ATM connections. */ struct atm_ncm { struct atm_ncm *ncm_next; /* Next in registry list */ u_short ncm_family; /* Protocol family */ /* Exported functions */ int (*ncm_ifoutput) /* Interface if_output handler */ (struct ifnet *, KBuffer *, struct sockaddr *); int (*ncm_stat) /* Network i/f status handler */ (int, struct atm_nif *, int); }; /* * ncm_stat() commands */ #define NCM_ATTACH 1 /* Attaching a new net i/f */ #define NCM_DETACH 2 /* Detaching a current net i/f */ #define NCM_SETADDR 3 /* Net i/f address change */ #define NCM_SIGATTACH 4 /* Attaching a signalling manager */ #define NCM_SIGDETACH 5 /* Detaching a signalling manager */ /* * atm_dev_alloc() parameters */ #define ATM_DEV_NONCACHE 1 /* Allocate non-cacheable memory */ /* * atm_dev_compress() buffer allocation sizes */ #define ATM_DEV_CMPR_LG MCLBYTES /* Size of large buffers */ #define ATM_DEV_CMPR_SM MLEN /* Size of small buffers */ /* * Macros to manage DMA addresses */ #define DMA_INIT() #define DMA_GET_ADDR(addr,len,align,flags) ((void *)vtophys(addr)) #define DMA_FREE_ADDR(addr,daddr,len,flags) #define DMA_RELEASE() /* * Macros to lock out device interrupts */ #define DEVICE_LOCK(u) ((u)->cu_savepri = splimp()) #define DEVICE_UNLOCK(u) ((void) splx((u)->cu_savepri)) /* * Macro to schedule the ATM interrupt queue handler */ typedef void (atm_intr_t)(void *, KBuffer *); /* Callback function type */ typedef atm_intr_t *atm_intr_func_t; /* Pointer to callback function */ #define SCHED_ATM schednetisr(NETISR_ATM) #endif /* _KERNEL */ #endif /* _NETATM_ATM_IF_H */ Index: head/sys/netatm/atm_var.h =================================================================== --- head/sys/netatm/atm_var.h (revision 98222) +++ head/sys/netatm/atm_var.h (revision 98223) @@ -1,183 +1,183 @@ /* * * =================================== * 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. * * @(#) $FreeBSD$ * */ /* * Core ATM Services * ----------------- * * ATM system variables * */ #ifndef _NETATM_ATM_VAR_H #define _NETATM_ATM_VAR_H #ifdef _KERNEL #include typedef void (*atm_init_fn)(void); /* * Global variable declarations */ extern struct pr_usrreqs atm_aal5_usrreqs; /* atm_proto.c */ extern struct domain atmdomain; /* atm_subr.c */ extern struct atm_pif *atm_interface_head; extern struct atm_ncm *atm_netconv_head; extern Atm_endpoint *atm_endpoints[]; extern struct sp_info *atm_pool_head; extern struct stackq_entry *atm_stackq_head; extern struct stackq_entry *atm_stackq_tail; extern struct ifqueue atm_intrq; extern struct atm_sock_stat atm_sock_stat; extern int atm_init; extern int atm_version; extern int atm_debug; extern struct timeval atm_debugtime; extern int atm_dev_print; extern int atm_print_data; extern uma_zone_t atm_attributes_zone; extern struct pr_usrreqs atm_dgram_usrreqs; /* * Global function declarations */ /* atm_aal5.c */ int atm_aal5_ctloutput(struct socket *, struct sockopt *); void atm_aal5_init(void); /* atm_cm.c */ int atm_cm_connect(Atm_endpoint *, void *, Atm_attributes *, Atm_connection **); int atm_cm_listen(Atm_endpoint *, void *, Atm_attributes *, Atm_connection **); int atm_cm_addllc(Atm_endpoint *, void *, struct attr_llc *, Atm_connection *, Atm_connection **); int atm_cm_addparty(Atm_connection *, int, struct t_atm_sap *); int atm_cm_dropparty(Atm_connection *, int, struct t_atm_cause *); int atm_cm_release(Atm_connection *, struct t_atm_cause *); int atm_cm_abort(Atm_connvc *, struct t_atm_cause *); int atm_cm_incoming(struct vccb *, Atm_attributes *); void atm_cm_connected(Atm_connvc *); void atm_cm_cleared(Atm_connvc *); Atm_connection *atm_cm_match(Atm_attributes *, Atm_connection *); int atm_cm_cpcs_ctl(int, Atm_connection *, void *); int atm_cm_cpcs_data(Atm_connection *, KBuffer *); int atm_cm_saal_ctl(int, Atm_connection *, void *); int atm_cm_saal_data(Atm_connection *, KBuffer *); int atm_cm_sscop_ctl(int, Atm_connection *, void *, void *); int atm_cm_sscop_data(Atm_connection *, KBuffer *); int atm_endpoint_register(Atm_endpoint *); int atm_endpoint_deregister(Atm_endpoint *); /* atm_device.c */ int atm_dev_inst(struct stack_defn **, Atm_connvc *); void atm_dev_lower(int, void *, int, int); void * atm_dev_alloc(u_int, u_int, u_int); void atm_dev_free(volatile void *); KBuffer * atm_dev_compress(KBuffer *); Cmn_vcc * atm_dev_vcc_find(Cmn_unit *, u_int, u_int, u_int); void atm_dev_pdu_print(Cmn_unit *, Cmn_vcc *, KBuffer *, char *); /* atm_if.c */ int atm_physif_register(Cmn_unit *, char *, struct stack_defn *); int atm_physif_deregister(Cmn_unit *); -void atm_physif_freenifs(struct atm_pif *); +void atm_physif_freenifs(struct atm_pif *, uma_zone_t); int atm_netconv_register(struct atm_ncm *); int atm_netconv_deregister(struct atm_ncm *); int atm_nif_attach(struct atm_nif *); void atm_nif_detach(struct atm_nif *); int atm_nif_setaddr(struct atm_nif *, struct ifaddr *); int atm_ifoutput(struct ifnet *, KBuffer *, struct sockaddr *, struct rtentry *); struct atm_pif * atm_pifname(char *); struct atm_nif * atm_nifname(char *); /* atm_proto.c */ int atm_proto_notsupp1(struct socket *); int atm_proto_notsupp2(struct socket *, struct sockaddr *, struct thread *); int atm_proto_notsupp3(struct socket *, struct sockaddr **); int atm_proto_notsupp4(struct socket *, int, KBuffer *, struct sockaddr *, KBuffer *, struct thread *); /* atm_signal.c */ int atm_sigmgr_register(struct sigmgr *); int atm_sigmgr_deregister(struct sigmgr *); int atm_sigmgr_attach(struct atm_pif *, u_char); int atm_sigmgr_detach(struct atm_pif *); int atm_stack_register(struct stack_defn *); int atm_stack_deregister(struct stack_defn *); int atm_create_stack(Atm_connvc *, struct stack_list *, void (*)(int, void *, int, int) ); /* atm_socket.c */ void atm_sock_init(void); int atm_sock_attach(struct socket *, u_long, u_long); int atm_sock_detach(struct socket *); int atm_sock_bind(struct socket *, struct sockaddr *); int atm_sock_listen(struct socket *, Atm_endpoint *); int atm_sock_connect(struct socket *, struct sockaddr *, Atm_endpoint *); int atm_sock_disconnect(struct socket *); int atm_sock_sockaddr(struct socket *, struct sockaddr **); int atm_sock_peeraddr(struct socket *, struct sockaddr **); int atm_sock_setopt(struct socket *, struct sockopt *, Atm_pcb *); int atm_sock_getopt(struct socket *, struct sockopt *, Atm_pcb *); void atm_sock_connected(void *); void atm_sock_cleared(void *, struct t_atm_cause *); /* atm_subr.c */ void atm_initialize(void); void * atm_allocate(struct sp_info *); void atm_free(void *); void atm_release_pool(struct sp_info *); void atm_timeout(struct atm_time *, int, void (*)(struct atm_time *) ); int atm_untimeout(struct atm_time *); int atm_stack_enq(int, void (*)(int, void *, int, int), void *, Atm_connvc *, int, int); void atm_stack_drain(void); void atm_intr(void); void atm_pdu_print(KBuffer *, char *); #endif /* _KERNEL */ #endif /* _NETATM_ATM_VAR_H */