3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sys/dev/hea/eni.c,v 1.10 1999/08/28 00:41:42 peter Exp $
31 * Efficient ENI adapter support
32 * -----------------------------
34 * Module supports PCI interface to ENI adapter
38 #include <netatm/kern_include.h>
40 #include <dev/hea/eni_stats.h>
41 #include <dev/hea/eni.h>
42 #include <dev/hea/eni_var.h>
45 __RCSID("@(#) $FreeBSD: src/sys/dev/hea/eni.c,v 1.10 1999/08/28 00:41:42 peter Exp $");
49 * Typedef local functions
51 static const char *eni_pci_probe __P((pcici_t, pcidi_t));
52 static void eni_pci_attach __P((pcici_t, int));
53 static int eni_get_ack __P((Eni_unit *));
54 static int eni_get_sebyte __P((Eni_unit *));
55 static void eni_read_seeprom __P((Eni_unit *));
58 static int eni_pci_shutdown __P((struct kern_devconf *, int));
60 static void eni_pci_shutdown __P((void *, int));
62 static void eni_pci_reset __P((Eni_unit *));
63 #endif /* __FreeBSD__ */
66 * Used by kernel to return number of claimed devices
69 static u_long eni_nunits;
71 static struct pci_device eni_pci_device = {
83 COMPAT_PCI_DRIVER (eni_pci, eni_pci_device);
84 #endif /* __FreeBSD__ */
87 * Called by kernel with PCI device_id which was read from the PCI
88 * register set. If the identified vendor is Efficient, see if we
89 * recognize the particular device. If so, return an identifying string,
90 * if not, return null.
93 * config_id PCI config token
94 * device_id contents of PCI device ID register
97 * string Identifying string if we will handle this device
98 * NULL unrecognized vendor/device
102 eni_pci_probe ( pcici_t config_id, pcidi_t device_id )
105 if ( (device_id & 0xFFFF) == EFF_VENDOR_ID ) {
106 switch ( (device_id >> 16) ) {
108 return ( "Efficient ENI ATM Adapter" );
118 * The ENI-155p adapter uses an ATMEL AT24C01 serial EEPROM to store
119 * configuration information. The SEEPROM is accessed via two wires,
120 * CLOCK and DATA, which are accessible via the PCI configuration
121 * registers. The following macros manipulate the lines to access the
122 * SEEPROM. See http://www.atmel.com/atmel/products/prod162.htm for
123 * a description of the AT24C01 part. Value to be read/written is
124 * part of the per unit structure.
127 * Write bits to SEEPROM
129 #define WRITE_SEEPROM() ( \
131 (void) pci_conf_write ( eup->eu_pcitag, SEEPROM, \
133 DELAY(SEPROM_DELAY); \
137 * Stobe first the DATA, then the CLK lines high
139 #define STROBE_HIGH() ( \
141 eup->eu_sevar |= SEPROM_DATA; WRITE_SEEPROM(); \
142 eup->eu_sevar |= SEPROM_CLK; WRITE_SEEPROM(); \
146 * Strobe first the CLK, then the DATA lines high
148 #define INV_STROBE_HIGH() ( \
150 eup->eu_sevar |= SEPROM_CLK; WRITE_SEEPROM(); \
151 eup->eu_sevar |= SEPROM_DATA; WRITE_SEEPROM(); \
155 * Strobe first the CLK, then the DATA lines low - companion to
158 #define STROBE_LOW() ( \
160 eup->eu_sevar &= ~SEPROM_CLK; WRITE_SEEPROM(); \
161 eup->eu_sevar &= ~SEPROM_DATA; WRITE_SEEPROM(); \
165 * Strobe first the DATA, then the CLK lines low - companion to
168 #define INV_STROBE_LOW() ( \
170 eup->eu_sevar &= ~SEPROM_DATA; WRITE_SEEPROM(); \
171 eup->eu_sevar &= ~SEPROM_CLK; WRITE_SEEPROM(); \
175 * Strobe the CLK line high, then low
177 #define STROBE_CLK() ( \
179 eup->eu_sevar |= SEPROM_CLK; WRITE_SEEPROM(); \
180 eup->eu_sevar &= ~SEPROM_CLK; WRITE_SEEPROM(); \
185 * Look for a positive ACK from the SEEPROM. Cycle begins by asserting
186 * the DATA line, then the CLK line. The DATA line is then read to
187 * retrieve the ACK status, and then the cycle is finished by deasserting
188 * the CLK line, and asserting the DATA line.
191 * eup pointer to per unit structure
205 * Read DATA line from SEPROM
207 eup->eu_sevar = pci_conf_read ( eup->eu_pcitag, SEEPROM );
208 DELAY ( SEPROM_DELAY );
209 ack = eup->eu_sevar & SEPROM_DATA;
211 eup->eu_sevar &= ~SEPROM_CLK;
213 eup->eu_sevar |= SEPROM_DATA;
220 * Read a byte from the SEEPROM. Data is read as 8 bits. There are two types
221 * of read operations. The first is a single byte read, the second is
222 * multiple sequential bytes read. Both cycles begin with a 'START' operation,
223 * followed by a memory address word. Following the memory address, the
224 * SEEPROM will send a data byte, followed by an ACK. If the host responds
225 * with a 'STOP' operation, then a single byte cycle is performed. If the
226 * host responds with an 'ACK', then the memory address is incremented, and
227 * the next sequential memory byte is serialized.
230 * eup pointer to per unit structure
233 * val value of byte read from SEEPROM
237 eni_get_sebyte( eup )
247 for ( i = 0; i < 8; i++ ) {
248 /* Shift bits to left so the next bit goes to position 0 */
250 /* Indicate we're ready to read bit */
253 * Read DATA line from SEPROM
255 data = pci_conf_read ( eup->eu_pcitag, SEEPROM );
256 DELAY ( SEPROM_DELAY );
257 /* (Possibly) mask bit into accumulating value */
258 if ( data & SEPROM_DATA )
259 rval |= 1; /* If DATA bit '1' */
260 /* Indicate we're done reading this bit */
264 /* Return acquired byte */
269 * The AT24C01 is a 1024 bit part organized as 128 words by 8 bits.
270 * We will read the entire contents into the per unit structure. Later,
271 * we'll retrieve the MAC address and serial number from the data read.
274 * eup pointer to per unit structure
281 eni_read_seeprom ( eup )
290 eup->eu_sevar = SEPROM_DATA | SEPROM_CLK;
293 /* Loop for all bytes */
294 for ( i = 0; i < SEPROM_SIZE ; i++ ) {
295 /* Send START operation */
300 * Send address. Addresses are sent as 7 bits plus
303 addr = ((i) << 1) + 1;
305 * Start with high order bit first working toward low
308 for ( j = 7; j >= 0; j-- ) {
309 /* Set current bit value */
310 eup->eu_sevar = ( addr >> j ) & 1 ?
311 eup->eu_sevar | SEPROM_DATA :
312 eup->eu_sevar & ~SEPROM_DATA;
314 /* Indicate we've sent it */
318 * We expect a zero ACK after sending the address
320 if ( !eni_get_ack ( eup ) ) {
321 /* Address okay - read data byte */
322 eup->eu_seeprom[i] = eni_get_sebyte ( eup );
323 /* Grab but ignore the ACK op */
324 (void) eni_get_ack ( eup );
326 /* Address ACK was bad - can't retrieve data byte */
327 eup->eu_seeprom[i] = 0xff;
335 * The kernel has found a device which we are willing to support.
336 * We are now being called to do any necessary work to make the
337 * device initially usable. In our case, this means allocating
338 * structure memory, configuring registers, mapping device
339 * memory, setting pointers, registering with the core services,
340 * and doing the initial PDU processing configuration.
343 * config_id PCI device token
344 * unit instance of the unit
351 eni_pci_attach ( pcici_t config_id, int unit )
361 if ( unit >= ENI_MAX_UNITS ) {
362 log ( LOG_ERR, "%s%d: too many devices\n",
363 ENI_DEV_NAME, unit );
368 * Make sure this isn't a duplicate unit
370 if ( eni_units[unit] != NULL )
374 * Allocate a new unit structure
376 eup = (Eni_unit *) atm_dev_alloc ( sizeof(Eni_unit), sizeof(int), 0 );
381 * Start initializing it
384 eup->eu_mtu = ENI_IFF_MTU;
385 eup->eu_pcitag = config_id;
386 eup->eu_ioctl = eni_atm_ioctl;
387 eup->eu_instvcc = eni_instvcc;
388 eup->eu_openvcc = eni_openvcc;
389 eup->eu_closevcc = eni_closevcc;
390 eup->eu_output = eni_output;
391 eup->eu_vcc_pool = &eni_vcc_pool;
392 eup->eu_nif_pool = &eni_nif_pool;
395 * Enable Memory Mapping / Bus Mastering
397 val = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG);
398 val |= (PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
399 pci_conf_write(config_id, PCI_COMMAND_STATUS_REG, val);
404 val = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG);
405 if ((val & PCIM_CMD_MEMEN) == 0) {
406 log(LOG_ERR, "%s%d: memory mapping not enabled\n",
410 if ( ( pci_map_mem ( config_id, PCI_MAP_REG_START, &va, &pa ) ) == 0 )
412 log(LOG_ERR, "%s%d: unable to map memory\n",
417 * Map okay - retain address assigned
419 eup->eu_base = (Eni_mem)va;
420 eup->eu_ram = (Eni_mem)(eup->eu_base + RAM_OFFSET);
423 * Map memory structures into adapter space
425 eup->eu_suni = (Eni_mem)(eup->eu_base + SUNI_OFFSET);
426 eup->eu_midway = (Eni_mem)(eup->eu_base + MIDWAY_OFFSET);
427 eup->eu_vcitbl = (VCI_Table *)(eup->eu_base + VCITBL_OFFSET);
428 eup->eu_rxdma = (Eni_mem)(eup->eu_base + RXQUEUE_OFFSET);
429 eup->eu_txdma = (Eni_mem)(eup->eu_base + TXQUEUE_OFFSET);
430 eup->eu_svclist = (Eni_mem)(eup->eu_base + SVCLIST_OFFSET);
431 eup->eu_servread = 0;
434 * Reset the midway chip
436 eup->eu_midway[MIDWAY_ID] = MIDWAY_RESET;
439 * Size and test adapter memory. Initialize our adapter memory
442 if ( eni_init_memory ( eup ) < 0 ) {
444 * Adapter memory test failed. Clean up and
447 log(LOG_ERR, "%s%d: memory test failed\n",
453 * Read the contents of the SEEPROM
455 eni_read_seeprom ( eup );
457 * Copy MAC address to PIF and config structures
459 KM_COPY ( (caddr_t)&eup->eu_seeprom[SEPROM_MAC_OFF],
460 (caddr_t)&eup->eu_pif.pif_macaddr, sizeof(struct mac_addr) );
461 eup->eu_config.ac_macaddr = eup->eu_pif.pif_macaddr;
464 * Copy serial number into config space
466 eup->eu_config.ac_serial =
467 ntohl(*(u_long *)&eup->eu_seeprom[SEPROM_SN_OFF]);
470 * Convert Endianess on DMA
472 val = pci_conf_read ( config_id, PCI_CONTROL_REG );
473 val |= ENDIAN_SWAP_DMA;
474 pci_conf_write ( config_id, PCI_CONTROL_REG, val );
479 if ( !pci_map_int ( config_id, eni_intr, (void *)eup, &net_imask ) )
481 log(LOG_ERR, "%s%d: unable to map interrupt\n",
487 * Setup some of the adapter configuration
492 val = eup->eu_midway[MIDWAY_ID];
493 eup->eu_config.ac_vendor = VENDOR_ENI;
494 eup->eu_config.ac_vendapi = VENDAPI_ENI_1;
495 eup->eu_config.ac_device = DEV_ENI_155P;
496 eup->eu_config.ac_media = val & MEDIA_MASK ? MEDIA_UTP155 : MEDIA_OC3C;
497 eup->eu_pif.pif_pcr = ATM_PCR_OC3C;
498 eup->eu_config.ac_bustype = BUS_PCI;
499 eup->eu_config.ac_busslot = config_id->bus << 8 | config_id->slot;
502 * Make a hw version number from the ID register values.
503 * Format: {Midway ID}.{Mother board ID}.{Daughter board ID}
505 snprintf ( eup->eu_config.ac_hard_vers,
506 sizeof ( eup->eu_config.ac_hard_vers ),
508 (val >> ID_SHIFT) & ID_MASK,
509 (val >> MID_SHIFT) & MID_MASK,
510 (val >> DID_SHIFT) & DID_MASK );
513 * There is no software version number
515 eup->eu_config.ac_firm_vers[0] = '\0';
518 * Save device ram info for user-level programs
519 * NOTE: This really points to start of EEPROM
520 * and includes all the device registers in the
523 eup->eu_config.ac_ram = (long)eup->eu_base;
524 eup->eu_config.ac_ramsize = eup->eu_ramsize + ENI_REG_SIZE;
527 * Setup max VPI/VCI values
529 eup->eu_pif.pif_maxvpi = ENI_MAX_VPI;
530 eup->eu_pif.pif_maxvci = ENI_MAX_VCI;
533 * Register this interface with ATM core services
535 if ( atm_physif_register
536 ( (Cmn_unit *)eup, ENI_DEV_NAME, eni_services ) != 0 )
539 * Registration failed - back everything out
541 log(LOG_ERR, "%s%d: atm_physif_register failed\n",
546 eni_units[unit] = eup;
550 * Add hook to out shutdown function
552 EVENTHANDLER_REGISTER(shutdown_post_sync, eni_pci_shutdown, eup,
553 SHUTDOWN_PRI_DEFAULT);
558 * Initialize driver processing
560 if ( eni_init ( eup ) ) {
561 log(LOG_ERR, "%s%d: adapter init failed\n",
570 * Attach failed - clean up
573 (void) pci_unmap_int(config_id);
579 * Device reset routine
582 * eup pointer to per unit structure
589 eni_pci_reset ( eup )
594 * We should really close down any open VCI's and
595 * release all memory (TX and RX) buffers. For now,
596 * we assume we're shutting the card down for good.
599 if (eup->eu_midway) {
601 * Issue RESET command to Midway chip
603 eup->eu_midway[MIDWAY_ID] = MIDWAY_RESET;
606 * Delay to allow everything to terminate
608 DELAY ( MIDWAY_DELAY );
617 * Device shutdown routine
620 * kdc pointer to device's configuration table
621 * force forced shutdown flag
628 eni_pci_shutdown ( kdc, force )
629 struct kern_devconf *kdc;
632 Eni_unit *eup = NULL;
634 if ( kdc->kdc_unit < eni_nunits ) {
636 eup = eni_units[kdc->kdc_unit];
638 /* Do device reset */
639 eni_pci_reset ( eup );
643 (void) dev_detach ( kdc );
648 * Device shutdown routine
651 * howto type of shutdown
652 * eup pointer to device unit structure
659 eni_pci_shutdown ( eup, howto )
664 /* Do device reset */
665 eni_pci_reset ( eup );
668 #endif /* BSD < 199506 */
669 #endif /* __FreeBSD__ */