diff --git a/BasiliskII/src/BeOS/Makefile b/BasiliskII/src/BeOS/Makefile index 890399a1..906b9972 100644 --- a/BasiliskII/src/BeOS/Makefile +++ b/BasiliskII/src/BeOS/Makefile @@ -86,7 +86,7 @@ SYSTEM_INCLUDE_PATHS = # additional paths to look for local headers # thes use the form: #include "header" # source file directories are automatically included -LOCAL_INCLUDE_PATHS = ../include +LOCAL_INCLUDE_PATHS = ../include SheepDriver SheepNet # specify the level of optimization that you desire # NONE, SOME, FULL diff --git a/BasiliskII/src/BeOS/SheepDriver/Makefile b/BasiliskII/src/BeOS/SheepDriver/Makefile new file mode 100644 index 00000000..f67ecc48 --- /dev/null +++ b/BasiliskII/src/BeOS/SheepDriver/Makefile @@ -0,0 +1,117 @@ +## BeOS Generic Makefile v2.1 ## + +## Fill in this file to specify the project being created, and the referenced +## makefile-engine will do all of the hard work for you. This handles both +## Intel and PowerPC builds of the BeOS. + +## Application Specific Settings --------------------------------------------- + +# specify the name of the binary +NAME= sheep + +# specify the type of binary +# APP: Application +# SHARED: Shared library or add-on +# STATIC: Static library archive +# DRIVER: Kernel Driver +TYPE= DRIVER + +# add support for new Pe and Eddie features +# to fill in generic makefile + +#%{ +# @src->@ + +# specify the source files to use +# full paths or paths relative to the makefile can be included +# all files, regardless of directory, will have their object +# files created in the common object directory. +# Note that this means this makefile will not work correctly +# if two source files with the same name (source.c or source.cpp) +# are included from different directories. Also note that spaces +# in folder names do not work well with this makefile. +SRCS= sheep_driver.c + +# specify the resource files to use +# full path or a relative path to the resource file can be used. +RSRCS= + +# @<-src@ +#%} + +# end support for Pe and Eddie + +# specify additional libraries to link against +# there are two acceptable forms of library specifications +# - if your library follows the naming pattern of: +# libXXX.so or libXXX.a you can simply specify XXX +# library: libbe.so entry: be +# +# - if your library does not follow the standard library +# naming scheme you need to specify the path to the library +# and it's name +# library: my_lib.a entry: my_lib.a or path/my_lib.a +LIBS= + +# specify additional paths to directories following the standard +# libXXX.so or libXXX.a naming scheme. You can specify full paths +# or paths relative to the makefile. The paths included may not +# be recursive, so include all of the paths where libraries can +# be found. Directories where source files are found are +# automatically included. +LIBPATHS= + +# additional paths to look for system headers +# thes use the form: #include
+# source file directories are NOT auto-included here +SYSTEM_INCLUDE_PATHS = + +# additional paths to look for local headers +# thes use the form: #include "header" +# source file directories are automatically included +LOCAL_INCLUDE_PATHS = + +# specify the level of optimization that you desire +# NONE, SOME, FULL +OPTIMIZE= FULL + +# specify any preprocessor symbols to be defined. The symbols will not +# have their values set automatically; you must supply the value (if any) +# to use. For example, setting DEFINES to "DEBUG=1" will cause the +# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG" +# would pass "-DDEBUG" on the compiler's command line. +DEFINES= + +# specify special warning levels +# if unspecified default warnings will be used +# NONE = supress all warnings +# ALL = enable all warnings +WARNINGS = + +# specify whether image symbols will be created +# so that stack crawls in the debugger are meaningful +# if TRUE symbols will be created +SYMBOLS = + +# specify debug settings +# if TRUE will allow application to be run from a source-level +# debugger. Note that this will disable all optimzation. +DEBUGGER = + +# specify additional compiler flags for all files +COMPILER_FLAGS = + +# specify additional linker flags +LINKER_FLAGS = + + +## include the makefile-engine +include /boot/develop/etc/makefile-engine + +install: $(TARGET) + cp $(TARGET) /boot/home/config/add-ons/kernel/drivers/bin + ln -s /boot/home/config/add-ons/kernel/drivers/bin/$(NAME) /boot/home/config/add-ons/kernel/drivers/dev/$(NAME) + +uninstall: + rm /boot/home/config/add-ons/kernel/drivers/bin/$(NAME) + rm /boot/home/config/add-ons/kernel/drivers/dev/$(NAME) diff --git a/BasiliskII/src/BeOS/SheepDriver/sheep_driver.c b/BasiliskII/src/BeOS/SheepDriver/sheep_driver.c new file mode 100644 index 00000000..df3dfd6e --- /dev/null +++ b/BasiliskII/src/BeOS/SheepDriver/sheep_driver.c @@ -0,0 +1,472 @@ +/* + * sheep_driver.c - Low memory and ROM access driver for SheepShaver and + * Basilisk II on PowerPC systems + * + * SheepShaver (C) 1997-2000 Mar"c Hellwig and Christian Bauer + * Basilisk II (C) 1997-2000 Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "sheep_driver.h" + +#define DEBUG 0 + +#if DEBUG==1 +#define bug pprintf +#elif DEBUG==2 +#define bug dprintf +#endif + +#if DEBUG +#define D(x) (x) +#else +#define D(x) ; +#endif + +#define PORT_NAME "sheep_driver installed" + + +/* + * For debugging + */ + +static int pprintf(const char* format, ...) +{ + port_id PortNum; + int len, ret; + char Buffer[1024]; + va_list ap; + + if ((PortNum = find_port("PortLogger")) == B_NAME_NOT_FOUND) + return(PortNum); + for (len=0; len<1024; len++) + Buffer[len]='\0'; + va_start(ap, format); + vsprintf(Buffer, format, ap); + ret = write_port(PortNum, 0, Buffer, strlen(Buffer)); + return ret; +} + + +/* + * Page table functions + */ + +static uint32 *pte_address = 0; +static uint32 vsid; +static uint32 table_size; + +static status_t map_page(uint32 ea, uint32 ra, uint32 **free_pte, uint32 bits) +{ + int i; + int pte_class; + uint32 hash1, hash2, api, *pteg1, *pteg2; + + D(bug("Trying to map EA %p -> RA %p\n", ea, ra)); + + // Find PTEG addresses for given EA + hash1 = (vsid & 0x7ffff) ^ ((ea >> 12) & 0xffff); + hash2 = ~hash1 & 0x7ffff; + api = (ea >> 22) & 0x3f; + pteg1 = (uint32 *)((uint32)pte_address + ((hash1 << 6) & (table_size - 1))); + pteg2 = (uint32 *)((uint32)pte_address + ((hash2 << 6) & (table_size - 1))); + D(bug("PTEG1 at %p, PTEG2 at %p\n", pteg1, pteg2)); + + // Search all 8 PTEs of each PTEG + *free_pte = NULL; + pte_class = 0; + for (i=0; i<8; i++) { + D(bug(" found %08lx %08lx\n", pteg1[i*2], pteg1[i*2+1])); + if (pteg1[i*2] == (0x80000000 | (vsid << 7) | (pte_class << 6) | api)) { + *free_pte = pteg1 + i*2; + D(bug(" existing PTE found (PTEG1)\n")); + break; + } else if (!pteg1[i*2]) { + *free_pte = pteg1 + i*2; + D(bug(" free PTE found (PTEG1)\n")); + break; + } + } + if (*free_pte == NULL) { + pte_class = 1; + for (i=0; i<8; i++) { + D(bug(" found %08lx %08lx\n", pteg2[i*2], pteg2[i*2+1])); + if (pteg2[i*2] == (0x80000000 | (vsid << 7) | (pte_class << 6) | api)) { + *free_pte = pteg2 + i*2; + D(bug(" existing PTE found (PTEG2)\n")); + break; + } else if (!pteg2[i*2]) { + *free_pte = pteg2 + i*2; + D(bug(" free PTE found (PTEG2)\n")); + break; + } + } + } + + // Remap page + if (*free_pte == NULL) { + D(bug(" No free PTE found :-(\m")); + return B_DEVICE_FULL; + } else { + (*free_pte)[0] = 0x80000000 | (vsid << 7) | (pte_class << 6) | api; + (*free_pte)[1] = ra | bits; + D(bug(" written %08lx %08lx to PTE\n", (*free_pte)[0], (*free_pte)[1])); + return B_NO_ERROR; + } +} + +static status_t remap_page(uint32 *free_pte, uint32 ra, uint32 bits) +{ + D(bug("Remapping PTE %p -> RA %p\n", free_pte, ra)); + + // Remap page + if (free_pte == NULL) { + D(bug(" Invalid PTE :-(\n")); + return B_BAD_ADDRESS; + } else { + free_pte[1] = ra | bits; + D(bug(" written %08lx %08lx to PTE\n", free_pte[0], free_pte[1])); + return B_NO_ERROR; + } +} + + +/* + * Foward declarations for hook functions + */ + +static status_t sheep_open(const char *name, uint32 flags, void **cookie); +static status_t sheep_close(void *cookie); +static status_t sheep_free(void *cookie); +static status_t sheep_control(void *cookie, uint32 op, void *data, size_t len); +static status_t sheep_read(void *cookie, off_t pos, void *data, size_t *len); +static status_t sheep_write(void *cookie, off_t pos, const void *data, size_t *len); + + +/* + * Version of our driver + */ + +int32 api_version = B_CUR_DRIVER_API_VERSION; + + +/* + * Device_hooks structure - has function pointers to the + * various entry points for device operations + */ + +static device_hooks my_device_hooks = { + &sheep_open, + &sheep_close, + &sheep_free, + &sheep_control, + &sheep_read, + &sheep_write, + NULL, + NULL, + NULL, + NULL +}; + + +/* + * List of device names to be returned by publish_devices() + */ + +static char *device_name_list[] = { + "sheep", + 0 +}; + + +/* + * Init - do nothing + */ + +status_t init_hardware(void) +{ +#if DEBUG==2 + set_dprintf_enabled(true); +#endif + D(bug("init_hardware()\n")); + return B_NO_ERROR; +} + +status_t init_driver(void) +{ + D(bug("init_driver()\n")); + return B_NO_ERROR; +} + +void uninit_driver(void) +{ + D(bug("uninit_driver()\n")); +} + + +/* + * publish_devices - return list of device names implemented by this driver + */ + +const char **publish_devices(void) +{ + return device_name_list; +} + + +/* + * find_device - return device hooks for a specific device name + */ + +device_hooks *find_device(const char *name) +{ + if (!strcmp(name, device_name_list[0])) + return &my_device_hooks; + + return NULL; +} + + +/* + * sheep_open - hook function for the open call. + */ + +static status_t sheep_open(const char *name, uint32 flags, void **cookie) +{ + return B_NO_ERROR; +} + + +/* + * sheep_close - hook function for the close call. + */ + +static status_t sheep_close(void *cookie) +{ + return B_NO_ERROR; +} + + +/* + * sheep_free - hook function to free the cookie returned + * by the open hook. Since the open hook did not return + * a cookie, this is a no-op. + */ + +static status_t sheep_free(void *cookie) +{ + return B_NO_ERROR; +} + + +/* + * sheep_control - hook function for the ioctl call + */ + +static asm void inval_tlb(uint32 ea) +{ + isync + tlbie r3 + sync + blr +} + +static asm void tlbsync(void) +{ + machine 604 + tlbsync + sync + blr +} + +static status_t sheep_control(void *cookie, uint32 op, void *data, size_t len) +{ + static void *block; + static void *block_aligned; + physical_entry pe[2]; + system_info sysinfo; + area_id id; + area_info info; + cpu_status cpu_st; + status_t res; + uint32 ra0, ra1; + uint32 *free_pte_0, *free_pte_1; + int i; + + D(bug("control(%d) data %p, len %08x\n", op, data, len)); + + switch (op) { + case SHEEP_UP: + + // Already messed up? Then do nothing now + if (find_port(PORT_NAME) != B_NAME_NOT_FOUND) + return B_NO_ERROR; + + // Get system info + get_system_info(&sysinfo); + + // Prepare replacement memory + block = malloc(B_PAGE_SIZE * 3); + D(bug("3 pages malloc()ed at %p\n", block)); + block_aligned = (void *)(((uint32)block + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE-1)); + D(bug("Address aligned to %p\n", block_aligned)); + res = lock_memory(block_aligned, B_PAGE_SIZE * 2, 0); + if (res < 0) + return res; + + // Get memory mapping + D(bug("Memory locked\n")); + res = get_memory_map(block_aligned, B_PAGE_SIZE * 2, pe, 2); + D(bug("get_memory_map returned %d\n", res)); + if (res != B_NO_ERROR) + return res; + + // Find PTE table area + id = find_area("pte_table"); + get_area_info(id, &info); + pte_address = (uint32 *)info.address; + D(bug("PTE table seems to be at %p\n", pte_address)); + table_size = info.size; + D(bug("PTE table size: %dKB\n", table_size / 1024)); + + // Disable interrupts + cpu_st = disable_interrupts(); + + // Find vsid and real addresses of replacement memory + for (i=0; i> 31),((pte_address[i*2]&0x7fffff80) >> 7), + ((pte_address[i*2]&0x00000040) >> 6),(pte_address[i*2] & 0x3f), + ((pte_address[i*2+1]&0xfffff000) >> 12),((pte_address[i*2+1]&0x00000100) >> 8), + ((pte_address[i*2+1]&0x00000080) >> 7),((pte_address[i*2+1]&0x00000078) >> 3), + (pte_address[i*2+1]&0x00000003))); + vsid = (pte_address[i*2]&0x7fffff80) >> 7; + ra0 = (uint32)pe[0].address & 0xfffff000; + } + if ((uint32)pe[0].size == B_PAGE_SIZE) { + if (((uint32)pe[1].address & 0xfffff000)==(pte_address[i*2+1]&0xfffff000)) { + D(bug("Found page 1f PtePos %04x V%x VSID %03x H%x API %02x RPN %03x R%1x C%1x WIMG%1x PP%1x \n", + i << 2, + ((pte_address[i*2]&0x80000000) >> 31), ((pte_address[i*2]&0x7fffff80) >> 7), + ((pte_address[i*2]&0x00000040) >> 6), (pte_address[i*2] & 0x3f), + ((pte_address[i*2+1]&0xfffff000) >> 12), ((pte_address[i*2+1]&0x00000100) >> 8), + ((pte_address[i*2+1]&0x00000080) >> 7), ((pte_address[i*2+1]&0x00000078) >> 3), + (pte_address[i*2+1]&0x00000003))); + ra1 = (uint32)pe[1].address & 0xfffff000; + } + } else { + if ((((uint32)pe[0].address + B_PAGE_SIZE) & 0xfffff000)==(pte_address[i*2+1]&0xfffff000)) { + D(bug("Found page 1d PtePos %04x V%x VSID %03x H%x API %02x RPN %03x R%1x C%1x WIMG%1x PP%1x \n", + i << 2, + ((pte_address[i*2]&0x80000000) >> 31), ((pte_address[i*2]&0x7fffff80) >> 7), + ((pte_address[i*2]&0x00000040) >> 6), (pte_address[i*2] & 0x3f), + ((pte_address[i*2+1]&0xfffff000) >> 12), ((pte_address[i*2+1]&0x00000100) >> 8), + ((pte_address[i*2+1]&0x00000080) >> 7), ((pte_address[i*2+1]&0x00000078) >> 3), + (pte_address[i*2+1]&0x00000003))); + ra1 = ((uint32)pe[0].address + B_PAGE_SIZE) & 0xfffff000; + } + } + } + + // Map low memory for emulator + free_pte_0 = NULL; + free_pte_1 = NULL; + __sync(); + __isync(); + inval_tlb(0); + inval_tlb(B_PAGE_SIZE); + if (sysinfo.cpu_type != B_CPU_PPC_603 && sysinfo.cpu_type != B_CPU_PPC_603e) + tlbsync(); + res = map_page(0, ra0, &free_pte_0, 0x12); + if (res == B_NO_ERROR) + res = map_page(B_PAGE_SIZE, ra1, &free_pte_1, 0x12); + inval_tlb(0); + inval_tlb(B_PAGE_SIZE); + if (sysinfo.cpu_type != B_CPU_PPC_603 && sysinfo.cpu_type != B_CPU_PPC_603e) + tlbsync(); + __sync(); + __isync(); + + // Restore interrupts + restore_interrupts(cpu_st); + + // Create port so we know that messing was successful + set_port_owner(create_port(1, PORT_NAME), B_SYSTEM_TEAM); + return B_NO_ERROR; + + case SHEEP_DOWN: + return B_NO_ERROR; + + default: + return B_BAD_VALUE; + } +} + + +/* + * sheep_read - hook function for the read call + */ + +static status_t sheep_read(void *cookie, off_t pos, void *data, size_t *len) +{ + void *rom_adr; + area_id area; + system_info info; + + D(bug("read() pos %Lx, data %p, len %08x\n", pos, data, *len)); + + get_system_info(&info); + if (info.platform_type == B_BEBOX_PLATFORM) { + *len = 0; + return B_ERROR; + } + if (*len != 0x400000 && pos != 0) { + *len = 0; + return B_BAD_VALUE; + } + area = map_physical_memory("mac_rom", (void *)0xff000000, 0x00400000, B_ANY_KERNEL_ADDRESS, B_READ_AREA, &rom_adr); + D(bug("Mapped ROM to %p, area id %d\n", rom_adr, area)); + if (area < 0) { + *len = 0; + return area; + } + D(bug("Copying ROM\n")); + memcpy(data, rom_adr, *len); + D(bug("Deleting area\n")); + delete_area(area); + return B_NO_ERROR; +} + + +/* + * sheep_write - hook function for the write call + */ + +static status_t sheep_write(void *cookie, off_t pos, const void *data, size_t *len) +{ + D(bug("write() pos %Lx, data %p, len %08x\n", pos, data, *len)); + return B_READ_ONLY_DEVICE; +} diff --git a/BasiliskII/src/BeOS/SheepDriver/sheep_driver.h b/BasiliskII/src/BeOS/SheepDriver/sheep_driver.h new file mode 100644 index 00000000..1221f164 --- /dev/null +++ b/BasiliskII/src/BeOS/SheepDriver/sheep_driver.h @@ -0,0 +1,33 @@ +/* + * sheep_driver.h - Low memory and ROM access driver for SheepShaver and + * Basilisk II on PowerPC systems + * + * SheepShaver (C) 1997-2000 Mar"c" Hellwig and Christian Bauer + * Basilisk II (C) 1997-2000 Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef SHEEP_DRIVER_H +#define SHEEP_DRIVER_H + +#include + +enum { + SHEEP_UP = B_DEVICE_OP_CODES_END + 1, + SHEEP_DOWN +}; + +#endif diff --git a/BasiliskII/src/BeOS/SheepNet/Makefile b/BasiliskII/src/BeOS/SheepNet/Makefile new file mode 100644 index 00000000..36b882fc --- /dev/null +++ b/BasiliskII/src/BeOS/SheepNet/Makefile @@ -0,0 +1,115 @@ +## BeOS Generic Makefile v2.1 ## + +## Fill in this file to specify the project being created, and the referenced +## makefile-engine will do all of the hard work for you. This handles both +## Intel and PowerPC builds of the BeOS. + +## Application Specific Settings --------------------------------------------- + +# specify the name of the binary +NAME= sheep_net + +# specify the type of binary +# APP: Application +# SHARED: Shared library or add-on +# STATIC: Static library archive +# DRIVER: Kernel Driver +TYPE= SHARED + +# add support for new Pe and Eddie features +# to fill in generic makefile + +#%{ +# @src->@ + +# specify the source files to use +# full paths or paths relative to the makefile can be included +# all files, regardless of directory, will have their object +# files created in the common object directory. +# Note that this means this makefile will not work correctly +# if two source files with the same name (source.c or source.cpp) +# are included from different directories. Also note that spaces +# in folder names do not work well with this makefile. +SRCS= sheep_net.cpp + +# specify the resource files to use +# full path or a relative path to the resource file can be used. +RSRCS= + +# @<-src@ +#%} + +# end support for Pe and Eddie + +# specify additional libraries to link against +# there are two acceptable forms of library specifications +# - if your library follows the naming pattern of: +# libXXX.so or libXXX.a you can simply specify XXX +# library: libbe.so entry: be +# +# - if your library does not follow the standard library +# naming scheme you need to specify the path to the library +# and it's name +# library: my_lib.a entry: my_lib.a or path/my_lib.a +LIBS= netdev + +# specify additional paths to directories following the standard +# libXXX.so or libXXX.a naming scheme. You can specify full paths +# or paths relative to the makefile. The paths included may not +# be recursive, so include all of the paths where libraries can +# be found. Directories where source files are found are +# automatically included. +LIBPATHS= + +# additional paths to look for system headers +# thes use the form: #include
+# source file directories are NOT auto-included here +SYSTEM_INCLUDE_PATHS = + +# additional paths to look for local headers +# thes use the form: #include "header" +# source file directories are automatically included +LOCAL_INCLUDE_PATHS = + +# specify the level of optimization that you desire +# NONE, SOME, FULL +OPTIMIZE= FULL + +# specify any preprocessor symbols to be defined. The symbols will not +# have their values set automatically; you must supply the value (if any) +# to use. For example, setting DEFINES to "DEBUG=1" will cause the +# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG" +# would pass "-DDEBUG" on the compiler's command line. +DEFINES= + +# specify special warning levels +# if unspecified default warnings will be used +# NONE = supress all warnings +# ALL = enable all warnings +WARNINGS = + +# specify whether image symbols will be created +# so that stack crawls in the debugger are meaningful +# if TRUE symbols will be created +SYMBOLS = + +# specify debug settings +# if TRUE will allow application to be run from a source-level +# debugger. Note that this will disable all optimzation. +DEBUGGER = + +# specify additional compiler flags for all files +COMPILER_FLAGS = + +# specify additional linker flags +LINKER_FLAGS = + + +## include the makefile-engine +include /boot/develop/etc/makefile-engine + +install: $(TARGET) + cp $(TARGET) /boot/beos/system/add-ons/net_server/$(NAME) + +uninstall: + rm /boot/beos/system/add-ons/net_server/$(NAME) diff --git a/BasiliskII/src/BeOS/SheepNet/sheep_net.cpp b/BasiliskII/src/BeOS/SheepNet/sheep_net.cpp new file mode 100644 index 00000000..5cf08ee2 --- /dev/null +++ b/BasiliskII/src/BeOS/SheepNet/sheep_net.cpp @@ -0,0 +1,294 @@ +/* + * sheep_net.cpp - Net server add-on for SheepShaver and Basilisk II + * + * SheepShaver (C) 1997-2000 Mar"c" Hellwig and Christian Bauer + * Basilisk II (C) 1997-2000 Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sheep_net.h" + +#define DEBUG 0 + +#if DEBUG==1 +#define bug pprintf +#elif DEBUG==2 +#define bug kprintf +#endif + +#if DEBUG +#define D(x) (x) +#else +#define D(x) ; +#endif + +static int pprintf(const char* format, ...) +{ + port_id PortNum; + int len,Ret; + char Buffer[1024]; + va_list ap; + + if ((PortNum = find_port("PortLogger")) == B_NAME_NOT_FOUND) + return(PortNum); + for (len=0; len<1024; len++) + Buffer[len]='\0'; + va_start(ap, format); + vsprintf(Buffer, format, ap); + Ret = write_port(PortNum, 0, Buffer, strlen(Buffer)); + return(Ret); +} + + +// Constants +#define NETDUMP_PRIO 1 // Default is 0 + +const uint32 buffer_size = (sizeof(net_buffer) / B_PAGE_SIZE + 1) * B_PAGE_SIZE; + + +// SheepNet add-on object +class SheepNetAddOn : public BNetProtocol, BPacketHandler { +public: + void AddDevice(BNetDevice *dev, const char *name); + bool PacketReceived(BNetPacket *buf, BNetDevice *dev); +}; + + +// Global variables +static bool shutdown_now = false; +static bool active = false; + +static thread_id write_thread; // Packet writer +static sem_id write_sem; // Semaphore to trigger packet writing +static BNetDevice *EtherCard = NULL; // The Ethernet card we are attached to +static area_id buffer_area; // Packet buffer area +static net_buffer *net_buffer_ptr; // Pointer to packet buffer + +static uint32 rd_pos; // Current read position in packet buffer +static uint32 wr_pos; // Current write position in packet buffer + + +/* + * Clear packet buffer + */ + +static void clear(void) +{ + int i; + for (i=0;iread[i].cmd = 0; + net_buffer_ptr->read[i].length = 0; + net_buffer_ptr->read[i].card = 0; + net_buffer_ptr->read[i].reserved = 0; + } + for (i=0;iwrite[i].cmd = 0; + net_buffer_ptr->write[i].length = 0; + net_buffer_ptr->write[i].card = 0; + net_buffer_ptr->write[i].reserved = 0; + } + rd_pos = wr_pos = 0; +} + + +/* + * Packet writer thread + */ + +static status_t write_packet_func(void *arg) +{ + while (!shutdown_now) { + + // Read and execute command + net_packet *p = &net_buffer_ptr->write[wr_pos]; + while (p->cmd & IN_USE) { + D(bug("wp: %d\n", wr_pos)); + switch (p->cmd >> 8) { + + case ACTIVATE_SHEEP_NET: + D(bug("activate sheep-net\n")); + active = false; + clear(); + active = true; + goto next; + + case DEACTIVATE_SHEEP_NET: + D(bug("deactivate sheep-net\n")); + active = false; + clear(); + goto next; + + case SHUTDOWN_SHEEP_NET: + D(bug("shutdown sheep-net\n")); + active = false; + clear(); + shutdown_now = true; + goto next; + + case ADD_MULTICAST: { + const char *data = (const char *)p->data; + D(bug("add multicast %02x %02x %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3], data[4], data[5])); + if (active) { + status_t result; + if ((result = EtherCard->AddMulticastAddress(data)) != B_OK) { + // !! handle error !! error while creating multicast address + D(bug("error while creating multicast address %d\n", result)); + } + } + break; + } + + case REMOVE_MULTICAST: { + const char *data = (const char *)p->data; + D(bug("remove multicast %02x %02x %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3], data[4], data[5])); + if (active) { + status_t result; + if ((result = EtherCard->RemoveMulticastAddress(data)) != B_OK) { + // !! handle error !! error while removing multicast address + D(bug("error while removing multicast address %d\n", result)); + } + } + break; + } + + case SHEEP_PACKET: { + uint32 length = p->length; + // D(bug("sheep packet %d\n", length)); + if (active) { + BStandardPacket *packet = new BStandardPacket(length); + packet->Write(0, (const char *)p->data, length); + EtherCard->SendPacket(packet); + } + break; + } + + default: + D(bug("error: unknown port packet type\n")); + break; + } + p->cmd = 0; // Free packet + wr_pos = (wr_pos + 1) % WRITE_PACKET_COUNT; + p = &net_buffer_ptr->write[wr_pos]; + } + + // Wait for next packet +next: acquire_sem_etc(write_sem, 1, B_TIMEOUT, 25000); + } + return 0; +} + + +/* + * Init the net add-on + */ + +static void init_addon() +{ + int i; + D(bug("init sheep-net\n")); + + // Create packet buffer + if ((buffer_area = create_area("packet buffer", &net_buffer_ptr, B_ANY_ADDRESS, buffer_size, B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA)) < B_NO_ERROR) { + D(bug("FATAL ERROR: can't create shared area\n")); + return; + } + + // Init packet buffer + clear(); + EtherCard->Address((char *)net_buffer_ptr->ether_addr); + net_buffer_ptr->read_sem = -1; + net_buffer_ptr->read_ofs = (uint32)(net_buffer_ptr->read) - (uint32)net_buffer_ptr; + net_buffer_ptr->read_packet_size = sizeof(net_packet); + net_buffer_ptr->read_packet_count = READ_PACKET_COUNT; + if ((write_sem = create_sem(0, "ether write")) < B_NO_ERROR) { + D(bug("FATAL ERROR: can't create semaphore\n")); + return; + } + net_buffer_ptr->write_sem = write_sem; + net_buffer_ptr->write_ofs = (uint32)(net_buffer_ptr->write) - (uint32)net_buffer_ptr; + net_buffer_ptr->write_packet_size = sizeof(net_packet); + net_buffer_ptr->write_packet_count = WRITE_PACKET_COUNT; + + // Start packet writer thread + write_thread = spawn_thread(write_packet_func, "sheep_net ether write", B_URGENT_DISPLAY_PRIORITY, NULL); + resume_thread(write_thread); +} + + +/* + * Add-on attached to Ethernet card + */ + +void SheepNetAddOn::AddDevice(BNetDevice *dev, const char *name) +{ + if (dev->Type() != B_ETHER_NET_DEVICE) + return; + if (EtherCard != NULL) { + // !! handle error !! support for multiple ethernet cards ... + D(bug("error: SheepShaver doesn't support multiple Ethernetcards !\n")); + return; + } + EtherCard = dev; + init_addon(); + register_packet_handler(this, dev, NETDUMP_PRIO); +} + + +/* + * Ethernet packet received + */ + +bool SheepNetAddOn::PacketReceived(BNetPacket *pkt, BNetDevice *dev) +{ + if (shutdown_now) { + unregister_packet_handler(this, dev); + return false; + } +// D(bug("read_packet_func %d\n", pkt->Size())); + if (active) { + D(bug("rp: %d\n", rd_pos)); + net_packet *p = &net_buffer_ptr->read[rd_pos]; + if (p->cmd & IN_USE) { + D(bug("error: full read buffer ... lost packet\n")); + } else { + memcpy(p->data, pkt->Data(), pkt->Size()); + p->length = pkt->Size(); + p->cmd = IN_USE | (SHEEP_PACKET << 8); + rd_pos = (rd_pos + 1) % READ_PACKET_COUNT; + release_sem(net_buffer_ptr->read_sem); + } + } + //D(bug("%02x %02x %02x %02x %02x %02x", (uchar) (pkt->Data())[0],(uchar) (pkt->Data())[1],(uchar) (pkt->Data())[2],(uchar) (pkt->Data())[3],(uchar) (pkt->Data())[4],(uchar) (pkt->Data())[5])); + return false; +} + +#pragma export on +extern "C" BNetProtocol *open_protocol(const char *device) +{ + SheepNetAddOn *dev = new SheepNetAddOn; + return dev; +} +#pragma export off diff --git a/BasiliskII/src/BeOS/sheep_net.h b/BasiliskII/src/BeOS/SheepNet/sheep_net.h similarity index 55% rename from BasiliskII/src/BeOS/sheep_net.h rename to BasiliskII/src/BeOS/SheepNet/sheep_net.h index 7d7febd9..165325c1 100644 --- a/BasiliskII/src/BeOS/sheep_net.h +++ b/BasiliskII/src/BeOS/SheepNet/sheep_net.h @@ -1,8 +1,22 @@ /* - * sheep_net.h - SheepShaver net server add-on + * sheep_net.h - Net server add-on for SheepShaver and Basilisk II * * SheepShaver (C) 1997-2000 Mar"c Hellwig and Christian Bauer - * All rights reserved. + * Basilisk II (C) 1997-2000 Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef SHEEP_NET_H diff --git a/BasiliskII/src/BeOS/sheep_driver.h b/BasiliskII/src/BeOS/sheep_driver.h deleted file mode 100644 index 3491b42a..00000000 --- a/BasiliskII/src/BeOS/sheep_driver.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * sheep_driver.h - Driver for SheepShaver (low memory, ROM access) - * - * SheepShaver (C) 1997-2000 Mar"c" Hellwig and Christian Bauer - * All rights reserved. - */ - -#ifndef SHEEP_DRIVER_H -#define SHEEP_DRIVER_H - -#include - -enum { - SHEEP_UP = B_DEVICE_OP_CODES_END + 1, - SHEEP_DOWN -}; - -#endif