Cleanup and Bugfixing
authorJohn Hodge <[email protected]>
Fri, 20 Nov 2009 16:06:55 +0000 (00:06 +0800)
committerJohn Hodge <[email protected]>
Fri, 20 Nov 2009 16:06:55 +0000 (00:06 +0800)
- Created a _very_ basic `ifconfig` app to test the IPStack module
- Fixed a bug in MM_NewWorkerStack that caused it to always fail
- Added the LEAVE_RET macro to simplify debugging
- Moved BochsGA driver to module tree
- More work on the IPStack
- Fixed compile errors in NE2000 driver
- and did some work on the makefiles

13 files changed:
Kernel/arch/x86/mm_virt.c
Kernel/binary.c
Kernel/drv/vterm.c
Kernel/include/common.h
Makefile
Modules/BochsGA/Makefile [new file with mode: 0644]
Modules/BochsGA/bochsvbe.c [new file with mode: 0644]
Modules/IPStack/link.h
Modules/IPStack/main.c
Modules/Makefile.tpl
Modules/NE2000/ne2000.c
Usermode/Applications/ifconfig_src/Makefile [new file with mode: 0644]
Usermode/Applications/ifconfig_src/main.c [new file with mode: 0644]

index 44e1865..9892998 100644 (file)
@@ -63,7 +63,7 @@ tPAddr        *gaTmpDir = (void*)TMP_DIR_ADDR;
 tPAddr *gTmpCR3 = (void*)TMP_CR3_ADDR;
  int   gilTempMappings = 0;
  int   gilTempFractal = 0;
-Uint32 gWorkerStacks[NUM_WORKER_STACKS/32];
+Uint32 gWorkerStacks[(NUM_WORKER_STACKS+31)/32];
  int   giLastUsedWorker = 0;
 
 // === CODE ===
@@ -615,6 +615,7 @@ tVAddr MM_NewWorkerStack()
                if( gWorkerStacks[base/32] & (1 << base) ) {
                        continue;
                }
