Implemented basic disk write support in EXT2.
authorJohn Hodge <[email protected]>
Sun, 11 Oct 2009 01:54:05 +0000 (09:54 +0800)
committerJohn Hodge <[email protected]>
Sun, 11 Oct 2009 01:54:05 +0000 (09:54 +0800)
Fixed Debug_HexDump bug.
Made changes to NE2000 driver (now triplefaults on write, instead of doing nothing

Kernel/arch/x86/time.c
Kernel/debug.c
Kernel/drv/ata_x86.c
Kernel/drv/ne2000.c
Kernel/drvutil.c
Kernel/vfs/fs/ext2.c
Kernel/vfs/open.c

index 9248bd1..adc2d13 100644 (file)
@@ -51,7 +51,7 @@ int Time_Setup()
        outb(0x70, inb(0x70)|0x80);     // Disable NMIs
        
        // Install IRQ Handler
        outb(0x70, inb(0x70)|0x80);     // Disable NMIs
        
        // Install IRQ Handler
-       IRQ_AddHandler(8, Time_Interrupt);
+       //IRQ_AddHandler(8, Time_Interrupt);
        return 0;
 }
 
        return 0;
 }
 
index bf2282f..99a236e 100644 (file)
@@ -311,7 +311,7 @@ void Debug_HexDump(char *Header, void *Data, Uint Length)
                Uint    byte = *cdat;
                LogF("%02x ", byte);
                Length--;
                Uint    byte = *cdat;
                LogF("%02x ", byte);
                Length--;
-               cdat --;
+               cdat ++;
        }
        E9('\n');
 }
        }
        E9('\n');
 }
index e64c65f..540ba2f 100644 (file)
@@ -105,10 +105,12 @@ tVFS_Node *ATA_FindDir(tVFS_Node *Node, char *Name);
 Uint64 ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
 Uint64 ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
  int   ATA_IOCtl(tVFS_Node *Node, int Id, void *Data);
 Uint64 ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
 Uint64 ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
  int   ATA_IOCtl(tVFS_Node *Node, int Id, void *Data);
-// Disk Read
+// Read/Write Interface/Quantiser
 Uint   ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk);
 Uint   ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk);
+Uint   ATA_WriteRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk);
+// Read/Write DMA
  int   ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer);
  int   ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer);
-// Disk Write
+ int   ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer);
 // IRQs
 void   ATA_IRQHandlerPri(int unused);
 void   ATA_IRQHandlerSec(int unused);
 // IRQs
 void   ATA_IRQHandlerPri(int unused);
 void   ATA_IRQHandlerSec(int unused);
@@ -326,7 +328,7 @@ int ATA_ScanDisk(int Disk)
                = node->CTime = now();
        
        node->Read = ATA_ReadFS;
                = node->CTime = now();
        
        node->Read = ATA_ReadFS;
-       //node->Write = ATA_WriteFS;
+       node->Write = ATA_WriteFS;
        node->IOCtl = ATA_IOCtl;
 
 
        node->IOCtl = ATA_IOCtl;
 
 
@@ -590,6 +592,7 @@ void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start
        Part->Node.ImplPtr = Part->Name;
        
        Part->Node.Read = ATA_ReadFS;
        Part->Node.ImplPtr = Part->Name;
        
        Part->Node.Read = ATA_ReadFS;
+       Part->Node.Write = ATA_WriteFS;
        Part->Node.IOCtl = ATA_IOCtl;
        LOG("Made '%s' (&Node=%p)", Part->Name, &Part->Node);
        LEAVE('-');
        Part->Node.IOCtl = ATA_IOCtl;
        LOG("Made '%s' (&Node=%p)", Part->Name, &Part->Node);
        LEAVE('-');
