skip book previous and next navigation links
go up to top of book: HP OpenVMS I/O User's Reference ManualHP OpenVMS I/O User's Reference Manual
go to beginning of chapter: Local Area Network (LAN) Device DriversLocal Area Network (LAN) Device Drivers
go to previous page: I/O Status BlockI/O Status Block
go to next page: ReferencesReferences
end of book navigation links

Application Programming Notes 



This sectioncontains information to assist you in writing application programsthat use the LAN device drivers. Promiscuous Mode discusses the additional rules required for applicationprograms that you intend to run in promiscuous mode. Local Area Network Programming Examples describe the Ethernet and802 sample programs.

Promiscuous Mode  

The LAN driversallow only one port per controller to enable promiscuous mode (NMA$C_PCLI_PRM specifiedas NMA$C_STATE_ON). A port running in promiscuous mode usually placesan additional load on the CPU because the LAN device is configuredto deliver all packets on the LAN to the LAN driver.

Rules for Promiscuous Mode Operation detailsadditional rules for ports running in promiscuous mode.

Table 47   Rules for Promiscuous Mode Operation
I/O Function Rule
IO$_SETMODE IO$_SETCHARItis not necessary to specify a unique identifier (a protocol type,SAP, or protocol identifier parameter ID) in the P2 buffer.

Theport cannot be running in shared mode.
IO$_WRITETheuser can only transmit packets in the packet format previously specifiedwith a set mode QIO when the user was started. The unique identifierfor the packet format must be included in the P5 buffer followingthe destination address (see Write ).
IO$_READThe LANdriver completes the promiscuous user's read requests with Ethernet, IEEE802, and 802 extended packets. Because any packet format can beused to complete a read request, the P5 parameter (if specified)must be at least 20 bytes in length (21 bytes for FDDI with RFCturned on).



All Ethernet format packetsare processed as if they have no size field specified after theprotocol type. Therefore, Ethernet packets are always returned with46 to 1500 bytes of data. If the Ethernet packet contains a sizefield, it is returned as part of the user data in the first wordof the P1 buffer.



The promiscuous usershould use the information returned in the P5 buffer to determinethe packet format. If the application program first filled the P5buffer with zeros, the program can determine the format of the packetreceived by scanning the P5 buffer after the read request is completed.



Local Area Network Programming Examples  

The VAX MACRO program LANETH.MAR (LANETH.MAR Local Area Network Programming Example) shows the typical use of QIO functions in driver operationssuch as establishing the protocol type, starting the port, and transmittingand receiving data. The program sends a LOOPBACK packet and waitsfor the packet to be returned.

The HP C programLAN802E.C (LAN802.C Local Area Network Programming Example ) showshow to initialize an 802E port and how to send and receive packetson that port. This program sends a LOOPBACK packet and waits forthe packet to be returned.
Example 3  LANETH.MAR Local Area Network ProgrammingExample  
        .TITLE  LAN SAMPLE TEST PROGRAM        .IDENT  /X02/        .PSECT  RWDATA,WRT,NOEXE,PAGE ; This LAN test program sends a MOP loopback message to the Loopback Assistant; Multicast address and waits for a response.  The program uses the LAN device; EWA0.  To use a different device, change the device name in the program or; define the desired lan device as EWA0.;; To build on VAX or Alpha:;        $ MACRO LANETH;        $ LINK LANETH         .LIBRARY "SYS$LIBRARY:LIB.MLB"         $IODEF                          ; Define I/O functions and modifiers              $NMADEF                         ; Define Network Management parameters        ; Setmode parameter buffer and descriptor.  Since the loopback protocol does; not include a length word following the protocol type, we have to explicitly; turn off padding since the default is on. SETPARM:        .WORD   NMA$C_PCLI_FMT          ; Packet format                   .LONG   NMA$C_LINFM_ETH         ;   Ethernet                    .WORD   NMA$C_PCLI_PTY          ; Protocol type                   .LONG   ^X0090                  ;   Loopback                   .WORD   NMA$C_PCLI_PAD          ; Padding                   .LONG   NMA$C_STATE_OFF         ;   Off            SETPARMLEN = .-SETPARM SETPARMDSC:        .LONG   SETPARMLEN        .ADDRESS SETPARM ; Sensemode parameter buffer and descriptor.  This is  used to get our physical; address to put into the loopback message. SENSEBUF:        .BLKB   512SENSELEN=.-SENSEBUF SENSEDSC:        .LONG   SENSELEN        .ADDRESS SENSEBUF ; P2 transmit data buffer. XMTBUF: .WORD   00                      ; Skip count          .WORD   02                      ; Forward request  FORW:   .BLKB   6                       ; Forward address         .WORD   01                      ; Reply request          .WORD   00XMTBUFLEN = .-XMTBUF                    ; Size of transmit buffer     ; P5 transmit destination address, the Loopback Assistant Multicast Address. XMTP5:  .BYTE   ^XCF,0,0,0,0,0 ; P2 receive data buffer. RCVBUF: .BLKB   512RCVBUFLEN = .-RCVBUF                    ; Size of receive buffer     ; P5 receive header buffer. RCVP5:RCVDA:  .BLKB   6RCVSA:  .BLKB   6RCVPTY: .BLKB   2 ; Messages used to display status of this program. GMSG:   .ASCID  "Successful test"LMSG:   .ASCID  "No response"EMSG:   .ASCID  "Error occurred while running test"DMSG:   .ASCID  "LAN device not found" ; Miscellaneous data. IOSB:   .BLKQ   1                       ; I/O status block DEVCHAN:.BLKL   1                       ; Returned port number LANDSC: .ASCID  'EWA0'                  ; Device to use for test       ;*************************************************************************;; Start of code;;*************************************************************************         .PSECT  CODE,EXE,NOWRT,PAGE        .ENTRY  START,^M
; Assign a port to the LAN device.         $ASSIGN_S DEVNAM=LANDSC,CHAN=DEVCHAN        BLBS    R0,10$                  ; Branch if succeeded              MOVAL   DMSG,R9                 ; Get address of error message               BRW     EXIT                    ; Print message and exit     ; Set up the port's characteristics. 10$:    MOVAL   EMSG,R9                 ; Assume error message address               $QIOW_S FUNC=#$_SETMODE!IO$M_CTRL!IO$M_STARTUP>,-                CHAN=DEVCHAN,IOSB=IOSB,-                P2=#SETPARMDSC        BLBC    R0,20$                  ; Branch if failed              MOVZWL  IOSB,R0                 ; Get status from IOSB               BLBS    R0,30$                  ; Branch if succeeded      20$:    BRW     EXIT                    ; Print message and exit     ; Issue the SENSEMODE QIO to get our physical address for the loopback; message. 30$:    $QIOW_S FUNC=#$_SENSEMODE!IO$M_CTRL>,-                CHAN=DEVCHAN,IOSB=IOSB,-                P2=#SENSEDSC        BLBC    R0,20$                  ; Branch if failed              MOVZWL  IOSB,R0                 ; Get status from IOSB               BLBC    R0,20$                  ; Branch if failed       ; Locate the PHA parameter in the SENSEMODE buffer and copy it into the; LOOPBACK transmit message.  The PHA parameter is a string parameter.         MOVAB   SENSEBUF,R0             ; Start at beginning of buffer   40$:    BBS     #^XC,(R0),50$           ; Branch if a string parameter             ADDL    #6,R0                   ; Skip over longword parameter             BRB     40$                     ; Check next parameter   50$:    BICW3   #^XF000,(R0)+,R1        ; Get type field less flag bits        CMPW    R1,#NMA$C_PCLI_PHA      ; Is this the PHA parameter?          BEQL    60$                     ; Branch if so           ADDW    (R0)+,R0                ; Skip over string parameter        BRW     40$                     ; Check next parameter   60$:    MOVL    2(R0),FORW              ; Copy our address to the loopback          MOVW    6(R0),FORW+4            ; packet we are about to transmit     ; Transmit the loopback message.         $QIOW_S FUNC=#IO$_WRITEVBLK,CHAN=DEVCHAN,IOSB=IOSB,-                P1=XMTBUF,P2=#XMTBUFLEN,P5=#XMTP5        BLBC    R0,70$                  ; Branch if failed              MOVZWL  IOSB,R0                 ; Get status from IOSB               BLBS    R0,80$                  ; Branch if succeeded      70$:    BRW     EXIT                    ; Print message and exit     ; Look for a response.  We use the NOW function modifier on the READ so that; we don't hang here waiting forever if there is no response.  If there is no; response in 1000 receive attempts, we declare no response status. 80$:    MOVL    #1000,R2                ; Check 1000 times90$:    $QIOW_S FUNC=#IO$_READVBLK!IO$M_NOW,CHAN=DEVCHAN,IOSB=IOSB,-                P1=RCVBUF,P2=#RCVBUFLEN,P5=#RCVP5        BLBC    R0,EXIT                 ; Branch if failed               MOVZWL  IOSB,R0                 ; Get status from IOSB               BLBS    R0,100$                 ; Branch if succeeded               CMPL    R0,#SS$_ENDOFFILE       ; Was there just no message available?         BNEQ    EXIT                    ; Branch if failed            SOBGTR  R2,90$                  ; Try again       ; No response in 1000 attempts.         MOVAL   LMSG,R9                 ; Get address of lost message               BRW     EXIT                    ; Print message and exit     ; Received a message. 100$:   MOVAL   GMSG,R9                 ; Get address of success message        ; The test is done.  Call LIB$PUT_OUTPUT to display the test status. EXIT:   PUSHL   R9                      ; P1 = Address of message to print          CALLS   #1,G^LIB$PUT_OUTPUT     ; Print the message           $EXIT_S                         ; Exit                .END    START