+               break;
        }
        if(base >= NUM_WORKER_STACKS) {
                Warning("Uh-oh! Out of worker stacks");
index 43d8cb3..e96da76 100644 (file)
@@ -12,7 +12,7 @@
 //! \todo Move 0xBC000000 to mm_virt.h\r
 #define BIN_HIGHEST    (0xBC000000-BIN_GRANUALITY)             // Just below the kernel\r
 #define        KLIB_LOWEST     MM_MODULE_MIN\r
-#define KLIB_GRANUALITY        0x8000          // 32KiB\r
+#define KLIB_GRANUALITY        0x10000         // 32KiB\r
 #define        KLIB_HIGHEST    (MM_MODULE_MAX-KLIB_GRANUALITY)\r
 \r
 // === TYPES ===\r
index 96f02ed..d33fad9 100644 (file)
@@ -16,8 +16,8 @@
 #define MAX_INPUT_CHARS32      64
 #define MAX_INPUT_CHARS8       (MAX_INPUT_CHARS32*4)
 #define VT_SCROLLBACK  1       // 2 Screens of text
-//#define DEFAULT_OUTPUT       "VGA"
-#define DEFAULT_OUTPUT "BochsGA"
+#define DEFAULT_OUTPUT "VGA"
+//#define DEFAULT_OUTPUT       "BochsGA"
 #define DEFAULT_INPUT  "PS2Keyboard"
 #define        DEFAULT_WIDTH   80
 #define        DEFAULT_HEIGHT  25
index 7638b48..0ff9c7f 100644 (file)
@@ -102,10 +102,13 @@ extern void       Debug_HexDump(char *Header, void *Data, Uint Length);
 # define ENTER(_types...)      Debug_Enter((char*)__func__, _types)
 # define LOG(_fmt...)  Debug_Log((char*)__func__, _fmt)
 # define LEAVE(_t...)  Debug_Leave((char*)__func__, _t)
+# define LEAVE_RET(_t,_v...)   do{LEAVE(_t,_v);return _v;}while(0)
+//# define LEAVE_RET(_t)       do{LEAVE(_t);return;}
 #else
 # define ENTER(...)
 # define LOG(...)
 # define LEAVE(...)
+# define LEAVE_RET(_t,_v...)   return (_v)
 #endif
 /**
  * \}
index 88b8377..90ed23c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -4,24 +4,24 @@
 
 .PHONY: all clean
 
-MODULES = IPStack
+MODULES = FS_Ext2 FDD BochsGA IPStack NE2000
 USRLIBS = ld-acess.so libacess.so libgcc.so libc.so
-USRAPPS = init login CLIShell cat ls mount
+USRAPPS = init login CLIShell cat ls mount ifconfig
 
 all:
        @for mod in $(MODULES); do \
-       (echo === $$mod && $(MAKE) all --no-print-directory -C Modules/$$mod) \
+       (echo === Module: $$mod && $(MAKE) all --no-print-directory -C Modules/$$mod) \
        done
        
        @echo === Kernel
        @$(MAKE) all --no-print-directory -C Kernel
        
        @for lib in $(USRLIBS); do \
-       (echo === $$lib && $(MAKE) all --no-print-directory -C Usermode/Libraries/`echo $$lib`_src) \
+       (echo === User Library: $$lib && $(MAKE) all --no-print-directory -C Usermode/Libraries/`echo $$lib`_src) \
        done
        
        @for app in $(USRAPPS); do \
-       (echo === $$app && $(MAKE) all --no-print-directory -C Usermode/Applications/`echo $$app`_src) \
+       (echo === User Application: $$app && $(MAKE) all --no-print-directory -C Usermode/Applications/`echo $$app`_src) \
        done
 
 #      @echo === ld-acess.so
@@ -46,6 +46,10 @@ all:
 #      @$(MAKE) all --no-print-directory -C Usermode/Applications/mount_src
 
 clean:
+       @for mod in $(MODULES); do \
+       ($(MAKE) clean --no-print-directory -C Modules/$$mod) \
+       done
+       
        @make clean --no-print-directory -C Kernel/
        
        @for lib in $(USRLIBS); do \
diff --git a/Modules/BochsGA/Makefile b/Modules/BochsGA/Makefile
new file mode 100644 (file)
index 0000000..2df219a
--- /dev/null
@@ -0,0 +1,7 @@
+#
+#
+
+OBJ = bochsvbe.o
+NAME = BochsGA
+
+-include ../Makefile.tpl
diff --git a/Modules/BochsGA/bochsvbe.c b/Modules/BochsGA/bochsvbe.c
new file mode 100644 (file)
index 0000000..a833503
--- /dev/null
@@ -0,0 +1,469 @@
+/**\r
+ * \file drv_bochsvbe.c\r
+ * \brief BGA (Bochs Graphic Adapter) Driver\r
+ * \note for Acess2\r
+ * \warning This driver does NOT support the Bochs PCI VGA driver\r
+*/\r
+#define DEBUG  0\r
+#include <common.h>\r
+#include <errno.h>\r
+#include <modules.h>\r
+#include <vfs.h>\r
+#include <fs_devfs.h>\r
+#include <drv_pci.h>\r
+#include <tpl_drv_video.h>\r
+\r
+//#define INT  static\r
+#define INT\r
+\r
+// === TYPEDEFS ===\r
+typedef struct {\r
+       Uint16  width;\r
+       Uint16  height;\r
+       Uint16  bpp;\r
+       Uint16  flags;\r
+       Uint32  fbSize;\r
+} t_bga_mode;\r
+\r
+// === CONSTANTS ===\r
+enum eMode_Flags {\r
+       MODEFLAG_TEXT = 1\r
+};\r
+#define        BGA_LFB_MAXSIZE (1024*768*4)\r
+#define        VBE_DISPI_BANK_ADDRESS  0xA0000\r
+#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000\r
+#define VBE_DISPI_IOPORT_INDEX 0x01CE\r
+#define        VBE_DISPI_IOPORT_DATA   0x01CF\r
+#define        VBE_DISPI_DISABLED      0x00\r
+#define VBE_DISPI_ENABLED      0x01\r
+#define        VBE_DISPI_LFB_ENABLED   0x40\r
+#define        VBE_DISPI_NOCLEARMEM    0x80\r
+enum {\r
+       VBE_DISPI_INDEX_ID,\r
+       VBE_DISPI_INDEX_XRES,\r
+       VBE_DISPI_INDEX_YRES,\r
+       VBE_DISPI_INDEX_BPP,\r
+       VBE_DISPI_INDEX_ENABLE,\r
+       VBE_DISPI_INDEX_BANK,\r
+       VBE_DISPI_INDEX_VIRT_WIDTH,\r
+       VBE_DISPI_INDEX_VIRT_HEIGHT,\r
+       VBE_DISPI_INDEX_X_OFFSET,\r
+       VBE_DISPI_INDEX_Y_OFFSET\r
+};\r
+\r
+\r
+// === PROTOTYPES ===\r
+// Driver\r
+ int   BGA_Install(char **Arguments);\r
+void   BGA_Uninstall();\r
+// Internal\r
+void   BGA_int_WriteRegister(Uint16 reg, Uint16 value);\r
+Uint16 BGA_int_ReadRegister(Uint16 reg);\r
+void   BGA_int_SetBank(Uint16 bank);\r
+void   BGA_int_SetMode(Uint16 width, Uint16 height);\r
+ int   BGA_int_UpdateMode(int id);\r
+ int   BGA_int_FindMode(tVideo_IOCtl_Mode *info);\r
+ int   BGA_int_ModeInfo(tVideo_IOCtl_Mode *info);\r
+ int   BGA_int_MapFB(void *Dest);\r
+// Filesystem\r
+Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer);\r
+Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer);\r
+ int   BGA_Ioctl(tVFS_Node *node, int id, void *data);\r
+\r
+// === GLOBALS ===\r
+MODULE_DEFINE(0, 0x0032, BochsGA, BGA_Install, NULL, NULL);\r
+tDevFS_Driver  gBGA_DriverStruct = {\r
+       NULL, "BochsGA",\r
+       {\r
+       .Read = BGA_Read,\r
+       .Write = BGA_Write,\r
+       .IOCtl = BGA_Ioctl\r
+       }\r
+};\r
+ int   giBGA_CurrentMode = -1;\r
+tVideo_IOCtl_Pos       gBGA_CursorPos = {-1,-1};\r
+ int   giBGA_DriverId = -1;\r
+Uint   *gBGA_Framebuffer;\r
+t_bga_mode     gBGA_Modes[] = {\r
+       {},\r
+       { 80,25, 12, MODEFLAG_TEXT, 80*25*8},   // 640 x 480\r
+       {100,37, 12, MODEFLAG_TEXT, 100*37*8},  // 800 x 600\r
+       {640,480,8, 0, 640*480},\r
+       {640,480,32, 0, 640*480*4},\r
+       {800,600,8, 0, 800*600},\r
+       {800,600,32, 0, 800*600*4},\r
+};\r
+#define        BGA_MODE_COUNT  (sizeof(gBGA_Modes)/sizeof(gBGA_Modes[0]))\r
+\r
+// === CODE ===\r
+/**\r
+ * \fn int BGA_Install(char **Arguments)\r
+ */\r
+int BGA_Install(char **Arguments)\r
+{\r
+        int    bga_version = 0;\r
+       \r
+       // Check BGA Version\r
+       bga_version = BGA_int_ReadRegister(VBE_DISPI_INDEX_ID);\r
+       // NOTE: This driver was written for 0xB0C4, but they seem to be backwards compatable\r
+       if(bga_version < 0xB0C4 || bga_version > 0xB0C5) {\r
+               Warning("[BGA ] Bochs Adapter Version is not 0xB0C4 or 0xB0C5, instead 0x%x", bga_version);\r
+               return 0;\r
+       }\r
+       \r
+       // Install Device\r
+       giBGA_DriverId = DevFS_AddDevice( &gBGA_DriverStruct );\r
+       if(giBGA_DriverId == -1) {\r
+               Warning("[BGA ] Unable to register with DevFS, maybe already loaded?");\r
+               return 0;\r
+       }\r
+       \r
+       // Map Framebuffer to hardware address\r
+       gBGA_Framebuffer = (void *) MM_MapHWPage(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 768);  // 768 pages (3Mb)\r
+       \r
+       return 1;\r
+}\r
+\r
+/**\r
+ * \fn void BGA_Uninstall()\r
+ */\r
+void BGA_Uninstall()\r
+{\r
+       //DevFS_DelDevice( giBGA_DriverId );\r
+       MM_UnmapHWPage( VBE_DISPI_LFB_PHYSICAL_ADDRESS, 768 );\r
+}\r
+\r
+/**\r
+ * \fn Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer)\r
+ * \brief Read from the framebuffer\r
+ */\r
+Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer)\r
+{\r
+       // Check Mode\r
+       if(giBGA_CurrentMode == -1)     return -1;\r
+       \r
+       // Check Offset and Length against Framebuffer Size\r
+       if(off+len > gBGA_Modes[giBGA_CurrentMode].fbSize)\r
+               return -1;\r
+       \r
+       // Copy from Framebuffer\r
+       memcpy(buffer, (void*)((Uint)gBGA_Framebuffer + (Uint)off), len);\r
+       return len;\r
+}\r
+\r
+/**\r
+ * \fn Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer)\r
+ * \brief Write to the framebuffer\r
+ */\r
+Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer)\r
+{      \r
+       ENTER("xoff xlen", off, len);\r
+       \r
+       // Check Mode\r
+       if(giBGA_CurrentMode == -1) {\r
+               LEAVE('i', -1);\r
+               return -1;\r
+       }\r
+       \r
+       // Check Input against Frambuffer Size\r
+       if(off+len > gBGA_Modes[giBGA_CurrentMode].fbSize) {\r
+               LEAVE('i', -1);\r
+               return -1;\r
+       }\r
+       \r
+       // Text Mode\r
+       if( gBGA_Modes[giBGA_CurrentMode].flags & MODEFLAG_TEXT )\r
+       {\r
+               tVT_Char        *chars = buffer;\r
+                int    pitch = gBGA_Modes[giBGA_CurrentMode].width * giVT_CharWidth;\r
+                int    x, y;\r
+               Uint32  *dest;\r
+               \r
+               off /= sizeof(tVT_Char);\r
+               dest = (void*)gBGA_Framebuffer;\r
+               x = (off % gBGA_Modes[giBGA_CurrentMode].width) * giVT_CharWidth;\r
+               y = (off / gBGA_Modes[giBGA_CurrentMode].width) * giVT_CharHeight;\r
+               dest += y * pitch;\r
+               dest += x * giVT_CharWidth;\r
+               len /= sizeof(tVT_Char);\r
+               while(len--)\r
+               {\r
+                       VT_Font_Render(\r
+                               chars->Ch,\r
+                               dest, pitch,\r
+                               VT_Colour12to24(chars->BGCol),\r
+                               VT_Colour12to24(chars->FGCol)\r
+                               );\r
+                       \r
+                       dest += giVT_CharWidth;\r
+                       \r
+                       chars ++;\r
+                       x += giVT_CharWidth;\r
+                       if( x >= pitch ) {\r
+                               x = 0;\r
+                               y += giVT_CharHeight;\r
+                               dest += pitch*(giVT_CharHeight-1);\r
+                       }\r
+               }\r
+       }\r
+       else\r
+       {\r
+               Uint8   *destBuf = (Uint8*) ((Uint)gBGA_Framebuffer + (Uint)off);\r
+               \r
+               LOG("buffer = %p\n", buffer);\r
+               LOG("Updating Framebuffer (%p to %p)\n", \r
+                       destBuf, destBuf + (Uint)len);\r
+               \r
+               \r
+               // Copy to Frambuffer\r
+               memcpy(destBuf, buffer, len);\r
+               \r
+               LOG("BGA Framebuffer updated\n");\r
+       }\r
+       \r
+       LEAVE('i', len);\r
+       return len;\r
+}\r
+\r
+/**\r
+ * \fn INT int BGA_Ioctl(tVFS_Node *node, int ID, void *Data)\r
+ * \brief Handle messages to the device\r
+ */\r
+INT int BGA_Ioctl(tVFS_Node *node, int ID, void *Data)\r
+{\r
+        int    ret = -2;\r
+       ENTER("pNode iId pData", node, ID, Data);\r
+       \r
+       switch(ID)\r
+       {\r
+       case DRV_IOCTL_TYPE:\r
+               ret = DRV_TYPE_VIDEO;\r
+               break;\r
+       case DRV_IOCTL_IDENT:\r
+               memcpy(Data, "BGA1", 4);\r
+               ret = 1;\r
+               break;\r
+       case DRV_IOCTL_VERSION:\r
+               ret = 0x100;\r
+               break;\r
+       case DRV_IOCTL_LOOKUP:  // TODO: Implement\r
+               ret = 0;\r
+               break;\r
+               \r
+       case VIDEO_IOCTL_SETMODE:\r
+               ret = BGA_int_UpdateMode(*(int*)(Data));\r
+               break;\r
+               \r
+       case VIDEO_IOCTL_GETMODE:\r
+               ret = giBGA_CurrentMode;\r
+               break;\r
+       \r
+       case VIDEO_IOCTL_FINDMODE:\r
+               ret = BGA_int_FindMode((tVideo_IOCtl_Mode*)Data);\r
+               break;\r
+       \r
+       case VIDEO_IOCTL_MODEINFO:\r
+               ret = BGA_int_ModeInfo((tVideo_IOCtl_Mode*)Data);\r
+               break;\r
+       \r
+       // Request Access to LFB\r
+       case VIDEO_IOCTL_REQLFB:\r
+               ret = BGA_int_MapFB( *(void**)Data );\r
+               break;\r
+       \r
+       case VIDEO_IOCTL_SETCURSOR:\r
+               gBGA_CursorPos.x = ((tVideo_IOCtl_Pos*)Data)->x;\r
+               gBGA_CursorPos.y = ((tVideo_IOCtl_Pos*)Data)->y;\r
+               break;\r
+       \r
+       default:\r
+               LEAVE('i', -2);\r
+               return -2;\r
+       }\r
+       \r
+       LEAVE('i', ret);\r
+       return ret;\r
+}\r
+\r
+//== Internal Functions ==\r
+/**\r
+ * \fn void BGA_int_WriteRegister(Uint16 reg, Uint16 value)\r
+ * \brief Writes to a BGA register\r
+ */\r
+void BGA_int_WriteRegister(Uint16 reg, Uint16 value)\r
+{\r
+       outw(VBE_DISPI_IOPORT_INDEX, reg);\r
+       outw(VBE_DISPI_IOPORT_DATA, value);\r
+}\r
+\r
+INT Uint16 BGA_int_ReadRegister(Uint16 reg)\r
+{\r
+       outw(VBE_DISPI_IOPORT_INDEX, reg);\r
+       return inw(VBE_DISPI_IOPORT_DATA);\r
+}\r
+\r
+#if 0\r
+INT void BGA_int_SetBank(Uint16 bank)\r
+{\r
+       BGA_int_WriteRegister(VBE_DISPI_INDEX_BANK, bank);\r
+}\r
+#endif\r
+\r
+/**\r
+ * \fn void BGA_int_SetMode(Uint16 width, Uint16 height, Uint16 bpp)\r
+ * \brief Sets the video mode from the dimensions and bpp given\r
+ */\r
+void BGA_int_SetMode(Uint16 width, Uint16 height)\r
+{\r
+       ENTER("iwidth iheight ibpp", width, height, bpp);\r
+       BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED);\r
+    BGA_int_WriteRegister(VBE_DISPI_INDEX_XRES,        width);\r
+    BGA_int_WriteRegister(VBE_DISPI_INDEX_YRES,        height);\r
+    BGA_int_WriteRegister(VBE_DISPI_INDEX_BPP, 32);\r
+    BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_NOCLEARMEM | VBE_DISPI_LFB_ENABLED);\r
+    //BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_NOCLEARMEM);\r
+       LEAVE('-');\r
+}\r
+\r
+/**\r
+ * \fn int BGA_int_UpdateMode(int id)\r
+ * \brief Set current vide mode given a mode id\r
+ */\r
+int BGA_int_UpdateMode(int id)\r
+{\r
+       // Sanity Check\r
+       if(id < 0 || id >= BGA_MODE_COUNT)      return -1;\r
+       \r
+       // Check if it is a text mode\r
+       if( gBGA_Modes[id].flags & MODEFLAG_TEXT )\r
+               BGA_int_SetMode(\r
+                       gBGA_Modes[id].width*giVT_CharWidth,\r
+                       gBGA_Modes[id].height*giVT_CharHeight);\r
+       else    // Graphics?\r
+               BGA_int_SetMode(\r
+                       gBGA_Modes[id].width,\r
+                       gBGA_Modes[id].height);\r
+       \r
+       giBGA_CurrentMode = id;\r
+       return id;\r
+}\r
+\r
+/**\r
+ * \fn int BGA_int_FindMode(tVideo_IOCtl_Mode *info)\r
+ * \brief Find a mode matching the given options\r
+ */\r
+int BGA_int_FindMode(tVideo_IOCtl_Mode *info)\r
+{\r
+        int    i;\r
+        int    best = 0, bestFactor = 1000;\r
+        int    factor, tmp;\r
+        int    rqdProduct = info->width * info->height * info->bpp;\r
+       \r
+       ENTER("pinfo", info);\r
+       LOG("info = {width:%i,height:%i,bpp:%i})\n", info->width, info->height, info->bpp);\r
+       \r
+       for(i = 0; i < BGA_MODE_COUNT; i++)\r
+       {\r
+               #if DEBUG >= 2\r
+               LogF("Mode %i (%ix%ix%i), ", i, gBGA_Modes[i].width, gBGA_Modes[i].height, gBGA_Modes[i].bpp);\r
+               #endif\r
+               \r
+               // Check if this mode is the same type as what we want\r
+               if( !(gBGA_Modes[i].flags & MODEFLAG_TEXT) != !(info->flags & VIDEO_FLAG_TEXT) )\r
+                       continue;\r
+               \r
+               // Ooh! A perfect match\r
+               if(gBGA_Modes[i].width == info->width\r
+               && gBGA_Modes[i].height == info->height\r
+               && gBGA_Modes[i].bpp == info->bpp)\r
+               {\r
+                       #if DEBUG >= 2\r
+                       LogF("Perfect!\n");\r
+                       #endif\r
+                       best = i;\r
+                       break;\r
+               }\r
+               \r
+               // If not, how close are we?\r
+               tmp = gBGA_Modes[i].width * gBGA_Modes[i].height * gBGA_Modes[i].bpp;\r
+               tmp -= rqdProduct;\r
+               tmp = tmp < 0 ? -tmp : tmp;     // tmp = ABS(tmp)\r
+               factor = tmp * 100 / rqdProduct;\r
+               \r
+               #if DEBUG >= 2\r
+               LogF("factor = %i\n", factor);\r
+               #endif\r
+               \r
+               if(factor < bestFactor)\r
+               {\r
+                       bestFactor = factor;\r
+                       best = i;\r
+               }\r
+       }\r
+       \r
+       info->id = best;\r
+       info->width = gBGA_Modes[best].width;\r
+       info->height = gBGA_Modes[best].height;\r
+       info->bpp = gBGA_Modes[best].bpp;\r
+       \r
+       info->flags = 0;\r
+       if(gBGA_Modes[best].flags & MODEFLAG_TEXT)\r
+               info->flags |= VIDEO_FLAG_TEXT;\r
+       \r
+       return best;\r
+}\r
+\r
+/**\r
+ * \fn int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info)\r
+ * \brief Get mode information\r
+ */\r
+int BGA_int_ModeInfo(tVideo_IOCtl_Mode *info)\r
+{\r
+       // Sanity Check\r
+       //if( !MM_IsUser( (Uint)info, sizeof(tVideo_IOCtl_Mode) ) ) {\r
+       //      return -EINVAL;\r
+       //}\r
+       \r
+       if(info->id < 0 || info->id >= BGA_MODE_COUNT)  return -1;\r
+       \r
+       info->width = gBGA_Modes[info->id].width;\r
+       info->height = gBGA_Modes[info->id].height;\r
+       info->bpp = gBGA_Modes[info->id].bpp;\r
+       \r
+       info->flags = 0;\r
+       if(gBGA_Modes[info->id].flags & MODEFLAG_TEXT)\r
+               info->flags |= VIDEO_FLAG_TEXT;\r
+       \r
+       return 1;\r
+}\r
+\r
+/**\r
+ * \fn int BGA_int_MapFB(void *Dest)\r
+ * \brief Map the framebuffer into a process's space\r
+ * \param Dest User address to load to\r
+ */\r
+int BGA_int_MapFB(void *Dest)\r
+{\r
+       Uint    i;\r
+       Uint    pages;\r
+       \r
+       // Sanity Check\r
+       if((Uint)Dest > 0xC0000000)     return 0;\r
+       if(gBGA_Modes[giBGA_CurrentMode].bpp < 15)      return 0;       // Only non-pallete modes are supported\r
+       \r
+       // Count required pages\r
+       pages = (gBGA_Modes[giBGA_CurrentMode].fbSize + 0xFFF) >> 12;\r
+       \r
+       // Check if there is space\r
+       for( i = 0; i < pages; i++ )\r
+       {\r
+               if(MM_GetPhysAddr( (Uint)Dest + (i << 12) ))\r
+                       return 0;\r
+       }\r
+       \r
+       // Map\r
+       for( i = 0; i < pages; i++ )\r
+               MM_Map( (Uint)Dest + (i<<12), VBE_DISPI_LFB_PHYSICAL_ADDRESS + (i<<12) );\r
+       \r
+       return 1;\r
+}\r
index c662f14..d96008d 100644 (file)
@@ -10,6 +10,7 @@ typedef void (*tPacketCallback)(tAdapter *Interface, tMacAddr From, int Length,
 
 extern void    Link_RegisterType(Uint16 Type, tPacketCallback Callback);
 extern void    Link_SendPacket(tAdapter *Interface, Uint16 Type, tMacAddr To, int Length, void *Buffer);
+extern void    Link_WatchDevice(tAdapter *Adapter);
 
 // === INTERNAL ===
 typedef struct sEthernetHeader tEthernetHeader;
index 051d064..5a250fb 100644 (file)
@@ -5,6 +5,7 @@
 #define DEBUG  0
 #define VERSION        ((0<<8)|10)
 #include "ipstack.h"
+#include "link.h"
 #include <modules.h>
 #include <fs_devfs.h>
 #include <tpl_drv_common.h>
@@ -31,12 +32,14 @@ tDevFS_Driver       gIP_DriverInfo = {
        .ACLs = &gVFS_ACL_EveryoneRX,
        .Flags = VFS_FFLAG_DIRECTORY,
        .ReadDir = IPStack_ReadDir,
-       .FindDir = IPStack_FindDir
+       .FindDir = IPStack_FindDir,
+       .IOCtl = IPStack_IOCtl
        }
 };
  int   glIP_Interfaces = 0;
 tInterface     *gIP_Interfaces = NULL;
 tInterface     *gIP_Interfaces_Last = NULL;