@@ -683,7 +686,30 @@ Uint64 ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
  */
 Uint64 ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
 {
  */
 Uint64 ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
 {
-       return 0;
+        int    disk = Node->Inode >> 8;
+        int    part = Node->Inode & 0xFF;
+       
+       // Raw Disk Access
+       if(part == 0xFF)
+       {
+               if( Offset >= gATA_Disks[disk].Sectors * SECTOR_SIZE )
+                       return 0;
+               if( Offset + Length > gATA_Disks[disk].Sectors*SECTOR_SIZE )
+                       Length = gATA_Disks[disk].Sectors*SECTOR_SIZE - Offset;
+       }
+       // Partition
+       else
+       {
+               if( Offset >= gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE )
+                       return 0;
+               if( Offset + Length > gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE )
+                       Length = gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE - Offset;
+               Offset += gATA_Disks[disk].Partitions[part].Start * SECTOR_SIZE;
+       }
+       
+       Log("ATA_WriteFS: (Node=%p, Offset=0x%llx, Length=0x%llx, Buffer=%p)", Node, Offset, Length, Buffer);
+       Debug_HexDump("ATA_WriteFS", Buffer, Length);
+       return DrvUtil_WriteBlock(Offset, Length, Buffer, ATA_ReadRaw, ATA_WriteRaw, SECTOR_SIZE, disk);
 }
 
 /**
 }
 
 /**
@@ -735,6 +761,41 @@ Uint ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk)
        return done+Count;
 }
 
        return done+Count;
 }
 
+/**
+ * \fn Uint ATA_WriteRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk)
+ */
+Uint ATA_WriteRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk)
+{
+        int    ret;
+       Uint    offset;
+       Uint    done = 0;
+        
+       // Pass straight on to ATA_ReadDMAPage if we can
+       if(Count <= MAX_DMA_SECTORS)
+       {
+               ret = ATA_WriteDMA(Disk, Address, Count, Buffer);
+               if(ret == 0)    return 0;
+               return Count;
+       }
+       
+       // Else we will have to break up the transfer
+       offset = 0;
+       while(Count > MAX_DMA_SECTORS)
+       {
+               ret = ATA_WriteDMA(Disk, Address+offset, MAX_DMA_SECTORS, Buffer+offset);
+               // Check for errors
+               if(ret != 1)    return done;
+               // Change Position
+               done += MAX_DMA_SECTORS;
+               Count -= MAX_DMA_SECTORS;
+               offset += MAX_DMA_SECTORS*SECTOR_SIZE;
+       }
+       
+       ret = ATA_WriteDMA(Disk, Address+offset, Count, Buffer+offset);
+       if(ret != 1)    return 0;
+       return done+Count;
+}
+
 /**
  * \fn int ATA_ReadDMAPage(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
  */
 /**
  * \fn int ATA_ReadDMAPage(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
  */
@@ -801,6 +862,72 @@ int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
        return 1;
 }
 
        return 1;
 }
 
+/**
+ * \fn int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
+ */
+int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
+{
+        int    cont = (Disk>>1)&1;     // Controller ID
+        int    disk = Disk & 1;
+       Uint16  base;
+       
+       // Check if the count is small enough
+       if(Count > MAX_DMA_SECTORS)     return 0;
+       
+       // Get exclusive access to the disk controller
+       LOCK( &giaATA_ControllerLock[ cont ] );
+       
+       // Set Size
+       gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE;
+       
+       // Get Port Base
+       base = ATA_GetBasePort(Disk);
+       
+       // Set up transfer
+       outb(base+0x01, 0x00);
+       if( Address > 0x0FFFFFFF )      // Use LBA48
+       {
+               outb(base+0x6, 0x40 | (disk << 4));
+               outb(base+0x2, 0 >> 8); // Upper Sector Count
+               outb(base+0x3, Address >> 24);  // Low 2 Addr
+               outb(base+0x3, Address >> 28);  // Mid 2 Addr
+               outb(base+0x3, Address >> 32);  // High 2 Addr
+       }
+       else
+       {
+               outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F)); //Disk,Magic,High addr
+       }
+       
+       outb(base+0x02, (Uint8) Count);         // Sector Count
+       outb(base+0x03, (Uint8) Address);               // Low Addr
+       outb(base+0x04, (Uint8) (Address >> 8));        // Middle Addr
+       outb(base+0x05, (Uint8) (Address >> 16));       // High Addr
+       if( Address > 0x0FFFFFFF )
+               outb(base+0x07, HDD_DMA_W48);   // Write Command (LBA48)
+       else
+               outb(base+0x07, HDD_DMA_W28);   // Write Command (LBA28)
+       
+       // Reset IRQ Flag
+       gaATA_IRQs[cont] = 0;
+       
+       // Copy to output buffer
+       memcpy( gATA_Buffers[cont], Buffer, Count*SECTOR_SIZE );
+       
+       // Start transfer
+       ATA_int_BusMasterWriteByte( cont << 3, 1 );     // Write and start
+       
+       // Wait for transfer to complete
+       while( gaATA_IRQs[cont] == 0 )  Threads_Yield();
+       
+       // Complete Transfer
+       ATA_int_BusMasterWriteByte( cont << 3, 0 );     // Write and stop
+       
+       // Release controller lock
+       RELEASE( &giaATA_ControllerLock[ cont ] );
+       
+       return 1;
+}
+
 /**
  * \fn void ATA_IRQHandlerPri(int unused)
  */
 /**
  * \fn void ATA_IRQHandlerPri(int unused)
  */
index c25718a..6fdbe89 100644 (file)
@@ -3,6 +3,7 @@
  * 
  * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc
  */
  * 
  * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc
  */
+#define        DEBUG   1
 #include <common.h>
 #include <modules.h>
 #include <fs_devfs.h>
 #include <common.h>
 #include <modules.h>
 #include <fs_devfs.h>
@@ -143,7 +144,7 @@ int Ne2k_Install(char **Options)
                        outb( base + IMR, 0x00 );
                        outb( base + ISR, 0xFF );
                        outb( base + RCR, 0x20 );       // Reciever to Monitor
                        outb( base + IMR, 0x00 );
                        outb( base + ISR, 0xFF );
                        outb( base + RCR, 0x20 );       // Reciever to Monitor
-                       outb( base + TCR, 0x02 );       // Transmitter OFF
+                       outb( base + TCR, 0x02 );       // Transmitter OFF (TCR.LB = 1, Internal Loopback)
                        outb( base + RBCR0, 6*4 );      // Remote Byte Count
                        outb( base + RBCR1, 0 );
                        outb( base + RSAR0, 0 );        // Clear Source Address
                        outb( base + RBCR0, 6*4 );      // Remote Byte Count
                        outb( base + RBCR1, 0 );
                        outb( base + RSAR0, 0 );        // Clear Source Address
@@ -164,7 +165,7 @@ int Ne2k_Install(char **Options)
                        outb( base+ISR, 0xFF ); // Clear all ints
                        outb( base+CMD, 0x22 ); // No DMA, Start
                        outb( base+IMR, 0x3F ); // Set Interupt Mask
                        outb( base+ISR, 0xFF ); // Clear all ints
                        outb( base+CMD, 0x22 ); // No DMA, Start
                        outb( base+IMR, 0x3F ); // Set Interupt Mask
-                       outb( base+RCR, 0x8F ); // Set WRAP and allow all packet matches
+                       outb( base+RCR, 0x0F ); // Set WRAP and allow all packet matches
                        outb( base+TCR, 0x00 ); // Set Normal Transmitter mode
                        outb( base+TPSR, 0x40); // Set Transmit Start
                        // Set MAC Address
                        outb( base+TCR, 0x00 ); // Set Normal Transmitter mode
                        outb( base+TPSR, 0x40); // Set Transmit Start
                        // Set MAC Address
@@ -231,11 +232,19 @@ Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
        Uint16  *buf = Buffer;
         int    rem = Length;
        
        Uint16  *buf = Buffer;
         int    rem = Length;
        
+       ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
+       
        // Sanity Check Length
        // Sanity Check Length
-       if(Length > TX_BUF_SIZE)        return 0;
+       if(Length > TX_BUF_SIZE) {
+               LEAVE('i', 0);
+               return 0;
+       }
        
        outb(Card->IOBase + CMD, 0|0x22);       // Page 0, Start, NoDMA
        
        outb(Card->IOBase + CMD, 0|0x22);       // Page 0, Start, NoDMA
-       // Send Size
+       // Send Size - Transmit Byte Count Register
+       outb(Card->IOBase + TBCR0, Length & 0xFF);
+       outb(Card->IOBase + TBCR1, Length >> 8);
+       // Send Size - Remote Byte Count Register
        outb(Card->IOBase + RBCR0, Length & 0xFF);
        outb(Card->IOBase + RBCR1, Length >> 8);
        // Clear Remote DMA Flag
        outb(Card->IOBase + RBCR0, Length & 0xFF);
        outb(Card->IOBase + RBCR1, Length >> 8);
        // Clear Remote DMA Flag
@@ -244,12 +253,17 @@ Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
        outb(Card->IOBase + RSAR0, 0x00);       // Page Offset
        outb(Card->IOBase + RSAR1, Ne2k_int_GetWritePage(Card, Length));        // Page Offset
        // Start
        outb(Card->IOBase + RSAR0, 0x00);       // Page Offset
        outb(Card->IOBase + RSAR1, Ne2k_int_GetWritePage(Card, Length));        // Page Offset
        // Start
-       outb(Card->IOBase + CMD, 0|0x12);       // Page 0, Start, DMA
+       outb(Card->IOBase + CMD, 0|0x18|0x4|0x2);       // Page 0, Transmit Packet, TXP, Start
        
        // Send Data
        for(rem = Length; rem; rem -= 2)
                outw(Card->IOBase + 0x10, *buf++);
        
        // Send Data
        for(rem = Length; rem; rem -= 2)
                outw(Card->IOBase + 0x10, *buf++);
