1
0
mirror of https://github.com/simh/simh.git synced 2026-03-14 22:19:02 +00:00
Files
simh.simh/Pcap-VMS/pcapvcm/pcap_client.c
Mark Pizzolato af6338d927 From Matt Burke
- Fixes a bug with DEC C v6.5-001 for OpenVMS/Alpha
  - Adds support for OpenVMS/Integrity
2011-09-23 11:28:00 -07:00

437 lines
11 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma module pcap_client "X-2"
/*
*****************************************************************************
*
* Copyright © 1996 Digital Equipment Corporation.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by Digital Equipment Corporation. The name of the
* Corporation may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
*****************************************************************************
*
* Important Note:
*
* This coding example uses privileged OpenVMS interfaces.
* OpenVMS does not guarantee that these interfaces will
* be supported indefinitely, and may change these interfaces
* without prior notice.
*
*****************************************************************************
*/
/* Define data structures and constants */
#include <descrip.h> /* Descriptors */
#include <ldrimgdef.h> /* Loaded image data block */
#include <lnmdef.h> /* Logical names */
#include <pdscdef.h> /* Linkage pairs */
#include <starlet.h> /* System service proto-types */
#include <ssdef.h> /* System service status codes */
#include <stsdef.h>
#include <stdio.h> /* CRTL I/O */
#include <string.h> /* CTRL strings */
#include <ldrdef.h>
#include <nmadef.h>
#include "pcapvcm.h"
typedef struct lkpdef LKP;
#pragma member_alignment __save
#pragma nomember_alignment
typedef struct _eth_header {
unsigned char da[6];
unsigned char sa[6];
unsigned char proto[2];
unsigned char data[2048];
} ETH_HEADER;
#pragma member_alignment __restore
typedef struct _ref_handle /* Dynamic loader reference handle */
{
void *base_addr;
LDRIMG *ldrimg_ptr;
int seq_num;
} REF_HANDLE;
/* Define special proto-types for the loader routines we need */
extern int ldr$load_image (struct dsc$descriptor_s *execlet_name, int flags,
REF_HANDLE *reference_handle);
extern int ldr$ref_info (struct dsc$descriptor_s *execlet_name,
REF_HANDLE *reference_handle);
extern int ldr$unload_image (struct dsc$descriptor_s *execlet_name,
REF_HANDLE *reference_handle);
/* Define proto-types for Kernel routines */
int load_execlet();
int unload_execlet();
/* Global data */
PCAPVCM *pcapvcm;
REF_HANDLE reference_handle; /* Dynamic loader ref handle */
void *rtnptr = 0;
$DESCRIPTOR(execlet_name, "PCAPVCM");
int is_loaded = 0;
#pragma __required_pointer_size __save
#pragma __required_pointer_size __long
int get_packet(VCRPLANDEF *vcrp, ETH_HEADER **hdrp)
{
VCRPDEF *vcrpbase;
uint64 boff;
int len;
vcrpbase = (VCRPDEF *) vcrp;
boff = vcrpbase->vcrp$l_boff;
len = vcrpbase->vcrp$l_bcnt;
*hdrp = (ETH_HEADER *) (((char *) vcrp) + boff);
return len;
}
int parse_vcrp(VCRPLANDEF *vcrp)
{
int status;
VCRPDEF *vcrpbase;
ETH_HEADER *hdr;
uint64 boff;
uint64 len;
uint64 haddr;
uint64 rstat;
uint32 size;
char *data;
uint64 format;
uint64 dest;
vcrpbase = (VCRPDEF *) vcrp;
size = vcrpbase->vcrp$w_size;
rstat = vcrpbase->vcrp$q_request_status;
haddr = vcrp->vcrp$a_lan_r_header;
boff = vcrpbase->vcrp$l_boff;
format = vcrp->vcrp$l_lan_pkformat;
dest = vcrp->vcrp$q_lan_t_dest;
len = vcrpbase->vcrp$l_bcnt;
hdr = (ETH_HEADER *) (((char *) vcrp) + boff);
// data = vcrp->vcrp$b_lan_filler4;
return status;
}
int build_vcrp(VCRPLANDEF *vcrp, int hdrlen, int len, char *packet)
{
int status;
VCRPDEF *base;
char *packptr;
char *rethdr;
int pdulen;
base = (VCRPDEF *) vcrp;
// status = init_transmit_vcrp(vcrp);
packptr = (char *) vcrp + VCRP$T_LAN_DATA + LAN$C_MAX_HDR_SIZE;
pdulen = (len-hdrlen) + 16;
base->vcrp$l_boff = (char *) packptr - (char *) base;
base->vcrp$l_bcnt = pdulen;
memcpy(&vcrp->vcrp$q_lan_t_dest, packet, 6);
packptr = (char *) packptr + 16;
memcpy(packptr, (packet+14), len-14);
return status;
}
#pragma __required_pointer_size __restore
/*
**++
** Main - Get us started
**
** Functional description:
**
** This routine exists to simply get us into Kernel mode to load the
** execlet.
**
** Calling convention:
**
** main()
**
** Input parameters:
**
** None
**
** Output parameters:
**
** None
**
** Return value:
**
** Various SS$_xxxx
**
** Environment:
**
** User mode.
**
**--
*/
int main()
{
int status;
uint64 arglist[10];
uint64 lstat;
int p2len;
int packlen;
int hdrlen;
ETH_HEADER *packet;
char sa[6] = {0xaa,0x00,0x2b,0x99,0x99,0x99};
char pty[2] = {0x08,0x00};
VCRPLANDEF *vcrp;
char vcrpbuff[4096];
#pragma __required_pointer_size __save
#pragma __required_pointer_size __long
char vcrpbuf[4096];
VCRPLANDEF *vcrpptr;
VCMCTX *vcmctx;
char *rawpackptr;
char devnam[128];
char p2buf[1024];
char hdr[128];
char *p2ptr;
char *tmpptr;
int q_stat[4];
#pragma __required_pointer_size __restore
/* Call kernel mode routine to load execlet and read symbol vector */
arglist[0] = 0;
status = sys$cmkrnl(load_execlet,arglist);
if (status & SS$_NORMAL)
{
printf("Execlet loaded\n");
}
else
{
printf("Status from load_execlet = %x.\n",status);
}
// Allocate a port
arglist[0] = 1;
arglist[1] = &vcmctx;
status = sys$cmkrnl_64(pcapvcm->alloc_port, arglist);
// Now get the devices
tmpptr = &devnam[0];
arglist[0] = 2;
arglist[1] = vcmctx;
arglist[2] = tmpptr;
status = sys$cmkrnl_64(pcapvcm->get_device, arglist);
// Create a port with this device
arglist[0] = 2;
arglist[1] = vcmctx;
arglist[2] = tmpptr;
status = sys$cmkrnl_64(pcapvcm->create_port, arglist);
// Populate P2 buffer
p2ptr = &p2buf[0];
memset(p2ptr, 0, 1024);
ADD_INT_VAL(p2ptr, NMA$C_PCLI_FMT, NMA$C_LINFM_ETH);
ADD_INT_VAL(p2ptr, NMA$C_PCLI_PTY, *(int *)pty);
ADD_INT_VAL(p2ptr, NMA$C_PCLI_PAD, NMA$C_STATE_OFF);
ADD_INT_VAL(p2ptr, NMA$C_PCLI_PRM, NMA$C_STATE_ON);
ADD_INT_VAL(p2ptr, NMA$C_PCLI_CCA, NMA$C_STATE_ON);
p2len = p2ptr - &p2buf[0];
arglist[0] = 3;
arglist[1] = vcmctx;
arglist[2] = p2len;
arglist[3] = &p2buf[0];
status = sys$cmkrnl_64(pcapvcm->enable_port, arglist);
if (!$VMS_STATUS_SUCCESS(status)) {
arglist[0] = 2;
arglist[1] = vcmctx;
arglist[2] = q_stat;
status = sys$cmkrnl_64(pcapvcm->get_mgm_error, arglist);
} else {
arglist[0] = 1;
arglist[1] = vcmctx;
// status = sys$cmkrnl_64(pcapvcm->disable_port, arglist);
}
// Read a packet
vcrpptr = &vcrpbuf[0];
memset(vcrpptr,0, 4096);
arglist[0] = 3;
arglist[1] = vcmctx;
arglist[2] = 4096;
arglist[3] = vcrpptr;
status = sys$cmkrnl_64(pcapvcm->read_packet, arglist);
status = parse_vcrp(vcrpptr);
packlen = get_packet(vcrpptr, &packet);
rawpackptr = &packet->da[0];
// Build us a header
arglist[0] = 3;
arglist[1] = vcmctx;
arglist[2] = 128;
arglist[3] = &hdr[0];
hdrlen = sys$cmkrnl_64(pcapvcm->build_header, arglist);
// Put in a SA in packet
memcpy(&packet->sa[0], sa, 6);
vcrp = &vcrpbuff[0];
status = build_vcrp(vcrp, 14, packlen, rawpackptr);
arglist[0] = 4;
arglist[1] = vcmctx;
arglist[2] = 14;
arglist[3] = packlen;
arglist[4] = rawpackptr;
status = sys$cmkrnl_64(pcapvcm->send_packet, arglist);
arglist[0] = 1;
arglist[1] = vcmctx;
status = sys$cmkrnl_64(pcapvcm->disable_port, arglist);
arglist[0] = 4;
arglist[1] = vcmctx;
arglist[2] = 14;
arglist[3] = packlen;
arglist[4] = packet;
status = sys$cmkrnl_64(pcapvcm->send_packet, arglist);
// Read another packet
arglist[0] = 3;
arglist[1] = vcmctx;
arglist[2] = 4098;
arglist[3] = vcrpptr;
status = sys$cmkrnl_64(pcapvcm->read_packet, arglist);
status = parse_vcrp(vcrpptr);
arglist[0] = 1;
arglist[1] = vcmctx;
status = sys$cmkrnl_64(pcapvcm->delete_port, arglist);
arglist[0] = 1;
arglist[1] = vcmctx;
status = sys$cmkrnl_64(pcapvcm->free_port, arglist);
// arglist[0] = 0;
// status = sys$cmkrnl(unload_execlet, arglist);
return (status);
}
/*
**++
** load_execlet - Load the specified execlet
**
** Functional description:
**
** This routine is called in Kernel Mode and will load the specified
** execlet.
**
** Calling convention:
**
** load_execlet()
**
** Input parameters:
**
** None
**
** Output parameters:
**
** None
**
** Return value:
**
** Various SS$_xxx
**
** Environment:
**
** Kernel mode
**
**--
*/
int load_execlet ()
{
int status;
LKP *symvec; /* Pointer to symbol vector */
int (*getContext)(PCAPVCM **);
/* Try referencing execlet first, in case it is already loaded */
status = LDR$REF_INFO (&execlet_name, &reference_handle);
/* If error, must not be loaded yet */
if (status != SS$_NORMAL)
{
/* Load execlet */
status = LDR$LOAD_IMAGE (&execlet_name, LDR$M_UNL, &reference_handle);
}
if ($VMS_STATUS_SUCCESS(status)) {
// Indicate that we've loaded the execlet
is_loaded = 1;
// Get the shared context. We built the execlet so that the address
// of the routine that does this is at home base...
#ifdef __ia64
rtnptr = *(void **)reference_handle.ldrimg_ptr->ldrimg$l_segments[5].ldrisd$p_base;
#else
rtnptr = *(void **)reference_handle.ldrimg_ptr->ldrimg$l_nonpag_w_base;
#endif
if (rtnptr) {
getContext = (int (*)())rtnptr;
status = (*getContext)(&pcapvcm);
}
}
return(status);
}
//
// Unload the execlet
//
int unload_execlet ()
{
int status;
if (is_loaded) {
status = LDR$REF_INFO (&execlet_name, &reference_handle);
if ($VMS_STATUS_SUCCESS(status)) {
status = LDR$UNLOAD_IMAGE(&execlet_name, &reference_handle);
}
is_loaded = 0;
} else {
status = SS$_ACCVIO;
}
return status;
}