+ int   giIP_NextIfaceId = 1;
  int   glIP_Adapters = 0;
 tAdapter       *gIP_Adapters = NULL;
 
@@ -63,6 +66,8 @@ int IPStack_Install(char **Arguments)
                }
        }
        
+       DevFS_AddDevice( &gIP_DriverInfo );
+       
        return 1;
 }
 
@@ -72,22 +77,33 @@ int IPStack_Install(char **Arguments)
 char *IPStack_ReadDir(tVFS_Node *Node, int Pos)
 {
        tInterface      *iface;
-       char    name[5] = "ip0\0\0";
+       char    name[] = "ip0\0\0\0";
+       ENTER("pNode iPos", Node, Pos);
+       
+       // Traverse the list
+       for( iface = gIP_Interfaces; iface && Pos--; iface = iface->Next ) ;
+       
+       // Did we run off the end?
+       if(!iface) {
+               LEAVE('n');
+               return NULL;
+       }
        
        // Create the name
+       Pos = iface->Node.ImplInt;
        if(Pos < 10)
                name[2] = '0' + Pos;
-       else {
+       else if(Pos < 100) {
                name[2] = '0' + Pos/10;
                name[3] = '0' + Pos%10;
        }
+       else {
+               name[2] = '0' + Pos/100;
+               name[3] = '0' + (Pos/10)%10;
+               name[4] = '0' + Pos%10;
+       }
        
-       // Traverse the list
-       for( iface = gIP_Interfaces; iface && Pos--; iface = iface->Next ) ;
-       
-       // Did we run off the end?
-       if(!iface)      return NULL;
-       
+       LEAVE('s', name);
        // Return the pre-generated name
        return strdup(name);
 }
@@ -97,27 +113,38 @@ char *IPStack_ReadDir(tVFS_Node *Node, int Pos)
  */
 tVFS_Node *IPStack_FindDir(tVFS_Node *Node, char *Name)
 {
-        int    i;
-        tInterface     *iface;
+        int    i, num;
+       tInterface      *iface;
        
-       if(Name[0] != 'i' || Name[1] != 'p')    return NULL;
-       if(Name[2] < '0' || Name[2] > '9')      return NULL;
+       ENTER("pNode sName", Node, Name);
        
-       if(Name[3] == '\0') {
-               i = Name[2] - '0';
-               for( iface = gIP_Interfaces; iface && i--; iface = iface->Next ) ;
-               if(!iface)      return NULL;
-               return &iface->Node;
+       if(Name[0] != 'i' || Name[1] != 'p') {
+               LEAVE('n');
+               return NULL;
        }
        
-       if(Name[3] < '0' || Name[3] > '9')      return NULL;
-       
-       i = (Name[2] - '0')*10;
-       i += Name[3] - '0';
+       i = 2;  num = 0;
+       while('0' <= Name[i] && Name[i] <= '9')
+       {
+               num *= 10;
+               num += Name[i] - '0';
+               i ++;
+       }
+       if(Name[i] != '\0') {
+               LEAVE('n');
+               return NULL;
+       }
        
-       for( iface = gIP_Interfaces; iface && i--; iface = iface->Next ) ;
-       if(!iface)      return NULL;
-       return &iface->Node;
+       for( iface = gIP_Interfaces; iface; iface = iface->Next )
+       {
+               if( iface->Node.ImplInt == num )
+               {
+                       LEAVE('p', &iface->Node);
+                       return &iface->Node;
+               }
+       }
+       LEAVE('p', NULL);
+       return NULL;
 }
 
 static const char *casIOCtls_Root[] = { DRV_IOCTLNAMES, "add_interface", NULL };
@@ -134,27 +161,35 @@ static const char *casIOCtls_Iface[] = {
  */
 int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data)
 {
+        int    tmp;
+       ENTER("pNode iID pData", Node, ID, Data);
+       
        switch(ID)
        {
        // --- Standard IOCtls (0-3) ---
        case DRV_IOCTL_TYPE:
+               LEAVE('i', DRV_TYPE_MISC);
                return DRV_TYPE_MISC;
        
        case DRV_IOCTL_IDENT:
-               if( !CheckMem( Data, 4 ) )      return -1;
+               if( !CheckMem( Data, 4 ) )      LEAVE_RET('i', -1);
                memcpy(Data, "IP\0\0", 4);
+               LEAVE('i', 1);
                return 1;
        
        case DRV_IOCTL_VERSION:
+               LEAVE('x', VERSION);
                return VERSION;
        
        case DRV_IOCTL_LOOKUP:
-               if( !CheckString( Data ) )      return -1;
-               
+               if( !CheckString( Data ) )      LEAVE_RET('i', -1);
+               LOG("Lookup '%s'", Data);
                if( Node == &gIP_DriverInfo.RootNode )
-                       return LookupString( (char**)casIOCtls_Root, (char*)Data );
+                       tmp = LookupString( (char**)casIOCtls_Root, (char*)Data );
                else
-                       return LookupString( (char**)casIOCtls_Iface, (char*)Data );
+                       tmp = LookupString( (char**)casIOCtls_Iface, (char*)Data );
+               LEAVE('i', tmp);
+               return tmp;
        }
        
        if(Node == &gIP_DriverInfo.RootNode)
@@ -166,10 +201,12 @@ int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data)
                 * - Adds a new IP interface and binds it to a device
                 */
                case 4:
-                       if( Threads_GetUID() != 0 )     return -1;
-                       if( !CheckString( Data ) )      return -1;
-                       return IPStack_AddInterface(Data);
+                       if( Threads_GetUID() != 0 )     LEAVE_RET('i', -1);
+                       if( !CheckString( Data ) )      LEAVE_RET('i', -1);
+                       tmp = IPStack_AddInterface(Data);
+                       LEAVE_RET('i', tmp);
                }
+               LEAVE('i', 0);
                return 0;       
        }
        else