-       return 0;
+       
+       // Complete DMA
+       outb(Card->IOBase + CMD, 0|0x20);
+       
+       LEAVE('i', Length);
+       return Length;
 }
 
 /**
 }
 
 /**
index 281ee38..c40a5d2 100644 (file)
@@ -130,7 +130,7 @@ Uint64 DrvUtil_WriteBlock(Uint64 Start, Uint64 Length, void *Buffer,
        // Read central blocks
        if(num)
        {
        // Read central blocks
        if(num)
        {
-               LOG("Reading %i blocks", num);
+               LOG("Writing %i blocks", num);
                ret = WriteBlocks(block, num, Buffer, Argument);
                if(ret != num ) {
                        LEAVE('X', leading + ret * BlockSize);
                ret = WriteBlocks(block, num, Buffer, Argument);
                if(ret != num ) {
                        LEAVE('X', leading + ret * BlockSize);
@@ -141,7 +141,7 @@ Uint64 DrvUtil_WriteBlock(Uint64 Start, Uint64 Length, void *Buffer,
        // Read last tailing block
        if(tailings != 0)
        {
        // Read last tailing block
        if(tailings != 0)
        {
-               LOG("Reading %i bytes from last block", tailings);
+               LOG("Writing %i bytes to last block", tailings);
                block += num;
                Buffer += num * BlockSize;
                // Read
                block += num;
                Buffer += num * BlockSize;
                // Read
index 0c4b527..da941f7 100644 (file)
@@ -270,18 +270,25 @@ Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
        Uint64  allocSize;\r
         int    bNewBlocks = 0;\r
        \r
        Uint64  allocSize;\r
         int    bNewBlocks = 0;\r
        \r
+       Debug_HexDump("Ext2_Write", Buffer, Length);\r
+       \r
        Ext2_int_GetInode(Node, &inode);\r
        \r
        Ext2_int_GetInode(Node, &inode);\r
        \r
-       // Round size up to block size\r
-       // block size is a power of two, so this will work\r
+       // Get the ammount of space already allocated\r
+       // - Round size up to block size\r
+       // - block size is a power of two, so this will work\r
        allocSize = (inode.i_size + disk->BlockSize) & ~(disk->BlockSize-1);\r
        allocSize = (inode.i_size + disk->BlockSize) & ~(disk->BlockSize-1);\r
+       \r
+       // Are we writing to inside the allocated space?\r
        if( Offset < allocSize )\r
        {\r
        if( Offset < allocSize )\r
        {\r
+               // Will we go out of it?\r
                if(Offset + Length > allocSize) {\r
                        bNewBlocks = 1;\r
                        retLen = allocSize - Offset;\r
                } else\r
                        retLen = Length;\r
                if(Offset + Length > allocSize) {\r
                        bNewBlocks = 1;\r
                        retLen = allocSize - Offset;\r
                } else\r
                        retLen = Length;\r
+               \r
                // Within the allocated space\r
                block = Offset / disk->BlockSize;\r
                Offset %= disk->BlockSize;\r
                // Within the allocated space\r
                block = Offset / disk->BlockSize;\r
                Offset %= disk->BlockSize;\r
@@ -290,7 +297,7 @@ Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
                // Write only block (if only one)\r
                if(Offset + retLen <= disk->BlockSize) {\r
                        VFS_WriteAt(disk->FD, base+Offset, retLen, Buffer);\r
                // Write only block (if only one)\r
                if(Offset + retLen <= disk->BlockSize) {\r
                        VFS_WriteAt(disk->FD, base+Offset, retLen, Buffer);\r
-                       if(bNewBlocks)  return Length;\r
+                       if(!bNewBlocks) return Length;\r
                        goto addBlocks; // Ugh! A goto, but it seems unavoidable\r
                }\r
                \r
                        goto addBlocks; // Ugh! A goto, but it seems unavoidable\r
                }\r
                \r
@@ -313,7 +320,7 @@ Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
                // Write last block\r
                base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);\r
                VFS_WriteAt(disk->FD, base, retLen, Buffer);\r
                // Write last block\r
                base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);\r
                VFS_WriteAt(disk->FD, base, retLen, Buffer);\r
-               if(bNewBlocks)  return Length;  // Writing in only allocated space\r
+               if(!bNewBlocks) return Length;  // Writing in only allocated space\r
        }\r
        \r
 addBlocks:\r
        }\r
        \r
 addBlocks:\r
index a1245f3..50641ca 100644 (file)
@@ -365,7 +365,7 @@ tVFS_Node *VFS_ParsePath(char *Path, char **TruePath)
        // Check if file was found
        if(!tmpNode) {
                LOG("Node '%s' not found in dir '%s'", &Path[ofs], Path);
        // Check if file was found
        if(!tmpNode) {
                LOG("Node '%s' not found in dir '%s'", &Path[ofs], Path);
-               Log("Child fail '%s' ('%s')", Path, &Path[ofs]);
+               //Log("Child fail '%s' ('%s')", Path, &Path[ofs]);
                if(TruePath)    free(*TruePath);
                if(curNode->Close)      curNode->Close(curNode);
                LEAVE('n');
                if(TruePath)    free(*TruePath);
                if(curNode->Close)      curNode->Close(curNode);
                LEAVE('n');

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