📄 etherdrv.c
字号:
/* * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved. * * This software may be freely used, copied, modified, and distributed * provided that the above copyright notice is preserved in all copies of the * software. *//* -*-C-*- * * $Revision: 1.9 $ * $Date: 2000/01/04 15:24:18 $ * * * etherdrv.c - Ethernet Driver for Angel. */#ifdef __hpux# define _POSIX_SOURCE 1# define _HPUX_SOURCE 1# define _XOPEN_SOURCE 1#endif#include <stdio.h>#ifdef __hpux# define uint hide_HPs_uint#endif#ifdef STDC_HEADERS# include <unistd.h># ifdef __hpux# undef uint# endif#endif#include <stdlib.h>#include <string.h>#ifdef __hpux# define uint hide_HPs_uint#endif#include <fcntl.h>#ifdef __hpux# undef uint#endif#include <errno.h>#include <stdarg.h>#include <ctype.h>#include "host.h"#ifdef COMPILING_ON_WINDOWS typedef char * caddr_t;# undef IGNORE# include <winsock.h># include "angeldll.h"#else# ifdef __hpux# define uint hide_HPs_uint# endif# include <sys/types.h># include <sys/socket.h># ifdef __hpux# undef uint# endif# include <netdb.h># include <sys/time.h># include <sys/ioctl.h># ifdef HAVE_SYS_FILIO_H# include <sys/filio.h># endif# include <netinet/in.h># include <arpa/inet.h>#endif#include "hsys.h"#include "devices.h"#include "angel_endian.h"#include "buffers.h"#include "hostchan.h"#include "params.h"#include "logging.h"#include "ethernet.h"#if !defined(COMPILING_ON_WINDOWS) && !defined(STDC_HEADERS)/* These two might not work for windows. */extern int sys_nerr;extern char * sys_errlist[];#endif#ifndef UNUSED# define UNUSED(x) (x = x) /* Silence compiler warnings */#endif/* * forward declarations of static functions */static int EthernetOpen(const char *name, const char *arg);static int EthernetMatch(const char *name, const char *arg);static void EthernetClose(void);static int EthernetRead(DriverCall *dc, bool block);static int EthernetWrite(DriverCall *dc);static int EthernetIoctl(const int opcode, void *args);/* * the device descriptor for Ethernet */DeviceDescr angel_EthernetDevice ={ "Ethernet", EthernetOpen, EthernetMatch, EthernetClose, EthernetRead, EthernetWrite, EthernetIoctl};/* * descriptor for the socket that we talk down */static int sock = -1;/* * address of the remote target */static struct sockaddr_in remote, *ia = &remote;/* * array of dynamic port numbers on target */static unsigned short int ports[2];/* * Function: set_address * Purpose: Try to get an address into an understandable form * * Params: * Input: addr The address to parse * * Output: ia Structure to hold the parsed address * * Returns: * OK: 0 * Error: -1 */static int set_address(const char *const addr, struct sockaddr_in *const ia){ ia->sin_family = AF_INET; /* * Try address as a dotted decimal */ ia->sin_addr.s_addr = inet_addr(addr); /* * If that failed, try it as a hostname */ if (ia->sin_addr.s_addr == (u_int)-1) { struct hostent *hp = gethostbyname(addr); if (hp == NULL) return -1; (void)memcpy((caddr_t)&ia->sin_addr, hp->h_addr, hp->h_length); } return 0;}/* * Function: open_socket * Purpose: Open a non-blocking UDP socket, and bind it to a port * assigned by the system. * * Params: None * * Returns: * OK: socket descriptor * Error: -1 */static int open_socket(void){ int sfd;#if 0 /* see #if 0 just below -VVV- */ int yesplease = 1;#endif struct sockaddr_in local; /* * open the socket */#ifdef COMPILING_ON_WINDOWS if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) return -1;#else if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {# ifdef DEBUG perror("socket");# endif return -1; }#endif /* * 960731 KWelton * * I don't believe that this should be necessary - if we * use select(), then non-blocking I/O is redundant. * Unfortunately, select() appears to be broken (under * Solaris, with a limited amount of time available for * debug), so this code stays in for the time being */#if 0 /* * enable non-blocking I/O */ if (ioctlsocket(sfd, FIONBIO, &yesplease) < 0) {# ifdef DEBUG perror("ioctl(FIONBIO)");# endif closesocket(sfd); return -1; }#endif /* 0/1 */ /* * bind local address to a system-assigned port */ memset((char *)&local, 0, sizeof(local)); local.sin_family = AF_INET; local.sin_port = htons(0); local.sin_addr.s_addr = INADDR_ANY; if (bind(sfd, (struct sockaddr *)&local, sizeof(local)) < 0) {#ifdef DEBUG perror("bind");#endif closesocket(sfd); return -1; } /* * all done */ return sfd;}/* * Function: fetch_ports * Purpose: Request assigned port numbers from remote target * * Params: None * * Returns: Nothing * * Post-conditions: This routine will *always* return something for the * port numbers. If the remote target does not * respond, then it makes something up - this allows * the standard error message (from ardi.c) to be * generated when the target is dead for whatever * reason. */static void fetch_ports(void){ int i; char ctrlpacket[10]; CtrlResponse response; memset (ctrlpacket, 0, 10); strcpy (ctrlpacket, CTRL_MAGIC); memset (response, 0, sizeof(CtrlResponse)); /* * we will try 3 times to elicit a response from the target */ for (i = 0; i < 3; ++i) { struct timeval tv; fd_set fdset; /* * send the magic string to the control * port on the remote target */ ia->sin_port = htons(CTRL_PORT);#ifdef DEBUG printf("CTLR_PORT=0x%04x sin_port=0x%04x\n");#endif if (sendto(sock, ctrlpacket, sizeof(ctrlpacket), 0, (struct sockaddr *)ia, sizeof(*ia)) < 0) {#ifdef DEBUG perror("fetch_ports: sendto");#endif return; } FD_ZERO(&fdset); FD_SET(sock, &fdset); tv.tv_sec = 0; tv.tv_usec = 250000; if (select(sock + 1, &fdset, NULL, NULL, &tv) < 0) {#ifdef DEBUG perror("fetch_ports: select");#endif return; } if (FD_ISSET(sock, &fdset)) { /* * there is something there - read it */ if (recv(sock, (char *)&response, sizeof(response), 0) < 0) {#ifdef COMPILING_ON_WINDOWS unsigned int werrno = WSAGetLastError(); if (werrno == WSAEWOULDBLOCK || werrno == 0)#else if (errno == EWOULDBLOCK)#endif { --i; continue; } else {#ifdef DEBUG perror("fetch_ports: recv");#endif return; } } { /* * XXX * * this is *very* unpleasant - try to match the structure * layout */ unsigned short *sptr = (unsigned short *)(response + RESP_DBUG); if (strcmp(response, ctrlpacket) == 0) { ports[DBUG_INDEX] = htons(*sptr); sptr++; ports[APPL_INDEX] = htons(*sptr); }#ifdef DEBUG printf("fetch_ports: got response, DBUG=%d, APPL=%d\n", ports[DBUG_INDEX], ports[APPL_INDEX]);#endif return; } } } /* * we failed to get a response */#ifdef DEBUG printf("fetch_ports: failed to get a real answer\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -