diff --git a/bochs/patches/patch.ethlinux-splite b/bochs/patches/patch.ethlinux-splite new file mode 100644 index 000000000..6cefaa463 --- /dev/null +++ b/bochs/patches/patch.ethlinux-splite @@ -0,0 +1,317 @@ +---------------------------------------------------------------------- +Patch name: patch.ethlinux-splite +Author: splite@purdue.edu +Date: 21 June 2001 +RCS Id: $Id: patch.ethlinux-splite,v 1.1 2001-06-25 21:49:19 bdenney Exp $ + +Detailed description: + implementation of ethernet packet mover using Linux Socket Filter + +Patch was created with: + diff -u +Apply patch to what version: + current cvs (tested june 25, 2001) +Instructions: + To patch, go to main bochs directory. + Type "patch -p0 < THIS_PATCH_FILE". +---------------------------------------------------------------------- + +--- configure.in.orig Thu Jun 21 10:05:22 2001 ++++ configure.in Mon Jun 25 12:32:13 2001 +@@ -311,6 +311,7 @@ + AC_DEFINE(BX_NE2K_SUPPORT, 1) + NE2K_OBJS='ne2k.o eth.o eth_null.o' + AC_CHECK_HEADER(net/bpf.h, NE2K_OBJS="$NE2K_OBJS eth_fbsd.o") ++ AC_CHECK_HEADER(netpacket/packet.h, NE2K_OBJS="$NE2K_OBJS eth_linux.o") + else + AC_MSG_RESULT(no) + AC_DEFINE(BX_NE2K_SUPPORT, 0) +--- iodev/eth.h.orig Wed Jun 13 17:27:52 2001 ++++ iodev/eth.h Mon Jun 25 12:33:18 2001 +@@ -75,6 +75,6 @@ + #if defined(__FreeBSD__) || defined(__OpenBSD__) + #define ETH_FBSD 1 + #endif +-#if (0 && defined(linux)) ++#if defined(linux) + #define ETH_LINUX 1 + #endif +--- iodev/eth_linux.cc.orig Mon Jun 25 12:33:52 2001 ++++ iodev/eth_linux.cc Mon Jun 25 12:56:32 2001 +@@ -0,0 +1,276 @@ ++// Copyright (C) 2001 MandrakeSoft S.A. ++// ++// MandrakeSoft S.A. ++// 43, rue d'Aboukir ++// 75002 Paris - France ++// http://www.linux-mandrake.com/ ++// http://www.mandrakesoft.com/ ++// ++// This library is free software; you can redistribute it and/or ++// modify it under the terms of the GNU Lesser General Public ++// License as published by the Free Software Foundation; either ++// version 2 of the License, or (at your option) any later version. ++// ++// This library is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++// Lesser General Public License for more details. ++// ++// You should have received a copy of the GNU Lesser General Public ++// License along with this library; if not, write to the Free Software ++// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ ++// Peter Grehan (grehan@iprg.nokia.com) coded all of this ++// NE2000/ether stuff. ++ ++// eth_linux.cc - A Linux socket filter adaptation of the FreeBSD BPF driver ++// 21 June 2001 ++// ++// Problems and limitations: ++// - packets cannot be sent from BOCHS to the host ++// - Linux kernel sometimes gets network watchdog timeouts under emulation ++// - author doesn't know C++ ++// ++// The config line in .bochsrc should look something like: ++// ++// ne2k: ioaddr=0x280, irq=10, mac=00:a:b:c:1:2, ethmod=linux, ethdev=eth0 ++// ++ ++#include "bochs.h" ++#ifdef ETH_LINUX ++#define LOG_THIS this-> ++ ++extern "C" { ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++}; ++ ++#define BX_PACKET_POLL 1000 // Poll for a frame every 1000 usecs ++ ++#define BX_PACKET_BUFSIZ 2048 // Enough for an ether frame ++ ++// template filter for a unicast mac address and all ++// multicast/broadcast frames ++static const struct sock_filter macfilter[] = { ++ BPF_STMT(BPF_LD|BPF_W|BPF_ABS, 2), ++ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0xaaaaaaaa, 0, 2), ++ BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 0), ++ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x0000aaaa, 2, 0), ++ BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 0), ++ BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x01, 0, 1), ++ BPF_STMT(BPF_RET, 1514), ++ BPF_STMT(BPF_RET, 0), ++}; ++#define BX_LSF_ICNT 8 // number of lsf instructions in macfilter ++ ++#if 0 ++// template filter for all frames ++static const struct sock_filter promiscfilter[] = { ++ BPF_STMT(BPF_RET, 1514) ++}; ++#endif ++ ++// ++// Define the class. This is private to this module ++// ++class bx_linux_pktmover_c : public eth_pktmover_c { ++public: ++ bx_linux_pktmover_c(const char *netif, ++ const char *macaddr, ++ eth_rx_handler_t rxh, ++ void *rxarg); ++ void sendpkt(void *buf, unsigned io_len); ++ ++private: ++ unsigned char *linux_macaddr[6]; ++ int fd; ++ int ifindex; ++ static void rx_timer_handler(void *); ++ void rx_timer(void); ++ int rx_timer_index; ++ struct sock_filter filter[BX_LSF_ICNT]; ++}; ++ ++ ++// ++// Define the static class that registers the derived pktmover class, ++// and allocates one on request. ++// ++class bx_linux_locator_c : public eth_locator_c { ++public: ++ bx_linux_locator_c(void) : eth_locator_c("linux") {} ++protected: ++ eth_pktmover_c *allocate(const char *netif, ++ const char *macaddr, ++ eth_rx_handler_t rxh, ++ void *rxarg) { ++ return (new bx_linux_pktmover_c(netif, macaddr, rxh, rxarg)); ++ } ++} bx_linux_match; ++ ++ ++// ++// Define the methods for the bx_linux_pktmover derived class ++// ++ ++// the constructor ++// ++bx_linux_pktmover_c::bx_linux_pktmover_c(const char *netif, ++ const char *macaddr, ++ eth_rx_handler_t rxh, ++ void *rxarg) ++{ ++ struct sockaddr_ll sll; ++ struct packet_mreq mr; ++ struct ifreq ifr; ++ struct sock_fprog fp; ++ ++ memcpy(linux_macaddr, macaddr, 6); ++ ++ // Open packet socket ++ // ++ if ((this->fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) { ++ if (errno == EACCES) ++ BX_INFO(("eth_linux: must be root or have CAP_NET_RAW capability to open socket\n")); ++ else ++ BX_INFO(("eth_linux: could not open socket\n")); ++ this->fd = -1; ++ return; ++ } ++ ++ // Translate interface name to index ++ // ++ memset(&ifr, 0, sizeof(ifr)); ++ strcpy(ifr.ifr_name, netif); ++ if (ioctl(this->fd, SIOCGIFINDEX, &ifr) == -1) { ++ BX_INFO(("eth_linux: could not get index for interface %s\n", netif)); ++ close(fd); ++ this->fd = -1; ++ return; ++ } ++ this->ifindex = ifr.ifr_ifindex; ++ ++ ++ // Bind to given interface ++ // ++ memset(&sll, 0, sizeof(sll)); ++ sll.sll_family = AF_PACKET; ++ sll.sll_ifindex = this->ifindex; ++ if (bind(fd, (struct sockaddr *)&sll, (socklen_t)sizeof(sll)) == -1) { ++ BX_INFO(("eth_linux: could not bind to interface %s\n", netif)); ++ close(fd); ++ this->fd = -1; ++ return; ++ } ++ ++ // Put the device into promisc mode. ++ // ++ memset(&mr, 0, sizeof(mr)); ++ mr.mr_ifindex = this->ifindex; ++ mr.mr_type = PACKET_MR_PROMISC; ++ if (setsockopt(this->fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, (void *)&mr, (socklen_t)sizeof(mr)) == -1) { ++ BX_INFO(("eth_linux: could not enable promisc mode: %s\n", strerror(errno))); ++ close(this->fd); ++ this->fd = -1; ++ return; ++ } ++ ++ // Set up non-blocking i/o ++ if (fcntl(this->fd, F_SETFL, O_NONBLOCK) == -1) { ++ BX_INFO(("eth_linux: could not set non-blocking i/o on socket\n")); ++ close(this->fd); ++ this->fd = -1; ++ return; ++ } ++ ++ // Install a filter ++#ifdef notdef ++ memcpy(&this->filter, promiscfilter, sizeof(promiscfilter)); ++ fp.len = 1; ++#endif ++ memcpy(&this->filter, macfilter, sizeof(macfilter)); ++ this->filter[1].k = (macaddr[2] & 0xff) << 24 | (macaddr[3] & 0xff) << 16 | ++ (macaddr[4] & 0xff) << 8 | (macaddr[5] & 0xff); ++ this->filter[3].k = (macaddr[0] & 0xff) << 8 | (macaddr[1] & 0xff); ++ fp.len = BX_LSF_ICNT; ++ fp.filter = this->filter; ++BX_INFO(("eth_linux: fp.len=%d fp.filter=%lx", fp.len, fp.filter)); ++ if (setsockopt(this->fd, SOL_SOCKET, SO_ATTACH_FILTER, &fp, sizeof(fp)) < 0) { ++ BX_INFO(("eth_linux: could not set socket filter: %s", strerror(errno))); ++ close(this->fd); ++ this->fd = -1; ++ return; ++ } ++ ++ // Start the rx poll ++ this->rx_timer_index = ++ bx_pc_system.register_timer(this, this->rx_timer_handler, BX_PACKET_POLL, ++ 1, 1); // continuous, active ++ ++ this->rxh = rxh; ++ this->rxarg = rxarg; ++ BX_INFO(("eth_linux: enabled NE2K emulation on interface %s\n", netif)); ++} ++ ++// the output routine - called with pre-formatted ethernet frame. ++void ++bx_linux_pktmover_c::sendpkt(void *buf, unsigned io_len) ++{ ++ int status; ++ ++ if (this->fd != -1) ++ status = write(this->fd, buf, io_len); ++ if (status == -1) ++ BX_INFO(("eth_linux: write failed: %s", strerror(errno))); ++} ++ ++// The receive poll process ++void ++bx_linux_pktmover_c::rx_timer_handler(void *this_ptr) ++{ ++ bx_linux_pktmover_c *class_ptr = (bx_linux_pktmover_c *) this_ptr; ++ ++ class_ptr->rx_timer(); ++} ++ ++void ++bx_linux_pktmover_c::rx_timer(void) ++{ ++ int nbytes = 0; ++ Bit8u rxbuf[BX_PACKET_BUFSIZ]; ++ struct sockaddr_ll sll; ++ socklen_t fromlen; ++ static unsigned char bcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; ++ ++ if (this->fd == -1) ++ return; ++ ++ fromlen = sizeof(sll); ++ nbytes = recvfrom(this->fd, rxbuf, sizeof(rxbuf), 0, (struct sockaddr *)&sll, &fromlen); ++ ++ if (nbytes == -1) { ++ if (errno != EAGAIN) ++ BX_INFO(("eth_linux: error receiving packet: %s\n", strerror(errno))); ++ return; ++ } ++ ++ // this should be done with LSF someday ++ // filter out packets sourced by us ++ if (memcmp(sll.sll_addr, this->linux_macaddr, 6) == 0) ++ return; ++ // let through broadcast, multicast, and our mac address ++// if ((memcmp(rxbuf, bcast_addr, 6) == 0) || (memcmp(rxbuf, this->linux_macaddr, 6) == 0) || rxbuf[0] & 0x01) { ++ BX_DEBUG(("eth_linux: got packet: %d bytes, dst=%x:%x:%x:%x:%x:%x, src=%x:%x:%x:%x:%x:%x\n", nbytes, rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3], rxbuf[4], rxbuf[5], rxbuf[6], rxbuf[7], rxbuf[8], rxbuf[9], rxbuf[10], rxbuf[11])); ++ (*rxh)(rxarg, rxbuf, nbytes); ++// } ++} ++#endif diff --git a/bochs/patches/patch.ne2k-splite-2 b/bochs/patches/patch.ne2k-splite-2 new file mode 100644 index 000000000..e4c886a0a --- /dev/null +++ b/bochs/patches/patch.ne2k-splite-2 @@ -0,0 +1,114 @@ +---------------------------------------------------------------------- +Patch name: patch.ne2k-splite-2 +Author: splite@purdue.edu +Date: Mon, 25 Jun 2001 13:23:22 -0500 +RCS Id: $Id: patch.ne2k-splite-2,v 1.1 2001-06-25 21:49:19 bdenney Exp $ + +Detailed description: + After much grovelling through the 8390 docs, I think this is the correct + answer to the odd-length packet problem I was having with the ne2k driver + under Linux. + + According to the datasheet, the 8390 always accesses its buffer memory in + word-size chunks if the WTS bit of the DCR is set. So it will always send + a word to the host bus interface if WTS==1. It's up to the host bus + interface to deliver the the number of requested bytes to the host. So + disallowing a byte read when the WTS bit is set is wrong (IMO) as the bus + interface may allow it, as the NE2000 appears to. + + The patch to ne2k.h bumps the receive buffer memory size to 32K. This fixes + the "out-of-bounds chipmem read" errors I was getting. + + Can someone with an NE2K datasheet verify these changes? They jibe with the + Linux ne.c driver, anyway. + +Patch was created with: + diff -u +Apply patch to what version: + cvs current (as of june 25, 2001) +Instructions: + To patch, go to main bochs directory. + Type "patch -p0 < THIS_PATCH_FILE". +---------------------------------------------------------------------- + +From bochs@sigint.cs.purdue.edu Mon Jun 25 17:23:33 2001 +Date: Mon, 25 Jun 2001 13:23:22 -0500 +From: bochs@sigint.cs.purdue.edu +To: bochs-developers@lists.sourceforge.net +Subject: [Bochs-developers] ne2k patch for hosted Linux support + +After much grovelling through the 8390 docs, I think this is the correct +answer to the odd-length packet problem I was having with the ne2k driver +under Linux. + +According to the datasheet, the 8390 always accesses its buffer memory in +word-size chunks if the WTS bit of the DCR is set. So it will always send +a word to the host bus interface if WTS==1. It's up to the host bus +interface to deliver the the number of requested bytes to the host. So +disallowing a byte read when the WTS bit is set is wrong (IMO) as the bus +interface may allow it, as the NE2000 appears to. + +The patch to ne2k.h bumps the receive buffer memory size to 32K. This fixes +the "out-of-bounds chipmem read" errors I was getting. + +Can someone with an NE2K datasheet verify these changes? They jibe with the +Linux ne.c driver, anyway. + +--- iodev/ne2k.h.orig Tue May 22 19:46:47 2001 ++++ iodev/ne2k.h Mon Jun 25 12:30:03 2001 +@@ -38,7 +38,7 @@ + # define BX_NE2K_THIS this-> + #endif + +-#define BX_NE2K_MEMSIZ (16*1024) ++#define BX_NE2K_MEMSIZ (32*1024) + #define BX_NE2K_MEMSTART (16*1024) + #define BX_NE2K_MEMEND (BX_NE2K_MEMSTART + BX_NE2K_MEMSIZ) + +--- iodev/ne2k.cc.orig Sat Jun 23 19:47:17 2001 ++++ iodev/ne2k.cc Mon Jun 25 12:27:49 2001 +@@ -259,22 +259,26 @@ + + switch (offset) { + case 0x0: // Data register +- // +- // The device must have been set up to perform DMA in +- // the same size as is being requested (the WTS bit +- // in the DCR), a read remote-DMA command must have +- // been issued, and the source-address and length +- // registers must have been initialised. + // +- if (io_len != (1 + BX_NE2K_THIS s.DCR.wdsize)) +- BX_PANIC(("dma read, wrong size %d", io_len)); +- +- if (BX_NE2K_THIS s.remote_bytes == 0) +- BX_PANIC(("ne2K: dma read, byte count 0")); ++ // A read remote-DMA command must have been issued, ++ // and the source-address and length registers must ++ // have been initialised. ++ // ++ if (io_len > BX_NE2K_THIS s.remote_bytes) ++ BX_PANIC(("ne2K: dma read underrun")); + + retval = chipmem_read(BX_NE2K_THIS s.remote_dma, io_len); +- BX_NE2K_THIS s.remote_dma += io_len; +- BX_NE2K_THIS s.remote_bytes -= io_len; ++ // ++ // The 8390 bumps the address and decreases the byte count ++ // by the selected word size after every access, not by ++ // the amount of data requested by the host (io_len). ++ // ++ BX_NE2K_THIS s.remote_dma += (BX_NE2K_THIS s.DCR.wdsize + 1); ++ // keep s.remote_bytes from underflowing ++ if (BX_NE2K_THIS s.remote_bytes > 1) ++ BX_NE2K_THIS s.remote_bytes -= (BX_NE2K_THIS s.DCR.wdsize + 1); ++ else ++ BX_NE2K_THIS s.remote_bytes = 0; + break; + + case 0xf: // Reset register + +_______________________________________________ +bochs-developers mailing list +bochs-developers@lists.sourceforge.net +http://lists.sourceforge.net/lists/listinfo/bochs-developers