Example 4  LAN802.C Local Area Network Programming Example  
    /************************************************************* * LAN Sample Test Program * * This LAN test program sends a MOP loopback message to the Loopback Assistant * Multicast address and waits for a response.  The program uses the LAN device * EWA0.  To use a different device, change the device name in the program or * define the desired lan device as EWA0. * * To build on VAX:                 To build on Alpha: *    $ CC LAN802E                     $ CC LAN802E + SYS$LIBRARY:SYS$LIB_C.TLB/LIB *    $ LINK LAN802E,SYS$INPUT:/OPT    $ LINK LAN802E *      SYS$SHARE:VAXCRTL.EXE/SHARE *************************************************************/ #include <ctype>/* Character type classification macros/routines */#include <descrip>/* For VMS descriptor manipulation */#include <iodef>/* I/O function code definitions */#include <ssdef>/* System service return status code definitions */#include <starlet>/* System library routine prototypes */#include <stdio>/* ANSI C Standard Input/Output */#include <stdlib>/* General utilities */#include <string>/* String handling */#include <stsdef>/* VMS status code definitions */ #define NMA$C_PCLI_FMT 2770#define NMA$C_PCLI_PID 2774#define NMA$C_PCLI_PHA 2820#define NMA$C_LINFM_802E 0#define $SUCCESS(status) ( ((status) & STS$M_SUCCESS) == SS$_NORMAL)#define $FAIL(status) ( ((status) & STS$M_SUCCESS) != SS$_NORMAL) #pragma nomember_alignment struct parm_802e{    short pcli_fmt;                     /* Format - 802E */    int fmt_value;    short pcli_pid;                     /* Protocol ID - 08-00-2B-90-00 */    short pid_length;    char pid_value[5];} setparm_802e = {NMA$C_PCLI_FMT, NMA$C_LINFM_802E,NMA$C_PCLI_PID, 5, 8,0,0x2b,0x90,0}; struct setparmdsc{    int parm_len;    void *parm_buffer;}; struct setparmdsc setparmdsc_loop = {sizeof(setparm_802e),_802e}; struct p5_param                         /* P5 Receive header buffer */{    unsigned char da[6];    unsigned char sa[6];    char misc[20];}; struct iosb                             /* IOSB structure */{    short w_err;                        /* Completion Status */    short w_xfer_size;                  /* Transfer Size */    short w_addl;                       /* Additional status */    short w_misc;                       /* Miscellaneous */}; struct ascid                            /* Device descriptor for assign */{    short w_len;    short w_info;    char *a_string;} devdsc = {4,0,"EWA0"}; struct iosb qio_iosb;                   /* IOSB structure */struct p5_param rcv_param;              /* Receive header structure */struct p5_param xmt_param={             /* Transmit header structure */  0xCF,0,0,0,0,0};                      /* Loopback Assistant Multicast Address */char rcv_buffer[512];                   /* Receive buffer */char xmt_buffer[20]={                   /* Transmit buffer */  0,0,                                  /* Skip count */  2,0,                                  /* Forward request */  0,0,0,0,0,0,                          /* Forward address */  1,0,                                  /* Reply request */  0,0}; char sense_buffer[512];                 /* Sensemode buffer */ struct setparmdsc sensedsc_loop = {sizeof(sense_buffer),_buffer}; /* * MAIN */ main(int argc, char *argv[]){    int i, j;                           /* Scratch */    int chan;                           /* Channel assigned */    int status;                         /* Return status */     /*     * Start a channel.     */     status = sys$assign(,,0,0);    if ($FAIL(status) ) exit(status);    status = sys$qiow(0,chan,IO$_SETMODE|IO$M_CTRL|IO$M_STARTUP,_iosb,0,0,0,                      _loop,0,0,0,0);    if ($SUCCESS(status) ) status = qio_iosb.w_err;    if ($FAIL(status) )    {        printf("IOSB addl status = %04X %04X (on startup)\n",qio_iosb.w_addl,qio_iosb.w_misc);        exit(status);    }     /*     * Issue the SENSEMODE QIO to get our physical address for the loopback message.     */     status = sys$qiow(0,chan,IO$_SENSEMODE|IO$M_CTRL,_iosb,0,0,0,                      _loop,0,0,0,0);    if ($SUCCESS(status) ) status = qio_iosb.w_err;    if ($FAIL(status) )    {        printf("IOSB addl status = %04X %04X (on sensemode)\n",                                   qio_iosb.w_addl,qio_iosb.w_misc);        exit(status);    }     /*     * Locate the PHA parameter in the SENSEMODE buffer and copy it into the     * LOOPBACK transmit message.  The PHA parameter is a string parameter.     */     j = 0;    while (j < sizeof(sense_buffer) )    {        i = (sense_buffer[j] + (sense_buffer[j+1]<<8) );        if (0x1000 & i)        {            if ( (i & 0xFFF) == NMA$C_PCLI_PHA)            {                memcpy(_buffer[4],_buffer[j+4],6);                break;            }            j += (sense_buffer[j+2] + (sense_buffer[j+3]<<8) ) + 4;        }        else        {            j += 6;                     /* Skip over longword parameter */        }    }     /*     * Transmit the loopback message.     */     status = sys$qiow(0,chan,IO$_WRITEVBLK,_iosb,0,0,_buffer[0],             sizeof(xmt_buffer),0,0,_param,0);    if ($SUCCESS(status) ) status = qio_iosb.w_err;    if ($FAIL(status) )    {        printf("IOSB addl status = %04X %04X (on transmit)\n",                                   qio_iosb.w_addl,qio_iosb.w_misc);        exit(status);    }     /*     * Look for a response.  We use the NOW function modifier on the READ so that     * we don't hang here waiting forever if there is no response.  If there is no     * response in 1000 receive attempts, we declare no response status.     */     for (i=0;i<1000;i++)    {        status = sys$qio(0,chan,IO$_READVBLK|IO$M_NOW,_iosb,0,0,_buffer[0],                 sizeof(rcv_buffer),0,0,_param,0);        if ($SUCCESS(status) ) status = qio_iosb.w_err;        if ($SUCCESS(status) ) break;    }    if ($SUCCESS(status) )        printf("Successful test\n");    else        printf("No response\n"); }



go to previous page: I/O Status BlockI/O Status Block
go to next page: ReferencesReferences