Compaq Tru64 UNIX Installation Manual
Compaq Tru64 UNIX Installation Manual

Compaq Tru64 UNIX Installation Manual

Writing network device drivers
Table of Contents

Advertisement

Quick Links

Tru64 UNIX
Writing Network Device Drivers
Part Number: AA-RNG2A-TE
December 2000
Product Version:
Device Driver Kit Version 2.0
Operating System and Version: Tru64 UNIX Version 5.0A or higher
This manual contains information that systems engineers need to write
network device drivers that operate on any bus.
Compaq Computer Corporation
Houston, Texas

Advertisement

Table of Contents
loading
Need help?

Need help?

Do you have a question about the Tru64 UNIX and is the answer not in the manual?

Questions and answers

Subscribe to Our Youtube Channel

Summary of Contents for Compaq Tru64 UNIX

  • Page 1 Product Version: Device Driver Kit Version 2.0 Operating System and Version: Tru64 UNIX Version 5.0A or higher This manual contains information that systems engineers need to write network device drivers that operate on any bus. Compaq Computer Corporation Houston, Texas...
  • Page 2 © 2000 Compaq Computer Corporation Compaq and the Compaq logo Registered in U.S. Patent and Trademark Office. Tru64 is a trademark of Compaq Information Technologies Group, L.P. in the United States and other countries. UNIX and X/Open are trademarks of The Open Group in the United States and other countries. All other product names mentioned herein may be trademarks of their respective companies.
  • Page 3: Table Of Contents

    Contents About This Manual 1 Network Device Driver Environment Include Files Section for a Network Driver ...... . 1–3 Declarations Section for a Network Driver ...... . 1–4 1.2.1 External and Forward Declarations .
  • Page 4 Defining the Interrupt Handler ID ........ . 3–6 Defining CSR Pointer Information ........ . 3–6 Defining FIFO Maintenance Information ..
  • Page 5 5.3.5 Entering the Packet Transmit Loop ......5–20 5.3.6 Saving Counters Prior to the Transmit Operation ..5–21 5.3.7 Allocating Memory for a Test Packet .
  • Page 6 7.10 Unregistering the Card from the Hardware Management Database .............. . 7–5 7.11 Freeing Resources .
  • Page 7 9.2.3 Transmitting the Buffer ......... 9–6 9.2.4 Accounting for Outgoing Bytes ........ . 9–7 9.2.5 Updating Counters, Freeing the Transmit Buffer, and...
  • Page 8 12.15 Resetting the Device (SIOCIFRESET ioctl Command) ..12–11 12.16 Setting Device Characteristics (SIOCIFSETCHAR ioctl Command) ............. 12–11 12.17 Releasing the Simple Lock and Resetting the IPL .
  • Page 9 2–4 Window 4 Diagnostic Registers ........2–11 3–1 Typical softc Data Structure ........3–2 3–2 Mapping Alternate Names .
  • Page 11: About This Manual

    About This Manual This manual discusses how to write network device drivers for computer systems that run the Compaq Tru64™ UNIX operating system. Audience This manual is intended for systems engineers who: • Use standard library routines to develop programs in the C language •...
  • Page 12: Scope Of This Manual

    • Socket and XTI programming examples • TCP specific programming information • Information for Token Ring driver developers • Data link interface See the Tru64 UNIX Network Programmer’s Guide for descriptions of these topics. Scope of this Manual This manual builds on the concepts and topics that are presented in Writing Device Drivers, which is the core manual for developing device drivers on Tru64 UNIX.
  • Page 13 New and Changed Features This revision of the manual documents the following new features: • Enabling support for enhanced hardware management Enhanced hardware management (EHM) allows you to modify hardware attributes, such as the type of LAN device, on either a local or a remote system.
  • Page 14: Related Documentation

    Chapter 8 Describes how to implement an init interface and associated routines, using the if_el device driver’s el_init( ) routine as an example. Chapter 9 Describes how to implement a start interface and associated routines, using the if_el device driver’s el_start( ) routine as an example.
  • Page 15 (Section 9u), and global variables (Section 9v) that apply to device drivers. Reader’s Comments Compaq welcomes any comments and suggestions you have on this and other Tru64 UNIX manuals. You can send your comments in the following ways: •...
  • Page 16 The Tru64 UNIX Publications group cannot respond to system problems or technical support inquiries. Please address technical questions to your local system vendor or to the appropriate Compaq technical support office. Information provided with the software media explains how to send problem reports to Compaq.
  • Page 17 that are used in driver configuration, these brackets indicate items that are optional. Vertical bars separating items that appear in the syntax definitions used in driver configuration indicate that you choose one item from among those listed. About This Manual xvii...
  • Page 19: Network Device Driver Environment

    Network Device Driver Environment A network device is responsible for both transmitting and receiving frames over the network media. Network devices have network device drivers associated with them. A network device driver attaches a network subsystem to a network interface, prepares the network interface for operation, and governs the transmission and reception of network frames over the network interface.
  • Page 20: Sections Of A Network Device Driver

    Figure 1–1: Sections of a Network Device Driver Network Device Driver /* Include Files Section */ /* Declarations Section */ /* Configure Section */ /* Initialization Section */ /* Autoconfiguration Support Section */ /* Start Transmit Section */ /* Ioctl Section */ /* Interrupt Section */ /* Reset Section */ /* Watchdog Section */...
  • Page 21: Include Files Section For A Network Driver

    Instead of registering its entry points in a dsent data structure, a network driver registers its entry points with the upper layers of the Tru64 UNIX operating system in an ifnet data structure. For example, a network driver registers entry points for queueing data for transmission and for starting data transmission.
  • Page 22: Declarations Section For A Network Driver

    #include <netinet/ip.h> #include <netinet/ip_var.h> #include <netinet/if_ether.h> #include <net/ether_driver.h> #include <io/common/devdriver.h> #include <hal/cpuconf.h> #include <kern/thread.h> #include <kern/sched_prim.h> #include <kern/lock.h> #include <io/dec/eisa/eisa.h> #include <io/dec/pcmcia/pcmcia.h> #include <io/dec/pcmcia/cardinfo.h> #include <io/dec/netif/lan_common.h> #include <io/dec/netif/if_elreg.h> Includes the ioctl.h include file, which defines common ioctl com- mands. The ioctl.h file is located in /usr/include/sys/ioctl.h. Includes the sysconfig.h header file, which defines the constants that all device drivers use during configuration.
  • Page 23: External And Forward Declarations

    • External and forward declarations (Section 1.2.1) • Declaration of softc and controller data structure arrays (Section 1.2.2) • Declaration of the driver data structure (Section 1.2.3) • Definitions of driver-specific macros (Section 1.2.4) The following sections discuss each of these categories of declarations, using the if_el device driver as an example.
  • Page 24: Declaring Softc And Controller Data Structure Arrays

    Declares a pointer to the external task_t data structure called first_task. The task_t data structure is an opaque data structure; that is, all of its associated members are referenced and manipulated by the Tru64 UNIX operating system and not by the user of kernel threads. Every kernel thread must be part of a task.
  • Page 25: Declaring And Initializing The Driver Data Structure

    1.2.3 Declaring and Initializing the driver Data Structure The following code shows how the if_el device driver declares and initializes the driver data structure with the names of its entry points: static struct driver eldriver = { el_probe, el_attach, "el", el_info, el_unattach, Declares and initializes the driver data structure called eldriver.
  • Page 26 READ_BUS_D8 Reads a byte (8 bits) from a device register. READ_BUS_D16 Reads a word (16 bits) from a device register. READ_BUS_D32 Reads a longword (32 bits) from a device register. READ_BUS_D64 Reads a quadword (64 bits) from a device register. WRITE_BUS_D8 Writes a byte (8 bits) to a device register.
  • Page 27: Driver-Specific Macros

    The second argument to the WRITE_CCR and the other write macros specifies the data to be written to the device register in bus address space. These write macros construct the second argument by referencing the val variable. For the if_el driver, this data is typically one of the device register offsets that is defined in the if_elreg.h file.
  • Page 28: Configure Section For A Network Driver

    Table 1–1: Driver-Specific Macros (cont.) Macro Description READ_RXS Read from the 3Com 3C5x9 device’s receive status register. READ_FDP Read from the 3Com 3C5x9 device’s FIFO diagnostic port register. 1.3 Configure Section for a Network Driver The configure section for a network device driver contains a configure interface.
  • Page 29: Watchdog Section For A Network Driver

    1.7 Watchdog Section for a Network Driver The watchdog section for a network device driver contains a watchdog interface, which attempts to restart the adapter. The watchdog interface is optional in a network device driver. If the network device driver implements it, watchdog is called by a kernel thread if the driver’s interrupt handler has not shut down the countdown timer within a certain number of seconds of queueing a data packet for transmission from the upper layer.
  • Page 30 interface to transmit the data. All network drivers must set the output member of the ifnet data structure to ether_output. 1–12 Network Device Driver Environment...
  • Page 31: Defining Device Register Offsets

    Defining Device Register Offsets The device register header file defines the device register offsets for the device. The if_elreg.h file is the device register header file for the if_el device driver. It defines the device register offsets for the 3Com 3C5x9 series Ethernet adapter.
  • Page 32: Command Port Register Offset Definitions

    Defines the interrupt latch bit position. Defines the adapter failure bit position. Defines the transmit complete bit position. Defines the transmit available bit position. Defines the receive complete bit position. Defines the receive early bit position. Defines the interrupt request bit position. Defines the update statistics bit position.
  • Page 33 #define CMD_POWERUP (0x1b<<11) #define CMD_POWERDOWN (0x1c<<11) #define CMD_POWERAUTO (0x1d<<11) Defines the offset for the I/O port of the command port register. Defines the reset command bit position. Defines the window selector for commands that are used to set up the device.
  • Page 34: Window 0 Configuration Register Offset Definitions

    Defines an enumerated data type called rx_filter. The if_el device driver can assign one of the following values to CMD_FILTER: RF_IND Individual address RF_GRP Group address RF_BRD Broadcast address RF_PRM Promiscuous address Defines the receive (RX) early threshold command. Defines the transmit (TX) available threshold command. Defines the transmit (TX) start threshold command.
  • Page 35: Window 0 Configuration Registers

    Figure 2–1: Window 0 Configuration Registers Register Constant Manufacturer ID Register W0_MID Adapter ID Register W0_AID Configuration Control Register W0_CCR Address Control Register W0_ACR Resource Configuration Register W0_RCR EEPROM Command Register W0_ECR EEPROM Data Register W0_EDR ZK-1267U-AI The following code shows the offset definitions for the registers that make up the window 0 configuration register: #define W0_MID #define W0_AID...
  • Page 36 ECR_WRITE=0x0040, ECR_ERASE=0x00c0, ECR_EWENA=0x0030, ECR_EWDIS=0x0000, ECR_EAR= 0x0020, ECR_WAR= 0x0010 #define W0_EDR Defines the offset for the manufacturer ID register. Defines the offset for the adapter ID register. Defines the offset for the configuration control register. Defines an enumerated data type called w0_ccr. The if_el device driver can assign one of the following values to W0_CCR (the configuration control register): CCR_PCMCIA...
  • Page 37: Window 3 Configuration Register Offset Definitions

    Defines an enumerated data type called w0_rcr. The if_el device driver can assign one of the following bits to W0_RCR (the resource configuration register): RCR_IRQ Represents the interrupt request (IRQ). RCR_RSV Represents a reserved field. Defines the offset for the EEPROM command register. Defines an enumerated data type called w0_ecr.
  • Page 38: Window 3 Configuration Registers

    Figure 2–2: Window 3 Configuration Registers Register Constant Additional Setup Information W3_ASI2 2 Register Additional Setup Information W3_ASI0 0 Register ZK-1268U-AI The following code shows the offset definitions for the registers that are associated with the window 3 configuration registers: #define W3_ASI2 #define W3_ASI0 enum w3_asi {...
  • Page 39: Window 1 Operational Register Offset Definitions

    ASI_RSIZE8 Indicates a RAM size of 8 kilobytes (the default). ASI_RSIZE32 Indicates a RAM size of 32 kilobytes. 2.5 Window 1 Operational Register Offset Definitions The window 1 operational registers include such registers as the receive status, the transmit status, and the request interrupt registers, as shown in Figure 2–3.
  • Page 40 #define TX_INT 0x8000 #define W1_RXDATA #define W1_TXDATA #define W1_FREETX Defines the offset for the receive status register. Defines an enumerated data type called w1_rxstat. The if_el device driver can assign one of the following values to W1_RXSTAT (the receive status register): RX_IC Indicates an incomplete operation.
  • Page 41: Window 4 Diagnostic Register Offset Definitions

    Defines the offset for the free transmit bytes register. 2.6 Window 4 Diagnostic Register Offset Definitions The window 4 operational registers include such registers as the media type and status register and the network diagnostic port register, as shown in Figure 2–4.
  • Page 42 Defines an enumerated data type called w4_media. The if_el device driver can assign one of the following values to W4_MEDIA (the media type and status register): MD_TPE Indicates that 10BaseT cable is enabled. MD_COAXE Indicates that 10Base2 cable is enabled. MD_RES1 Reserved.
  • Page 43: Eeprom Data Structure Definition

    2.7 EEPROM Data Structure Definition The following code shows the definition for the w3_eeprom data structure. This data structure stores information about the 3Com 3C5x9 device. struct w3_eeprom { unsigned short addr[3]; unsigned short pid; unsigned short mandata[3]; unsigned short mid; unsigned short addrconf;...
  • Page 45: Defining The Softc Data Structure

    Defining the softc Data Structure All network device drivers define a softc data structure to contain the software context of the network device driver and to allow the driver interfaces to share information. A softc data structure contains the following information: •...
  • Page 46: Defining Common Information

    Figure 3–1: Typical softc Data Structure Common Information Enhanced Hardware Management Information Media State Information Base Register Multicast Table Information Interrupt Handler ID CSR Pointer Information FIFO Maintenance Information Bus-Specific Information Broadcast Flag Debug Flag Interrupt and Timeout Information Autosense Kernel Thread Context Information Polling Context Flag w3_eeprom Structure...
  • Page 47 #define is_ac is_ed->ess_ac #define ztime is_ed->ess_ztime #define ctrblk is_ed->ess_ctrblk #define is_if is_ac.ac_if #define is_addr is_ac.ac_enaddr Declares an instance of the ether_driver data structure and calls it is_ed. All network drivers must have an ether_driver data structure. By convention, a pointer to this data structure is the first element in the softc data structure.
  • Page 48: Enabling Support For Enhanced Hardware Management

    Figure 3–2: Mapping Alternate Names ether_driver arpcom #define is_ac ac_if #define is_if ess_ac #define ztime #define ac_enaddr ess_ztime ac_hwaddr #define ctrblk ess_ctrblk #define is_addr ZK-1274U-AI 3.2 Enabling Support for Enhanced Hardware Management Enhanced hardware management (EHM) is a feature of Tru64 UNIX Version 5.0 that allows a system administrator to view, and possibly modify, various attributes of the hardware on either a local or a remote system.
  • Page 49 lan_media_mode usually reflects how the media is to be selected. (In contrast, the value that is stored in the lan_media member reflects the current setting of the device.) Typically, you set this member in the driver’s probe interface to the media mode constant that identifies the mode for the media.
  • Page 50: Defining The Base Register

    member in the driver’s probe interface to the media state constant that identifies the state for the media. You can set the lan_media member to the same constants that are listed for the lan_media_mode member in item 2. 3.4 Defining the Base Register The base register in a network driver’s softc data structure is a member that represents the base register of the device.
  • Page 51: Defining Fifo Maintenance Information

    access a CSR directly. The driver-specific macros handle the read and write operations that are made on these device registers. The following code shows the declarations of the CSR addresses in the if_el device driver’s el_softc data structure. Make sure that the CSR pointer information part of your softc data structure has similar declarations.
  • Page 52: Defining The Broadcast Flag

    Contains the I/O base address. Contains a tag value that identifies 3Com 3C5x9 devices on an ISA bus. Contains a value that indicates whether the user has ejected the PCMCIA card. Contains a value that indicates whether the user has reloaded the PCMCIA card.
  • Page 53: Defining Autosense Kernel Thread Context Information

    The following code shows the declarations of the timeout and interrupt information in the if_el device driver’s el_softc data structure: unsigned long txreset; unsigned long xmit_tmo; unsigned long tint; unsigned long rint; Contains the number of transmitter error resets. Contains the number of times that transmit timeouts occurred. The el_watch( ) routine increments this member.
  • Page 54: Defining A Copy Of The W3_Eeprom Data Structure

    3.15 Defining a Copy of the w3_eeprom Data Structure The w3_eeprom data structure copy in the if_el driver’s el_softc data structure consists of information about the hardware-specific w3_eeprom data structure. The following code shows the declaration of this device-specific data structure. If your device has an EEPROM, you might want to save some or all of its contents in your softc data structure.
  • Page 55: Implementing The Configure Section

    Implementing the Configure Section The configure section of a network device driver contains the code that incorporates the device driver into the kernel, either statically or dynamically. In a static configuration, the device driver’s configure interface registers callback routines, which allow the cfgmgr framework to configure the driver into the kernel at a specified point during system startup.
  • Page 56 The following code shows the declaration of the variables and the initialization of the cfg_subsys_attr_t data structure for the if_el device driver: static unsigned char el_pcmcia_optiondata[400] = ""; static unsigned char el_isa_optiondata[300] = ""; static unsigned char el_unused[300] = ""; static int el_polling = 0;...
  • Page 57: Setting Up The El_Configure Routine

    Declares the lan_config_data structure, which contains all information specific to the el driver. The lan_configure common code uses this structure. Declares an array of cfg_subsys_attr_t data structures and calls it el_attributes. Describes the PCMCIA_Option attribute, which specifies the option data for the PCMCIA bus. Describes the ISA_Option attribute, which specifies the option data for the ISA bus.
  • Page 58 represents a variety of information, including the if_el driver’s interrupt polling requirements. Declares an argument called indatalen to store the size of this input data structure. This argument represents the number of cfg_attr_t data structures included in indata. Declares an argument for user-defined configuration operations, which can occur when the cfgmgr framework calls the driver’s configure interface with the CFG_OP_USERDEFINED operation code.
  • Page 59: Implementing The Autoconfiguration Support Section (Probe)

    Implementing the Autoconfiguration Support Section (probe) The autoconfiguration support section contains the code that implements a network device driver’s probe interface. A network device driver’s probe interface determines whether the network device exists and is functional on a given system. The bus configuration code calls the driver’s probe interface. The if_el driver operates on the ISA and PCMCIA bus.
  • Page 60: Setting Up The El_Probe Routine

    • For subsequent probe operations, reads the EEPROM to determine if the hardware address (and thus the adapter) has changed (Section 5.1.10) • Registers the interrupt handler (Section 5.1.11) • Saves the controller and softc data structure pointers (Section 5.1.12) •...
  • Page 61 contained in the ctlr_num member of the controller data structure for this 3Com 3C5x9 device. Declares a handler_intr_info data structure called el_intr_info. The handler_intr_info data structure is a generic data structure that contains interrupt handler information for buses that are connected to a device controller.
  • Page 62: Checking The Maximum Number Of Devices That The Driver Supports

    5.1.2 Checking the Maximum Number of Devices That the Driver Supports The following code shows how to check for the maximum number of devices that the if_el device driver supports: if (unit >= el_MAXDEV) { printf("el%d: el_probe: unit exceeds max supported devices\n", unit);...
  • Page 63 case BUS_ISA: if (get_config(ctlr, RES_PORT, NULL, &port_sel, 0) >= 0) { reg = port_sel.base_address; } else { printf("el%d: Can’t get assigned IOBASE\n",unit); return(0); if (get_config(ctlr, RES_IRQ, NULL, &irq_sel, 0) < 0) { printf("el%d: Can’t get assigned IRQ\n", unit); return(0); if (el_isa_reset++ == 0) el_isa_reset_all(reg, &isatag, ctlr);...
  • Page 64: Allocating Memory For The Softc Data Structure

    Calls the READ_BUS_D16 macro a second time to determine whether the EtherLink III is attached. If the data returned by READ_BUS_D16 is not 0x6d50, calls the printf( ) routine to display an appropriate message on the console terminal. Returns the value 0 (zero) to indicate that the probe operation failed. Performs tasks related to the ISA bus if bus_type evaluates to the constant BUS_ISA.
  • Page 65: Allocating The Ether_Driver Data Structure

    if (el_softc[unit]) { sc = el_softc[unit]; sc->cardout = 0; sc->reprobe = 1; } else { MALLOC(sc, void*, sizeof(struct el_softc), M_DEVBUF, M_WAIT | M_ZERO); if (!sc) { printf("el%d: el_probe: failed to get buffer memory for softc\n", unit); return(0); If the user removed and returned the PCMCIA card to its slot: •...
  • Page 66: Initializing The Enhanced Hardware Management Data Structure

    Initializes all Ethernet statistics counters in the ether_driver data structure to 0 (zero). 5.1.6 Initializing the Enhanced Hardware Management Data Structure The following code shows how the el_probe( ) routine initializes the data structure for enhanced hardware management (EHM) support: lan_ehm_init(&sc->ehm, NET_EHM_VERSION_ID);...
  • Page 67 sc->irq = 3; sc->iobase = 0; sc->ispcmcia = 1; sc->cinfop =card_infop; pcmcia_register_event_callback(card_infop->socket_vnum, CARD_REMOVAL_EVENT, (caddr_t)el_card_remove, (caddr_t)sc); if (multi_func_flag) lan_set_attribute(sc->ehm.current_val, NET_MODEL_NDX, "3C562"); else lan_set_attribute(sc->ehm.current_val, NET_MODEL_NDX, "3C589"); break; case BUS_ISA: sc->irq = irq_sel.channel; sc->isa_tag = isatag; sc->iobase = ((reg-0x200)/0x10)&0x1f; lan_set_attribute(sc->ehm.current_val, NET_MODEL_NDX, "3C509"); break; Evaluates the bus_type member of the bus data structure for this 3Com 3C5x9 device.
  • Page 68: Handling First-Time Probe Operations

    5.1.9 Handling First-Time Probe Operations If the device has not already been probed, the el_probe( ) routine performs the following tasks: • Reads the EEPROM and saves it to a temporary data structure • Reads and saves the device’s physical address •...
  • Page 69 for (i=0; i<(sizeof(struct w3_eeprom)/2); i++) { WRITE_ECR(sc, ECR_READ+i); DELAY(1000); *ed = READ_EDR(sc); ed++; for (i=0; i<3; i++) { j = sc->eeprom.addr[i]; sc->is_addr[(i*2)] = (j>>8) & 0xff; sc->is_addr[(i*2)+1] = (j) & 0xff; sc->lm_media_mode = LAN_MODE_AUTOSENSE; sc->lm_media_state = LAN_MEDIA_STATE_SENSING; sc->lm_media = LAN_MEDIA_UTP; sc->autosense_thread = kernel_thread_w_arg(first_task, el_autosense_thread, (void *)sc);...
  • Page 70: Handling Subsequent Probe Operations

    Calls the kernel_thread_w_arg( ) routine to create and start a kernel thread with timeshare scheduling. A kernel thread that is created with timeshare scheduling means that its priority degrades if it consumes an inordinate amount of CPU resources. Make sure that your device driver calls kernel_thread_w_arg( ) only for long-running tasks and always attaches a kernel thread to the first task.
  • Page 71 if (status == SUCCESS) { ee = (unsigned char *)&ee_copy; for (i = 0; i < (sizeof(struct w3_eeprom)); i++) { *ee = tuple_data_infop->TupleData[i]; ee++; } else { printf("el%d: Can’t read multifunction card’s eeprom.\n", unit); if (sc->ispcmcia) pcmcia_unregister_event_callback(card_infop->socket_vnum, CARD_REMOVAL_EVENT, (caddr_t)el_card_remove); return(0); } else { printf("el%d: Can’t read multifunction card’s eeprom.\n", unit);...
  • Page 72: Registering The Interrupt Handler

    bcopy(&ee_copy, &sc->eeprom, sizeof(struct w3_eeprom)); If this is a multifunction card, reads the EEPROM data and saves it in a temporary data structure, ee_copy. If this is a 3Com 3C562 multifunction PC card, the EEPROM data is located in the card information data structure.
  • Page 73 registration of interrupt handlers. All network device drivers are required to register interrupt handlers. el_intr_info.configuration_st = (caddr_t)ctlr; el_intr_info.intr = el_intr; el_intr_info.param = (caddr_t)unit; el_intr_info.config_type = CONTROLLER_CONFIG_TYPE; if (ctlr->bus_hd->bus_type == BUS_PCMCIA) el_intr_info.config_type |= SHARED_INTR_CAPABLE; el_ihandle.ih_bus = ctlr->bus_hd; el_ihandle.ih_bus_info = (char *)&el_intr_info; sc->hid = handler_add(&el_ihandle);...
  • Page 74: Saving The Controller And Softc Data Structure Pointers

    This routine returns an opaque ihandler_id_t key, which is a unique number that identifies the interrupt handler to be acted on by subsequent calls to handler_del, handler_disable, and handler_enable. The hid member of the el_softc data structure stores this key. If the return value from handler_add equals NULL, the if_el driver failed to register an interrupt handler for the if_el device.
  • Page 75: Registering The Shutdown Routine

    5.1.14 Registering the shutdown Routine The following code shows how the el_probe( ) routine registers its shutdown( ) routine. The kernel calls this routine when the system shuts down. The driver can specify an argument for the kernel to pass to the routine at that time.
  • Page 76 To determine the mode, el_autosense_thread( ) tries to send a test data packet in each of the possible modes. When it successfully transmits the data packet, it sets the network interface to that mode. The lm_media_mode, lm_media, and lm_media_state members of the el_softc data structure keep track of the progress of the autosensing procedure, as follows: •...
  • Page 77: Setting Up The El_Autosense_Thread Routine

    • Determines whether packets were transmitted successfully (Section 5.3.14) • Prints debug information (Section 5.3.15) • Sets up new media to try if transmit was unsuccessful (Section 5.3.16) • Establishes media if transmit was successful (Section 5.3.17) 5.3.1 Setting Up the el_autosense_thread Routine The following code shows how to set up the el_autosense_thread( ) routine: unsigned char el_junk_msg[] = {...
  • Page 78: Testing For The Termination Flag

    5.3.3 Testing for the Termination Flag The following code shows how the el_autosense_thread( ) routine tests for the termination flag: while (thread_should_halt(sc->autosense_thread)) { printf("el%d: Autosense thread exiting\n", ifp->if_unit); thread_halt_self(); Performs an initial test for the termination flag. The termination flag would have been set if another kernel thread had called the thread_terminate( ) routine for the el_autosense_thread( ) routine.
  • Page 79: Saving Counters Prior To The Transmit Operation

    simple_unlock(&sc->el_softc_lock); splx(s); thread_halt_self(); Enters a loop for transmitting a packet and determining if it succeeds. A packet must go out twice successfully for media selection to succeed. This algorithm probably will not work in all cases. 5.3.6 Saving Counters Prior to the Transmit Operation The following code shows how the el_autosense_thread( ) routine saves counters prior to the transmit operation: prev_tint= sc->tint;...
  • Page 80: Setting The Media In The Hardware

    ifp->if_unit, lan_media_strings_10[sc->lm_media]); good_xmits = 100; Uses the default from ROM. 5.3.9 Setting the Media in the Hardware The following code shows how the el_autosense_thread( ) routine sets the media setting in the hardware: el_reset(ifp->if_unit); break; } else { Directs the hardware to use the media setting that was selected in the previous section.
  • Page 81: Setting A Timer For The Current Kernel Thread

    5.3.12 Setting a Timer for the Current Kernel Thread The following code shows how the el_autosense_thread( ) routine sets a timer for the current kernel thread: wait = 0; while ((prev_tint == sc->tint) && (prev_tmo == sc->xmit_tmo) && (wait++ < 4)) { assert_wait((vm_offset_t)&wait_flag, TRUE);...
  • Page 82: Determining Whether Packets Were Transmitted Successfully

    WRITE_CMD(sc, CMD_WINDOW1); simple_unlock(&sc->el_softc_lock); splx(s); break; default: break; Tests for loss of carrier errors. Most network adapters give carrier errors if no cable is plugged in or if transceivers are not present. 5.3.14 Determining Whether Packets Were Transmitted Successfully The following code shows how the el_autosense_thread( ) routine determines whether packets were successfully transmitted: if ((prev_err == ifp->if_oerrors) &&...
  • Page 83: Establishing The Media

    if (sc->lm_media_mode == LAN_MODE_AUTOSENSE) sc->lm_media = LAN_MEDIA_UTP; break; case LAN_MEDIA_BNC: if (sc->lm_media_mode == LAN_MODE_AUTOSENSE) sc->lm_media = LAN_MEDIA_AUI; break; case LAN_MEDIA_UTP: default: if (sc->lm_media_mode == LAN_MODE_AUTOSENSE) sc->lm_media = LAN_MEDIA_BNC; break; el_reset(ifp->if_unit); Selects new media. Calls the el_reset( ) routine to reset the hardware. This reset will establish the next media to try.
  • Page 84 Because simple locks are spin locks, simple_lock( ) does not return until the lock has been obtained. The el_softc_lock member of the el_softc data structure points to a simple lock data structure. The if_el device driver declares this data structure by calling the decl_simple_lock_data( ) routine. Calls the WRITE_CMD macro to write data to the command port register.
  • Page 85: Implementing The Autoconfiguration Support Section (Attach)

    Implementing the Autoconfiguration Support Section (attach) The autoconfiguration support section implements a network device driver’s attach interface. A network device driver’s attach interface establishes communication with the device. The interface initializes the pointer to the ifnet data structure and attaches the network interface to the packet filter. The bus configuration code calls the driver’s attach interface.
  • Page 86: Initializing The Media Address And Media Header Lengths

    of the controller. The bus configuration code passes this initialized controller data structure to the driver’s probe and attach interfaces. Declares a unit variable and initializes it to the controller number for this controller. This controller number identifies the specific 3Com 3C5x9 controller that is being attached.
  • Page 87: Setting Up The Media

    header length is the size of the ether_header data structure plus 8 (the size of the maximum LLC header). The media headers are represented by the following data structures: ether_header The media header structure for Ethernet-related media. The if_ether.h file defines the ether_header structure.
  • Page 88 Sets the if_mtu member of the ifnet data structure for this device to the maximum transmission unit, which for Ethernet-related media is represented by the constant ETHERMTU. The following media-specific constants represent the maximum transmission unit: ETHERMTU The maximum transmission unit for Ethernet media.
  • Page 89: Initializing Simple Lock Information

    Sets the sin_family member of the sockaddr_in data structure to the address family, which in this case is represented by the constant AF_INET. The socket.h file defines this and other address family constants. 6.4 Initializing Simple Lock Information The following code shows how the el_attach( ) routine sets up simple lock information: ifp->if_affinity = NETALLCPU;...
  • Page 90: Printing A Success Message

    6.5 Printing a Success Message The following code shows how the el_attach( ) routine prints a success message: printf("el%d: %s, hardware address: %s\n", unit, ifp->if_version, ether_sprintf(sc->is_addr)); Calls the printf( ) routine to display the following information message on the console terminal: •...
  • Page 91 Sets the if_start member of the ifnet data structure for this device to el_start, which is the if_el device driver’s start transmit for output interface. Sets the if_output member of the ifnet data structure for this device to ether_output, which is the if_el device driver’s output interface.
  • Page 92: Setting The Baud Rate

    Sets the if_version member of the ifnet data structure for this device to the string 3Com EtherLink III. 6.7 Setting the Baud Rate The following code shows how the el_attach( ) routine sets the baud rate: ifp->if_baudrate = ETHER_BANDWIDTH_10MB; Sets the if_baudrate member of the ifnet data structure for this device to the constant ETHER_BANDWIDTH_10MB.
  • Page 93: Setting Network Attributes And Registering The Adapter

    Calls the if_attach( ) routine to attach an interface to the list of active interfaces. The argument to the if_attach( ) routine is a pointer to the ifnet data structure for with this device. If the probe and attach operations were successful, increments the number of successfully configured el devices.
  • Page 94: Enabling The Interrupt Handler

    6.11 Enabling the Interrupt Handler The following code shows how the el_attach( ) routine enables the interrupt handler: handler_enable(sc->hid); Calls the handler_enable( ) routine to enable a previously registered interrupt handler. The el_probe( ) routine calls handler_add to register the interrupt handler and it stores the handler ID in the hid member of the el_softc data structure for this device.
  • Page 95: Implementing The Unattach Routine

    Implementing the unattach Routine The el_unattach( ) routine is called to stop the device and to free memory and other resources prior to unloading the driver or powering off the bus to which the device is attached. The el_unattach( ) routine undoes everything that was performed by the el_probe( ) and el_attach( ) routines.
  • Page 96: Verifying That The Interface Has Shut Down

    struct el_softc *sc = el_softc[unit]; struct ifnet *ifp = &sc->is_if; Declares as an argument a pointer to a bus data structure and a controller data structure for this controller. The controller data structure contains such information as the controller type, the controller name, and the current status of the controller.
  • Page 97: Disabling The Interrupt Handler

    s variable. This value represents the CPU priority level that existed before the call to splimp( ). Calls the simple_lock( ) routine to assert a lock with exclusive access for the resource that is associated with the el_softc_lock data structure. This means that no other kernel thread can gain access to the locked resource until you call simple_unlock( ) to release it.
  • Page 98: Unregistering The Pcmcia Event Callback Routine

    7.6 Unregistering the PCMCIA Event Callback Routine The following code shows how the el_unattach( ) routine unregisters the PCMCIA event callback routine: if (sc->ispcmcia) pcmcia_unregister_event_callback(sc->cinfop->socket_vnum, CARD_REMOVAL_EVENT, (caddr_t)el_card_remove); For PCMCIA versions of the card, directs the bus code not to return notification if the card has been removed.
  • Page 99: Unregistering The Card From The Hardware Management Database

    7.10 Unregistering the Card from the Hardware Management Database The following code shows how the el_unattach( ) routine unregisters the card from the hardware management database: lan_ehm_free(&sc->ehm); Frees up any memory allocated for enhanced hardware management and unregisters this card from the hardware management database. 7.11 Freeing Resources The following code shows how the el_unattach( ) routine frees data structures and memory that the adapter uses:...
  • Page 101: Implementing The Initialization Section

    Implementing the Initialization Section The initialization section prepares the network interface to transmit and receive data packets. It can also allocate mbuf data structures for the receive ring. The if_el device driver implements the following routines in its initialization section: •...
  • Page 102: Determining Whether The Pcmcia Card Is Present

    Declares a pointer to an ifnet data structure called ifp and initializes it to the address of the ifnet data structure for this device. The ifnet data structure is referenced through the is_if member of the el_softc data structure pointer. The is_if name is an alternate name for the ac_if member of the arpcom data structure.
  • Page 103: Calling The El_Init_Locked Routine

    The el_softc_lock member of the el_softc data structure points to a simple lock data structure. The if_el device driver declares this data structure by calling the decl_simple_lock_data( ) routine. 8.1.4 Calling the el_init_locked Routine The following code shows how the el_init( ) routine calls the el_init_locked( ) routine, which performs the actual initialization tasks: i = el_init_locked(sc, ifp, unit);...
  • Page 104: Resetting The Transmitter And Receiver

    • Sets the LAN media type attribute (Section 8.2.6) • Selects memory mapping (Section 8.2.7) • Resets the transmitter and receiver a second time (Section 8.2.8) • Sets the LAN address (Section 8.2.9) • Processes special flags (Section 8.2.10) • Sets the debug flag (Section 8.2.11) •...
  • Page 105: Starting The Device

    This task is specific to the 3Com 3C5x9 device. Make sure that you perform similar initialization tasks for the hardware device that your network driver controls. WRITE_CMD(sc, CMD_ACKINT+0xff); Calls the WRITE_CMD macro to write data to the command port register. The data written to the command port register is the acknowledge interrupt command (CMD_ACKINT) plus a mask that specifies that all interrupts are to be acknowledged.
  • Page 106: Setting The Lan Media

    8.2.5 Setting the LAN Media The following code shows how the el_init_locked( ) routine sets the LAN media. This task is specific to the 3Com 3C5x9 device. You may want to perform similar initialization tasks for the hardware device that your network driver controls.
  • Page 107: Setting A Lan Attribute

    For the default case, sets the lm_media member to LAN_MEDIA_UTP (media mode is unshielded twisted pair cable). Determines whether lm_media evaluates to LAN_MEDIA_UTP. Calls WRITE_ACR to write to the address control register. The data to be written establishes the Ethernet unshielded twisted-pair cable as the media.
  • Page 108: Setting The Lan Address

    WRITE_CMD(sc, CMD_TXRESET); WRITE_CMD(sc, CMD_RXRESET); Calls the WRITE_CMD macro to write data to the command port register. The data to be written is the transmit (TX) reset command (CMD_TXRESET). Calls the WRITE_CMD macro to write data to the command port register. In this call, the data to be written is the receive (RX) reset command (CMD_RXRESET).
  • Page 109: Setting The Debug Flag

    else { lan_set_attribute(sc->ehm.current_val, NET_PROMISC_NDX, (void *)0); WRITE_CMD(sc, CMD_FILTER+i); If loopback mode is requested, enables it. Sets the LAN loopback attribute for EHM support. Selects to receive frames that are sent to both the local address and the broadcast address. If the network device receives all multicast packets, selects all group addresses.
  • Page 110: Enabling Interrupts

    WRITE_CMD(sc, CMD_RXENA); WRITE_CMD(sc, CMD_TXENA); Calls the WRITE_CMD macro to write data to the command port register. The data to be written is the receive (RX) enable command (CMD_RXENA). Calls the WRITE_CMD macro to write data to the command port register. In this call, the data to be written is the transmit (TX) enable command (CMD_TXENA).
  • Page 111: Starting The Autosense Kernel Thread

    ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~ IFF_OACTIVE; Sets the IFF_RUNNING flag to mark the device as running. Clears the IFF_OACTIVE flag to indicate that there is no output outstanding. 8.2.16 Starting the Autosense Kernel Thread The following code shows how the el_init_locked( ) routine starts the autosense kernel thread.
  • Page 113: Implementing The Start Section

    Implementing the Start Section The start section of a network device driver transmits data packets across the network. When the network protocol has a data packet to transmit, it prepares the packet, then calls the start interface for the appropriate network device driver.
  • Page 114: Calling The El_Start_Locked Routine

    Calls the simple_lock_try( ) routine to try to assert a lock with read and write access for the resource that is associated with the specified simple lock. The el_start( ) routine calls simple_lock_try( ) rather than simple_lock( ) because simple_lock_try( ) returns immediately if the resource is already locked;...
  • Page 115: Implementing The El_Start_Locked Routine

    This simple lock was previously asserted by calling the simple_lock( ) or simple_lock_try( ) routine. Calls the splx( ) routine to reset the CPU priority to the level that the s variable specifies. 9.2 Implementing the el_start_locked Routine The el_start_locked( ) routine performs the start operation. It is called by the if_el device driver’s el_init_locked( ), el_start( ), el_intr( ), and el_autosense_thread( ) routines.
  • Page 116: Removing Packets From The Pending Queue And Preparing

    IF_DEQUEUE(&ifp->if_snd, m); while (m) { m_freem(m); IF_DEQUEUE(&ifp->if_snd, m); return; Declares a pointer to an ether_header data structure called eh. The ether_header data structure contains information that is associated with a 10 Mb/s and 100 Mb/s Ethernet header. If the cardout member of the el_softc data structure for this device is set to 1 (true), the user removed the PCMCIA card from the slot.
  • Page 117 mp = ms; mn = mp->m_next; len = mp->m_len; while (mn != NULL) { if (mn->m_len == 0) { mp->m_next = mn->m_next; mn->m_next = NULL; m_free(mn); } else { len += mn->m_len; mp = mn; mn = mp->m_next; While true, removes packets from the pending queue and has the device transmit the packets.
  • Page 118: The Transmit Buffer

    in the middle. The mfree( ) routine is called to free any zero-length memory buffers. Otherwise, adds the length and sets the next memory buffer in the chain to the mp mbuf pointer. 9.2.3 Transmitting the Buffer The following code shows how the el_start_locked( ) routine transmits the buffer: WRITE_DATA(sc, len | TX_INT);...
  • Page 119: Accounting For Outgoing Bytes

    Copies transmit data from memory to the card using 32-bit writes. Only a multiple of 4 bytes can be copied this way. If some number of bytes (fewer than 4) remain in the current memory buffer, the driver either copies those bytes directly to the card (if they were the last bytes for the entire frame), or combines those bytes with bytes from the next memory buffer (if there is more data for this frame).
  • Page 120: Indicating When To Start The Watchdog Routine

    9.2.6 Indicating When to Start the Watchdog Routine The following code shows how the el_start_locked( ) routine indicates the time for starting the driver’s watchdog interface. Although this task is optional, we recommend that all network drivers perform this task. ifp->if_timer = 3;...
  • Page 121: Implementing A Watchdog Section

    Implementing a Watchdog Section Network device drivers can take advantage of the watchdog timer. The network layer implements this mechanism to ensure that the network device is transmitting data. The driver starts the watchdog timer when it sends a transmit request to the device. After it receives the transmit completion interrupt, the driver stops the timer.
  • Page 122: Incrementing The Transmit Timeout Counter And Resetting

    Calls the simple_lock( ) routine to assert a lock with exclusive access for the resource that is associated with the el_softc_lock simple lock data structure pointer. This means that no other kernel thread can gain access to the locked resource until you call simple_unlock( ) to release it.
  • Page 123: Implementing The Reset Section

    Implementing the Reset Section The reset section of a network device driver contains the code that resets the LAN adapter when there is a network failure and there is a need to restart the device. It resets all of the counters and local variables and can free up and reallocate all of the buffers that the network driver uses.
  • Page 124: Implementing The El_Reset_Locked Routine

    Calls the el_reset_locked( ) routine, which performs the actual tasks that are associated with resetting the device. Calls the simple_unlock( ) routine to release the simple lock for the el_softc data structure and then resets the CPU priority to the level that it was originally at upon entrance to this routine.
  • Page 125: Implementing The Ioctl Section

    Implementing the ioctl Section The ioctl section of a network device driver contains the code that implements a network device driver’s ioctl interface. The ioctl interface performs miscellaneous tasks that have nothing to do with data packet transmission and reception. Typically, it turns specific features of the hardware on or off. The el_ioctl( ) routine performs the following tasks: •...
  • Page 126: Setting Up The El_Ioctl Routine

    Table 12–1: Network ioctl Commands (cont.) Required Description For More Information ioctl Command SIOCSIFFLAGS Ensures that the Section 12.12 interface is operating correctly according to the interface flags (if_flags). SIOCSIPMTU Sets the IP maximum Section 12.13 transmission unit (MTU). SIOCSMACSPEED Sets the media speed.
  • Page 127: Determining Whether The User Has Removed The Pcmcia

    Casts the data argument to a data structure of type ifdevea for use with the SIOCRPHYSADDR ioctl command. Casts the data argument to a data structure of type ctrreq for use with the SIOCRDCTRS and SIOCRDZCTRS ioctl commands. Casts the data argument to a data structure of type ifchar for use with the SIOCIFSETCHAR ioctl command.
  • Page 128: Enabling Loopback Mode (Siocenablback Ioctl Command)

    you call simple_unlock( ) to release it. Because simple locks are spin locks, simple_lock( ) does not return until the lock has been obtained. 12.4 Enabling Loopback Mode (SIOCENABLBACK ioctl Command) The following code shows how the el_ioctl( ) routine implements the SIOCENABLBACK ioctl command to enable loopback mode when an application requests it.
  • Page 129: Reading Current And Default Mac Addresses (Siocrphysaddr Ioctl Command)

    12.6 Reading Current and Default MAC Addresses (SIOCRPHYSADDR ioctl Command) The following code shows how the el_ioctl( ) routine implements the SIOCRPHYSADDR ioctl command to read the current and default MAC addresses when an application requests them: case SIOCRPHYSADDR: bcopy(sc->is_addr, ifd->current_pa, 6); for (i=0;...
  • Page 130: Adding The Device To A Multicast Group (Siocaddmulti Ioctl Command)

    If the 3Com 3C5x9 device is running, calls the el_reset_locked( ) routine to restart the network interface with the new address. Calls the simple_unlock( ) routine to release the simple lock for the resource that is associated with el_softc_lock. Calls the splx( ) routine to reset the CPU priority to the level that the s variable specifies.
  • Page 131: Deleting The Device From A Multicast Group (Siocdelmulti Ioctl Command)

    ether_sprintf(maddr), sc->is_multi.lan_mtable[j-1].muse); lan_build_mclist (mclist_buf, NET_SZ_MCLIST, &sc->is_multi); lan_set_attribute(sc->ehm.current_val, NET_MCLIST_NDX, mclist_buf); break; Determines whether the cmd argument is SIOCADDMULTI. If the address is broadcast, indicates the presence of another broadcast user. If the address is multicast, the el_ioctl( ) routine adds the address to the table.
  • Page 132: Accessing Network Counters (Siocrdctrs And Siocrdzctrs Ioctl Commands)

    if (sc->debug) { j = 0; printf("el%d: Dump of multicast table after DEL (%d entries)\n", unit, sc->is_multi.lan_nmulti); for (i=0; i<sc->is_multi.lan_nmulti; i++) { unsigned char *maddr; LAN_GET_MULTI(&sc->is_multi, maddr, j); printf(" %s (muse==%d)\n", i+1, ether_sprintf(maddr), sc->is_multi.lan_mtable[j-1].muse); lan_build_mclist (mclist_buf, NET_SZ_MCLIST, &sc->is_multi); lan_set_attribute(sc->ehm.current_val, NET_MCLIST_NDX, mclist_buf); break;...
  • Page 133: Bringing Up The Device (Siocsifaddr Ioctl Command)

    FDDI FDDI interface statistics Status information SMT attributes MAC attributes Path attributes Port attributes SMT MIB attributes Extended MIB attributes (Compaq proprietary) Token Ring Characteristics Counters MIB counters MIB statistics 12.11 Bringing Up the Device (SIOCSIFADDR ioctl Command) The following code shows how the el_ioctl( ) routine implements the...
  • Page 134: Using Currently Set Flags (Siocsifflags Ioctl Command)

    Marks the interface as up and calls the el_reset_locked( ) routine to start the network interface with the current settings. Sets the counter cleared time (used by DECnet, netstat, clusters, and so forth). 12.12 Using Currently Set Flags (SIOCSIFFLAGS ioctl Command) The following code shows how the el_ioctl( ) routine implements the SIOCSIFFLAGS ioctl command to reset the device using currently set flags:...
  • Page 135: Resetting The Device (Siocifreset Ioctl Command)

    SIOCSMACSPEED and SIOCIFSETCHAR ioctl commands perform some of the same tasks.) case SIOCSMACSPEED: bcopy(ifr->ifr_data, (u_char *)&speed, sizeof(u_short)); if ((speed != 0) && (speed != 10)) { status = EINVAL; break; break; Determines whether the cmd argument is SIOCSMACSPEED. If the LAN speed passed is anything other than 10 (0 means no change), fails the request.
  • Page 136 if (ifc->ifc_auto_sense != -1) { if ((ifc->ifc_auto_sense == LAN_AUTOSENSE_ENABLE) && (sc->lm_media_mode != LAN_MODE_AUTOSENSE)) { sc->lm_media_mode = LAN_MODE_AUTOSENSE; need_reset++; } else if ((ifc->ifc_auto_sense == LAN_AUTOSENSE_DISABLE) && (sc->lm_media_mode == LAN_MODE_AUTOSENSE)) { sc->lm_media_mode = sc->lm_media; need_reset++; if (ifc->ifc_media_type != -1) { switch (ifc->ifc_media_type) { case LAN_MEDIA_UTP: case LAN_MEDIA_AUI: case LAN_MEDIA_BNC:...
  • Page 137: Releasing The Simple Lock And Resetting The Ipl

    If the user sets media that the card does not have, the interface may not work. Selects the new mode. Resets the device to pick up the new mode (if the interface was running). The default case returns an error that indicates that the caller has issued an invalid ioctl command.
  • Page 139: Implementing The Interrupt Section

    Implementing the Interrupt Section The interrupt section of a network device driver contains the code that is called whenever the network interface transmits or receives a frame. The if_el device driver implements the following routines in its interrupt section: • el_intr( ) (Section 13.1) •...
  • Page 140: Setting The Ipl And Obtaining The Simple Lock

    13.1.1 Setting the IPL and Obtaining the Simple Lock The following code shows how the el_intr( ) routine sets the CPU’s IPL and obtains the simple lock: static int el_intr(int unit) register u_int s; volatile u_int status; register struct el_softc *sc = el_softc[unit]; register struct ifnet *ifp = &sc->is_if;...
  • Page 141: Reading The Interrupt Status

    13.1.3 Reading the Interrupt Status The following code shows how the el_intr( ) routine uses the READ_STS macro to read the interrupt status from the I/O status register: status = READ_STS(sc); 13.1.4 Processing Completed Receive and Transmit Operations The following code shows how the el_intr( ) routine processes the receive and transmit rings: if (((status &...
  • Page 142: Acknowledging The Interrupt

    • If the status variable has the S_AF bit set, calls the el_error( ) routine to process the error. • Calls the READ_STS macro to read the interrupt status again from the I/O status register. 13.1.5 Acknowledging the Interrupt The following code shows how the el_intr( ) routine acknowledges the interrupt: WRITE_CMD(sc, CMD_ACKINT+(S_IL));...
  • Page 143: Indicating That The Interrupt Was Serviced

    13.1.8 Indicating That the Interrupt Was Serviced The following code shows how the el_intr( ) routine indicates that the interrupt was serviced: return INTR_SERVICED; Returns the INTR_SERVICED constant to the kernel interrupt dispatcher to indicate that el_intr( ) serviced the shared interrupt. 13.2 Implementing the el_rint Routine The if_el driver’s el_rint( ) routine is the receive interrupt completion routine.
  • Page 144: Pulling The Packets From The Fifo Buffer

    13.2.2 Pulling the Packets from the FIFO Buffer The following code shows how the el_rint( ) routine pulls the packets from the first-in/first-out (FIFO) buffer. This task is specific to the hardware device that is associated with the if_el device driver. If you need to perform a similar task with your hardware device, use this example as a model.
  • Page 145: Examining The First Part Of The Packet

    Looks for errors. Processes the error. Processes the overrun error case. Processes the runt and oversized error cases. Processes the CRC error case. Processes the alignment error case. Discards the packet if none of the previous cases apply. This indicates a size error.
  • Page 146: Copying The Received Packet Into The Mbuf

    if (bcmp(mtod(m, unsigned char *), etherbroadcastaddr, 6) != 0) { int ix; LAN_FIND_MULTI(&sc->is_multi, mtod(m, unsigned char *), ix, i); if ( (i != LAN_MULTI_FOUND) || (sc->is_multi.lan_mtable[ix].muse == 0)) { m_freem(m); goto scrap; If an mbuf was successfully allocated, copies the packet data into the mbuf (receive data are 32-bit aligned).
  • Page 147: Discarding A Packet

    eh = *(mtod(m, struct ether_header *)); eh.ether_type = ntohs((unsigned short)eh.ether_type); m->m_data += sizeof(struct ether_header); ADD_RECV_PACKET(ifp, sc, m->m_pkthdr.len); if (eh.ether_dhost[0] & 0x1) { ADD_RECV_MPACKET(ifp, sc, m->m_pkthdr.len); i = READ_RXS(sc); if (i &= 0x7ff) { if ((i & 0x400) == 0) { m_freem(m);...
  • Page 148: Implementing The El_Tint Routine

    if ((sc->debug) && (count <= 0)) printf("el%d: Receive in INFINITE loop %04X\n", ifp->if_unit, status); Calls the WRITE_CMD macro to write data to the command port register. The data to be written is the receive discard top packet command (CMD_RXDTP). 13.3 Implementing the el_tint Routine The if_el device driver’s el_tint( ) routine is the transmit interrupt completion routine.
  • Page 149: Managing Excessive Data Collisions

    WRITE_CMD(sc, CMD_TXRESET); DELAY(10); WRITE_CMD(sc, CMD_TXENA); Calls the READ_TXS macro to read the transmit status from the transmit status register. Examines the status for a jabber or an underrun error. If either of these errors happened, then the transmitter must be reset. Clears the transmit status register and resets the transmitter.
  • Page 150: Queuing Other Transmits

    Updates the softc data structure with the amount of space that is available in the transmit FIFO. 13.3.5 Queuing Other Transmits The following code shows how the el_tint( ) routine clears the output active flag to permit other transmits to be queued to the device: ifp->if_flags &= ~IFF_OACTIVE;...
  • Page 151: Network Device Driver Configuration

    Network Device Driver Configuration Device driver configuration incorporates device drivers into the kernel to make them available to system administration and other utilities. The operating system provides two methods for configuring drivers into the kernel: static and dynamic. We recommend that you implement your driver products as a single binary module so that customers can statically or dynamically configure them into the kernel.
  • Page 153: Index

    Index Numbers and Special Characters carrier , 5–23 10Base2 transceiver checking for transmits , 8–5 ensuring that it is off cfg_subsys_attr_t data structure 4–2 command port register , 2–2 definitions common information allocating the ether_driver data , 3–2 el_softc data structure , 5–7 structure , 5–8...
  • Page 154 , 13–4 of pending transmit frames SIOCADDMULTI ioctl command , 13–8 12–6 of receive interrupt , 3–8 debug flag SIOCDELMULTI ioctl command , 8–9 12–7 setting debug information SIOCDISABLBACK ioctl command , 5–24 printing 12–4 declarations SIOCENABLBACK ioctl command , 4–2 configure-related 12–4 , 1–4...
  • Page 155 initializing the enhanced hardware , 5–8 management data structure hardware address , 5–4 performing bus-specific tasks , 5–12 determining a change registering interrupt handlers , 12–5 reading current 5–15 header file registering the shutdown routine , 1–4 devdriver.h 5–17 , 1–3 errno.h saving controller and el_softc data , 2–1...
  • Page 156 interrupt handler , 6–10 enabling kernel thread , 3–6 , 5–19 blocking , 5–15 registering , 5–23 setting a timer for , 1–11 interrupt section , 5–10 starting , 13–1 implementing ioctl command , 12–6 SIOCADDMULTI , 12–7 SIOCDELMULTI , 12–4 SIOCDISABLBACK , 8–8 setting address...
  • Page 157 autoconfiguration support section PCI_Option entry 1–10 , 14–1 sysconfigtab file fragment PCMCIA bus , 1–10 configure section , 9–3 discarding all transmits , 1–4 declarations initializing bus-specific data , 1–1 environment , 5–8 , 1–3 structure include files , 5–4 , 1–10 probe initialization section...
  • Page 158 SIOCDISABLBACK ioctl , 5–21 , 12–4 using the default from command RX status SIOCENABLBACK ioctl command , 13–5 reading 12–4 SIOCIFRESET ioctl command 12–11 SIOCIFSETCHAR ioctl command section 12–11 , 1–10, autoconfiguration support SIOCRDCTRS ioctl command 5–1, 6–1 12–8 , 1–10 configure SIOCRDZCTRS ioctl command , 1–4...
  • Page 159 , 5–22 loading into the buffer unit , 5–22 , 10–2 transmitting resetting timeout information in el_softc data , 3–9 structure , 13–2 rearming the next VBA_Option entry timer , 14–1 sysconfigtab file fragment , 10–2 clearing transmit , 13–10 counting interrupts , 10–2 counting timeouts...

Table of Contents