@@ -182,29 +219,41 @@ int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data)
                 * - Get/Set the interface type
                 */
                case 4:
-                       // Get Type?
-                       if( !Data )     return iface->Type;
-                       // Ok, it's set type
-                       if( Threads_GetUID() != 0 )     return -1;
-                       if( !CheckMem( Data, sizeof(int) ) )    return -1;
-                       switch( *(int*)Data )
+                       // Set Type?
+                       if( Data )
                        {
-                       case 0: // Disable
-                               iface->Type = 0;
-                               memset(&iface->IP6, 0, sizeof(tIPv6));  // Clear address
-                               break;
-                       case 4: // IPv4
-                               iface->Type = 4;
-                               memset(&iface->IP4, 0, sizeof(tIPv4));
-                               break;
-                       case 6: // IPv6
-                               iface->Type = 6;
-                               memset(&iface->IP6, 0, sizeof(tIPv6));
-                               break;
-                       default:
-                               return -1;
+                               // Ok, it's set type
+                               if( Threads_GetUID() != 0 ) {
+                                       LOG("Attempt by non-root to alter an interface (%i)", Threads_GetUID());
+                                       LEAVE('i', -1);
+                                       return -1;
+                               }
+                               if( !CheckMem( Data, sizeof(int) ) ) {
+                                       LOG("Invalid pointer %p", Data);
+                                       LEAVE('i', -1);
+                                       return -1;
+                               }
+                               switch( *(int*)Data )
+                               {
+                               case 0: // Disable
+                                       iface->Type = 0;
+                                       memset(&iface->IP6, 0, sizeof(tIPv6));  // Clear address
+                                       break;
+                               case 4: // IPv4
+                                       iface->Type = 4;
+                                       memset(&iface->IP4, 0, sizeof(tIPv4));
+                                       break;
+                               case 6: // IPv6
+                                       iface->Type = 6;
+                                       memset(&iface->IP6, 0, sizeof(tIPv6));
+                                       break;
+                               default:
+                                       LEAVE('i', -1);
+                                       return -1;
+                               }
                        }
