Guide to the dec text processing utility (152 pages)
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...
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 .
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 •...
• 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.
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...
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.
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.
#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.
• 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.
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.
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.
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.
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.
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...
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.
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.
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.
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...
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.
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 {...
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.
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.
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;...
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: •...
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.
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.
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.
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.
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.
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.
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.
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;...
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.
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.
• 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.
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);...
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.
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: •...
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.
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 •...
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);...
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);...
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.
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: •...
• 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[] = {...
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.
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;...
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.
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);...
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) &&...
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.
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.
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.
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.
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;...
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.
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.
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.
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.
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.
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.
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.
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.
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:...
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: •...
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.
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);...
• 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) •...
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.
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.
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.
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).
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.
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).
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.
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.
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;...
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.
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.
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);...
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).
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;...
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.
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.
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.
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.
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: •...
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.
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.
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.
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;...
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.
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.
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...
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:...
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:...
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.
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) •...
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;...
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 &...
• 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));...
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.
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.
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.
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).
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.
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.
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;...
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.
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...
Need help?
Do you have a question about the Tru64 UNIX and is the answer not in the manual?
Questions and answers