-                       return 0;
+                       LEAVE('i', iface->Type);
+                       return iface->Type;
                
                /*
                 * get_address
@@ -213,41 +262,41 @@ int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data)
                case 5:
                        switch(iface->Type)
                        {
-                       case 0: return 1;
+                       case 0: LEAVE_RET('i', 1);
                        case 4:
-                               if( !CheckMem( Data, sizeof(tIPv4) ) )  return -1;
-                               memcpy( Data, &iface->IP4, sizeof(tIPv4) );
-                               return 1;
+                               if( !CheckMem( Data, sizeof(tIPv4) ) )  LEAVE_RET('i', -1);
+                               memcpy( Data, &iface->IP4.Address, sizeof(tIPv4) );
+                               LEAVE_RET('i', 1);
                        case 6:
-                               if( !CheckMem( Data, sizeof(tIPv6) ) )  return -1;
-                               memcpy( Data, &iface->IP6, sizeof(tIPv6) );
-                               return 1;
+                               if( !CheckMem( Data, sizeof(tIPv6) ) )  LEAVE_RET('i', -1);
+                               memcpy( Data, &iface->IP6.Address, sizeof(tIPv6) );
+                               LEAVE_RET('i', 1);
                        }
-                       return 0;
+                       LEAVE_RET('i', 0);
                
                /*
                 * set_address
                 * - Get the interface's address
                 */
                case 6:
-                       if( Threads_GetUID() != 0 )     return -1;
+                       if( Threads_GetUID() != 0 )     LEAVE_RET('i', -1);
                        switch(iface->Type)
                        {
-                       case 0: return 1;
+                       case 0: LEAVE_RET('i', 1);
                        case 4:
-                               if( !CheckMem( Data, sizeof(tIPv4) ) )  return -1;
+                               if( !CheckMem( Data, sizeof(tIPv4) ) )  LEAVE_RET('i', -1);
                                iface->Type = 0;        // One very hacky mutex/trash protector
-                               memcpy( &iface->IP4, Data, sizeof(tIPv4) );
+                               memcpy( &iface->IP4.Address, Data, sizeof(tIPv4) );
                                iface->Type = 4;
-                               return 1;
+                               LEAVE_RET('i', 1);
                        case 6:
-                               if( !CheckMem( Data, sizeof(tIPv6) ) )  return -1;
+                               if( !CheckMem( Data, sizeof(tIPv6) ) )  LEAVE_RET('i', -1);
                                iface->Type = 0;
-                               memcpy( &iface->IP6, Data, sizeof(tIPv6) );
+                               memcpy( &iface->IP6.Address, Data, sizeof(tIPv6) );
                                iface->Type = 6;
-                               return 1;
+                               LEAVE_RET('i', 1);
                        }
-                       return 0;
+                       LEAVE_RET('i', 0);
                
                /*
                 * getset_subnet
@@ -259,35 +308,79 @@ int IPStack_IOCtl(tVFS_Node *Node, int ID, void *Data)
                        {
                                switch( iface->Type )
                                {
-                               case 4:         return iface->IP4.SubnetBits;
-                               case 6:         return iface->IP6.SubnetBits;
-                               default:        return 0;
+                               case 4:         LEAVE_RET('i', iface->IP4.SubnetBits);
+                               case 6:         LEAVE_RET('i', iface->IP6.SubnetBits);
+                               default:        LEAVE_RET('i', 0);
                                }
                        }
                        
                        // Ok, set.
-                       if( Threads_GetUID() != 0 )     return -1;
-                       if( !CheckMem(Data, sizeof(int)) )      return -1;
+                       if( Threads_GetUID() != 0 )     LEAVE_RET('i', -1);
+                       if( !CheckMem(Data, sizeof(int)) )      LEAVE_RET('i', -1);
                        
                        // Check and set the subnet bits
                        switch( iface->Type )
                        {
                        case 4:
-                               if( *(int*)Data < 0 || *(int*)Data > 31 )       return -1;
+                               if( *(int*)Data < 0 || *(int*)Data > 31 )       LEAVE_RET('i', -1);
                                iface->IP4.SubnetBits = *(int*)Data;
-                               return iface->IP4.SubnetBits;
+                               LEAVE_RET('i', iface->IP4.SubnetBits);
                        case 6:
-                               if( *(int*)Data < 0 || *(int*)Data > 127 )      return -1;
+                               if( *(int*)Data < 0 || *(int*)Data > 127 )      LEAVE_RET('i', -1);
                                iface->IP6.SubnetBits = *(int*)Data;
-                               return iface->IP6.SubnetBits;
+                               LEAVE_RET('i', iface->IP6.SubnetBits);
                        default:
                                break;
                        }
                        
+                       LEAVE('i', 0);
+                       return 0;
+                       
+               /*
+                * get_gateway
+                * - Get the interface's IPv4 gateway
+                */
+               case 8:
+                       switch(iface->Type)
+                       {
+                       case 0:
+                               LEAVE_RET('i', 1);
+                       case 4:
+                               if( !CheckMem( Data, sizeof(tIPv4) ) )  LEAVE_RET('i', -1);
+                               memcpy( Data, &iface->IP4.Gateway, sizeof(tIPv4) );
+                               LEAVE_RET('i', 1);
+                       case 6:
+                               LEAVE_RET('i', 1);
+                       }
+                       LEAVE('i', 0);
                        return 0;
+               
+               /*
+                * set_gateway
+                * - Get the interface's IPv4 gateway
+                */
+               case 9:
+                       if( Threads_GetUID() != 0 )     LEAVE_RET('i', -1);
+                       switch(iface->Type)
+                       {
+                       case 0:
+                               LEAVE_RET('i', 1);
+                       
+                       case 4:
+                               if( !CheckMem( Data, sizeof(tIPv4) ) )  LEAVE_RET('i', -1);
+                               iface->Type = 0;        // One very hacky mutex/trash protector
+                               memcpy( &iface->IP4.Gateway, Data, sizeof(tIPv4) );
+                               iface->Type = 4;
+                               LEAVE_RET('i', 1);
+                               
+                       case 6:
+                               LEAVE_RET('i', 1);
+                       }
+                       LEAVE_RET('i', 0);
                }
        }
        
+       LEAVE('i', 0);
        return 0;
 }
 
@@ -300,24 +393,33 @@ int IPStack_AddInterface(char *Device)
 {
        tInterface      *iface;
        
+       ENTER("sDevice", Device);
+       
        iface = malloc(sizeof(tInterface));
-       if(!iface)      return -2;      // Return ERR_MYBAD
+       if(!iface) {
+               LEAVE('i', -2);
+               return -2;      // Return ERR_MYBAD
+       }
        
        iface->Next = NULL;
        iface->Type = 0;        // Unset type
        
        // Create Node
+       iface->Node.ImplPtr = iface;
+       iface->Node.ImplInt = giIP_NextIfaceId++;
        iface->Node.Flags = VFS_FFLAG_DIRECTORY;
        iface->Node.Size = 0;
        iface->Node.NumACLs = 1;
        iface->Node.ACLs = &gVFS_ACL_EveryoneRX;
        iface->Node.ReadDir = NULL;
        iface->Node.FindDir = NULL;
+       iface->Node.IOCtl = IPStack_IOCtl;
        
        // Get adapter handle
        iface->Adapter = IPStack_GetAdapter(Device);
        if( !iface->Adapter ) {
                free( iface );
+               LEAVE('i', -1);
                return -1;      // Return ERR_YOUFAIL
        }
        
@@ -333,8 +435,11 @@ int IPStack_AddInterface(char *Device)
        }
        RELEASE( &glIP_Interfaces );
        
+       gIP_DriverInfo.RootNode.Size ++;
+       
        // Success!
-       return 1;
+       LEAVE('i', iface->Node.ImplInt);
+       return iface->Node.ImplInt;
 }
 
 /**
@@ -344,6 +449,9 @@ int IPStack_AddInterface(char *Device)
 tAdapter *IPStack_GetAdapter(char *Path)
 {
        tAdapter        *dev;
+        int    tmp;
+       
+       ENTER("sPath", Path);
        
        LOCK( &glIP_Adapters );
        
@@ -353,6 +461,7 @@ tAdapter *IPStack_GetAdapter(char *Path)
                if( strcmp(dev->Device, Path) == 0 ) {
                        dev->NRef ++;
                        RELEASE( &glIP_Adapters );
+                       LEAVE('p', dev);
                        return dev;
                }
        }
@@ -361,6 +470,7 @@ tAdapter *IPStack_GetAdapter(char *Path)
        dev = malloc( sizeof(tAdapter) + strlen(Path) + 1 );
        if(!dev) {
                RELEASE( &glIP_Adapters );
+               LEAVE('n');
                return NULL;
        }
        
@@ -373,15 +483,19 @@ tAdapter *IPStack_GetAdapter(char *Path)
        if( dev->DeviceFD == -1 ) {
                free( dev );
                RELEASE( &glIP_Adapters );
+               LEAVE('n');
                return NULL;
        }
        
        // Check that it is a network interface
-       if( VFS_IOCtl(dev->DeviceFD, 0, NULL) != DRV_TYPE_NETWORK ) {
+       tmp = VFS_IOCtl(dev->DeviceFD, 0, NULL);
+       LOG("Device type = %i", tmp);
+       if( tmp != DRV_TYPE_NETWORK ) {
                Warning("IPStack_GetAdapter: '%s' is not a network interface", dev->Device);
                VFS_Close( dev->DeviceFD );
                free( dev );
                RELEASE( &glIP_Adapters );
+               LEAVE('n');
                return NULL;
        }
        
@@ -393,5 +507,10 @@ tAdapter *IPStack_GetAdapter(char *Path)
        gIP_Adapters = dev;
        
        RELEASE( &glIP_Adapters );
+       
+       // Start watcher
+       Link_WatchDevice( dev );
+       
+       LEAVE('p', dev);
        return dev;
 }
index a9a6d8d..2484610 100644 (file)
@@ -5,7 +5,7 @@
 -include ../../Makefile.cfg
 
 CPPFLAGS = -I../../Kernel/include -I../../Kernel/arch/$(ARCHDIR)/include -DARCH=$(ARCH)
-CFLAGS = -Wall -Werror $(CPPFLAGS)
+CFLAGS = -Wall -Werror -fno-stack-protector $(CPPFLAGS)
 
 OBJ := $(addsuffix .$(ARCH),$(OBJ))
 BIN = ../$(NAME).kmd.$(ARCH)
@@ -19,12 +19,13 @@ DEPFILES := $(DEPFILES:%.o.$(ARCH)=%.d.$(ARCH))
 all: $(BIN)
 
 clean:
-       $(RM) $(BIN) $(KOBJ) $(OBJ) $(DEPFILES)
+       $(RM) $(BIN) $(BIN).dsm $(KOBJ) $(OBJ) $(DEPFILES)
 
 $(BIN): $(OBJ)
        @echo --- $(LD) -o $@
        @$(LD) -T ../link.ld -shared -nostdlib -o $@ $(OBJ)
 #      @$(LD) -shared -nostdlib -o $@ $(OBJ)
+       @$(OBJDUMP) -d $(BIN) > $(BIN).dsm
        cp $@ $(DISTROOT)/Modules/$(NAME).kmd
        @echo --- $(LD) -o $(KOBJ)
        @$(CC) -Wl,-r -nostdlib -o $(KOBJ) $(OBJ)
index 225a021..3717a99 100644 (file)
@@ -9,6 +9,7 @@
 #include <modules.h>
 #include <fs_devfs.h>
 #include <drv_pci.h>
+#include <tpl_drv_network.h>
 
 // === CONSTANTS ===
 #define        MEM_START       0x40
@@ -91,7 +92,8 @@ tDevFS_Driver gNe2k_DriverInfo = {
        .ACLs = &gVFS_ACL_EveryoneRX,
        .Flags = VFS_FFLAG_DIRECTORY,
        .ReadDir = Ne2k_ReadDir,
-       .FindDir = Ne2k_FindDir
+       .FindDir = Ne2k_FindDir,
+       .IOCtl = Ne2k_IOCtl
        }
 };
 Uint16 gNe2k_BaseAddress;
@@ -233,30 +235,56 @@ static const char *casIOCtls[] = { DRV_IOCTLNAMES, DRV_NETWORK_IOCTLNAMES, NULL
  */
 int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data)
 {
+        int    tmp;
+       ENTER("pNode iID pData", Node, ID, Data);
        switch( ID )
        {
-       case DRV_IOCTL_TYPE:    return DRV_TYPE_NETWORK;
+       case DRV_IOCTL_TYPE:
+               LEAVE('i', DRV_TYPE_NETWORK);
+               return DRV_TYPE_NETWORK;
+       
        case DRV_IOCTL_IDENT:
-               if(!CheckMem(Data, 4))  return -1;
+               if(!CheckMem(Data, 4)) {
+                       LEAVE('i', -1);
+                       return -1;
+               }
                memcpy(Data, "NE2K", 4);
+               LEAVE('i', 1);
                return 1;
-       case DRV_IOCTL_VERSION: return VERSION;
+       
+       case DRV_IOCTL_VERSION:
+               LEAVE('x', VERSION);
+               return VERSION;
+       
        case DRV_IOCTL_LOOKUP:
-               if(!CheckString(Data))  return -1;
-               return LookupString( casIOCtls, Data );
+               if( !CheckString(Data) ) {
+                       LEAVE('i', -1);
+                       return -1;
+               }
+               tmp = LookupString( (char**)casIOCtls, Data );
+               LEAVE('i', tmp);
+               return tmp;
        }
        
        // If this is the root, return
-       if( Node == &gNe2k_DriverInfo.Node )    return 0;
+       if( Node == &gNe2k_DriverInfo.RootNode ) {
+               LEAVE('i', 0);
+               return 0;
+       }
        
        // Device specific settings
        switch( ID )
        {
        case NET_IOCTL_GETMAC:
-               if(!CheckMem(Data, 6))  return -1;
+               if( !CheckMem(Data, 6) ) {
+                       LEAVE('i', -1);
+                       return -1;
+               }
                memcpy( Data, ((tCard*)Node->ImplPtr)->MacAddr, 6 );
+               LEAVE('i', 1);
                return 1;
        }
+       LEAVE('i', 0);
        return 0;
 }
 
diff --git a/Usermode/Applications/ifconfig_src/Makefile b/Usermode/Applications/ifconfig_src/Makefile
new file mode 100644 (file)
index 0000000..75e9519
--- /dev/null
@@ -0,0 +1,27 @@
+# Project: ifconfig\r
+\r
+-include ../Makefile.cfg\r
+\r
+COBJ = main.o
+BIN = ../ifconfig\r
+\r
+CFLAGS  += -Wall -fno-builtin -fno-stack-protector\r
+LDFLAGS += \r
+\r
+.PHONY : all clean\r
+\r
+all: $(BIN)\r
+\r
+$(BIN): $(COBJ)\r
+       @echo --- $(LD) -o $@\r
+       @$(LD) $(LDFLAGS) -o $@ $(COBJ) -Map Map.txt\r
+       @objdump -d $(BIN) > $(BIN).dsm\r
+       cp $(BIN) $(DISTROOT)/Bin/
+\r
+clean:\r
+       @$(RM) $(COBJ) $(BIN) $(BIN).dsm Map.txt
+\r
+$(COBJ): %.o: %.c\r
+       @echo --- GCC -o $@
+       @$(CC) $(CFLAGS) -c $? -o $@
+\r
diff --git a/Usermode/Applications/ifconfig_src/main.c b/Usermode/Applications/ifconfig_src/main.c
new file mode 100644 (file)
index 0000000..47798a8
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Acess2 IFCONFIG command
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <acess/sys.h>
+
+// === CONSTANTS ===
+#define FILENAME_MAX   255
+#define IPSTACK_ROOT   "/Devices/ip"
+
+// === PROTOTYPES ===
+void   PrintUsage(char *ProgName);
+void   DumpInterfaces( int DumpAll );
+ int   AddInterface( char *Address );
+ int   DoAutoConfig( char *Device );
+
+// === CODE ===
+/**
+ * \fn int main(int argc, char *argv[])
+ * \brief Entrypoint
+ */
+int main(int argc, char *argv[])
+{
+       if(argc == 1) {
+               DumpInterfaces(0);
+               return 0;
+       }
+       
+       if( strcmp(argv[1], "add") == 0 ) {
+               if( argc < 3 ) {
+                       fprintf(stderr, "ERROR: `add` requires an argument\n");
+                       PrintUsage(argv[0]);
+                       return 0;
+               }
+               return AddInterface( argv[2] );
+       }
+       
+       if( strcmp(argv[1], "autoconf") == 0 ) {
+               DoAutoConfig(argv[2]);
+       }
+       
+       return 0;
+}
+
+void PrintUsage(char *ProgName)
+{
+       fprintf(stderr, "Usage: %s [add <ipaddr>]\n", ProgName);
+}
+
+void DumpInterfaces(int DumpAll)
+{
+        int    dp, fd;
+        int    type;
+       char    path[sizeof(IPSTACK_ROOT)+1+FILENAME_MAX] = IPSTACK_ROOT"/";
+       char    *filename = &path[sizeof(IPSTACK_ROOT)];
+       
+       dp = open(IPSTACK_ROOT, OPENFLAG_READ);
+       
+       while( readdir(dp, filename) )
+       {
+               if(filename[0] == '.')  continue;
+               if(filename[0] != 'i' || filename[1] != 'p')    continue;
+               
+               fd = open(path, OPENFLAG_READ);
+               if(fd == -1) {
+                       printf("%s:\tUnable to open ('%s'\n\n", filename, path);
+               }
+               
+               type = ioctl(fd, 4, NULL);
+               
+               printf("%s:\t", filename);
+               switch(type)
+               {
+               case 0:
+                       printf("DISABLED\n");
+                       break;
+               case 4:
+                       {
+                       uint8_t ip[4];
+                        int    subnet;
+                       printf("IPv4\n");
+                       ioctl(fd, 5, ip);       // Get IP Address
+                       subnet = ioctl(fd, 7, NULL);    // Get Subnet Bits
+                       printf("\t%i.%i.%i.%i/%i\n", ip[0], ip[1], ip[2], ip[3], subnet);
+                       ioctl(fd, 8, ip);       // Get Gateway
+                       printf("\tGateway: %i.%i.%i.%i\n", ip[0], ip[1], ip[2], ip[3]);
+                       }
+                       break;
+               case 6:
+                       {
+                       uint16_t        ip[8];
+                        int    subnet;
+                       printf("IPv6\n");
+                       ioctl(fd, 5, ip);       // Get IP Address
+                       subnet = ioctl(fd, 7, NULL);    // Get Subnet Bits
+                       printf("\t%x:%x:%x:%x:%x:%x:%x:%x/%i\n",
+                               ip[0], ip[1], ip[2], ip[3],
+                               ip[4], ip[5], ip[6], ip[7],
+                               subnet);
+                       }
+                       break;
+               default:
+                       printf("UNKNOWN\n");
+                       break;
+               }
+               printf("\n");
+                       
+               close(fd);
+       }
+       
+       close(dp);
+}
+
+int AddInterface( char *Device )
+{
+        int    dp, ret;
+       
+       dp = open(IPSTACK_ROOT, OPENFLAG_READ);
+       ret = ioctl(dp, 4, Device);
+       close(dp);
+       
+       if( ret < 0 ) {
+               fprintf(stderr, "Unable to add '%s' as a network interface\n", Device);
+               return -1;
+       }
+       
+       printf("-- Added '"IPSTACK_ROOT"/ip%i' using device %s\n", ret, Device);
+       
+       return ret;
+}
+
+int DoAutoConfig( char *Device )
+{
+        int    tmp, fd;
+       char    path[sizeof(IPSTACK_ROOT)+5+1]; // ip000
+       uint8_t addr[4] = {192,168,1,39};
+       uint8_t gw[4] = {192,168,1,1};
+       
+       tmp = AddInterface(Device);
+       if( tmp < 0 )   return tmp;
+       
+       sprintf(path, IPSTACK_ROOT"/ip%i", tmp);
+       
+       fd = open(path, OPENFLAG_READ);
+       if( fd == -1 ) {
+               fprintf(stderr, "Unable to open '%s'\n", path);
+               return -1;
+       }
+       
+       tmp = 4;        // IPv4
+       tmp = ioctl(fd, ioctl(fd, 3, "getset_type"), &tmp);
+       if( tmp != 4 ) {
+               fprintf(stderr, "Error in setting address type (got %i, expected 4)\n", tmp);
+               return -1;
+       }
+       // Set Address
+       ioctl(fd, ioctl(fd, 3, "set_address"), addr);
+       // Set Subnet
+       tmp = 24;
+       ioctl(fd, ioctl(fd, 3, "getset_subnet"), &tmp);
+       // Set Gateway
+       ioctl(fd, ioctl(fd, 3, "set_gateway"), gw);
+       
+       close(fd);
+       
+       printf("Set address to 192.168.1.39/24 (GW: 192.168.1.1)\n");
+       
+       return 0;
+}

UCC git Repository :: git.ucc.asn.au