More work on UDI, cleanup and pseudod should now load.
[tpg/acess2.git] / Modules / NE2000 / ne2000.c
index 225a021..99abbb3 100644 (file)
@@ -3,12 +3,13 @@
  * 
  * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc
  */
-#define        DEBUG   1
+#define        DEBUG   0
 #define VERSION        ((0<<8)|50)
-#include <common.h>
+#include <acess.h>
 #include <modules.h>
 #include <fs_devfs.h>
 #include <drv_pci.h>
+#include <tpl_drv_network.h>
 
 // === CONSTANTS ===
 #define        MEM_START       0x40
@@ -19,6 +20,7 @@
 #define TX_FIRST       (MEM_START+RX_BUF_SIZE)
 #define TX_LAST                (MEM_END)
 #define        TX_BUF_SIZE     0x40
+#define        MAX_PACKET_QUEUE        10
 
 static const struct {
        Uint16  Vendor;
@@ -59,11 +61,18 @@ enum eNe2k_Page0Write {
        IMR             //!< interrupt mask register (init)
 };
 
+enum eNe2k_Page1Read {
+       CURR = 7        //!< current page
+};
+
 // === TYPES ===
 typedef struct sNe2k_Card {
        Uint16  IOBase; //!< IO Port Address from PCI
        Uint8   IRQ;    //!< IRQ Assigned from PCI
        
+        int    NumWaitingPackets;
+        int    NextRXPage;
+       
         int    NextMemPage;    //!< Next Card Memory page to use
        
        Uint8   Buffer[RX_BUF_SIZE];
@@ -79,6 +88,7 @@ char  *Ne2k_ReadDir(tVFS_Node *Node, int Pos);
 tVFS_Node      *Ne2k_FindDir(tVFS_Node *Node, char *Name);
  int   Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data);
 Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
+Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
 Uint8  Ne2k_int_GetWritePage(tCard *Card, Uint16 Length);
 void   Ne2k_IRQHandler(int IntNum);
 
@@ -91,7 +101,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;
@@ -118,8 +129,8 @@ int Ne2k_Install(char **Options)
        
        // Enumerate Cards
        k = 0;
-       gpNe2k_Cards = malloc( giNe2k_CardCount * sizeof(tCard) );
-       memsetd(gpNe2k_Cards, 0, giNe2k_CardCount * sizeof(tCard) / 4);
+       gpNe2k_Cards = calloc( giNe2k_CardCount, sizeof(tCard) );
+       
        for( i = 0; i < NUM_COMPAT_DEVICES; i ++ )
        {
                count = PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0 );
@@ -131,6 +142,7 @@ int Ne2k_Install(char **Options)
                        gpNe2k_Cards[ k ].IOBase = base;
                        gpNe2k_Cards[ k ].IRQ = PCI_GetIRQ( id );
                        gpNe2k_Cards[ k ].NextMemPage = 64;
+                       gpNe2k_Cards[ k ].NextRXPage = RX_FIRST;
                        
                        // Install IRQ Handler
                        IRQ_AddHandler(gpNe2k_Cards[ k ].IRQ, Ne2k_IRQHandler);
@@ -141,6 +153,8 @@ int Ne2k_Install(char **Options)
                        outb( base + ISR, 0x80 );
                        
                        // Initialise Card
+                       outb( base + CMD, 0x40|0x21 );  // Page 1, No DMA, Stop
+                       outb( base + CURR, RX_FIRST );  // Current RX page
                        outb( base + CMD, 0x21 );       // No DMA and Stop
                        outb( base + DCR, 0x49 );       // Set WORD mode
                        outb( base + IMR, 0x00 );
@@ -154,12 +168,12 @@ int Ne2k_Install(char **Options)
                        outb( base + CMD, 0x0A );       // Remote Read, Start
                        
                        // Read MAC Address
-                       gpNe2k_Cards[ k ].MacAddr[0] = inb(base+0x10);  inb(base+0x10);
-                       gpNe2k_Cards[ k ].MacAddr[1] = inb(base+0x10);  inb(base+0x10);
-                       gpNe2k_Cards[ k ].MacAddr[2] = inb(base+0x10);  inb(base+0x10);
-                       gpNe2k_Cards[ k ].MacAddr[3] = inb(base+0x10);  inb(base+0x10);
-                       gpNe2k_Cards[ k ].MacAddr[4] = inb(base+0x10);  inb(base+0x10);
-                       gpNe2k_Cards[ k ].MacAddr[5] = inb(base+0x10);  inb(base+0x10);
+                       gpNe2k_Cards[ k ].MacAddr[0] = inb(base+0x10);//        inb(base+0x10);
+                       gpNe2k_Cards[ k ].MacAddr[1] = inb(base+0x10);//        inb(base+0x10);
+                       gpNe2k_Cards[ k ].MacAddr[2] = inb(base+0x10);//        inb(base+0x10);
+                       gpNe2k_Cards[ k ].MacAddr[3] = inb(base+0x10);//        inb(base+0x10);
+                       gpNe2k_Cards[ k ].MacAddr[4] = inb(base+0x10);//        inb(base+0x10);
+                       gpNe2k_Cards[ k ].MacAddr[5] = inb(base+0x10);//        inb(base+0x10);
                        
                        outb( base+PSTART, RX_FIRST);   // Set Receive Start
                        outb( base+BNRY, RX_LAST-1);    // Set Boundary Page
@@ -195,13 +209,14 @@ int Ne2k_Install(char **Options)
                        gpNe2k_Cards[ k ].Node.NumACLs = 0;     // Root Only
                        gpNe2k_Cards[ k ].Node.CTime = now();
                        gpNe2k_Cards[ k ].Node.Write = Ne2k_Write;
+                       gpNe2k_Cards[ k ].Node.Read = Ne2k_Read;
                        gpNe2k_Cards[ k ].Node.IOCtl = Ne2k_IOCtl;
                }
        }
        
        gNe2k_DriverInfo.RootNode.Size = giNe2k_CardCount;
        DevFS_AddDevice( &gNe2k_DriverInfo );
-       return 0;
+       return 1;
 }
 
 /**
@@ -233,30 +248,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;
 }
 
@@ -303,7 +344,7 @@ Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
        for(rem = Length; rem; rem -= 2)
                outw(Card->IOBase + 0x10, *buf++);
        
-       while( inb(Card->IOBase + ISR) == 0   // Wait for Remote DMA Complete
+       while( inb(Card->IOBase + ISR) == 0 )   // Wait for Remote DMA Complete
                ;       //Proc_Yield();
        
        outb( Card->IOBase + ISR, 0x40 );       // ACK Interrupt
@@ -318,6 +359,106 @@ Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
        return Length;
 }
 
+/**
+ * \fn Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+ * \brief Wait for and read a packet from the network card
+ */
+Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+{
+       tCard   *Card = (tCard*)Node->ImplPtr;
+       Uint8   page;
+       Uint8   data[256];
+        int    i;
+       struct {
+               Uint8   Status;
+               Uint8   NextPacketPage;
+               Uint16  Length; // Little Endian
+       }       *pktHdr;
+       
+       ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
+       
+       while(Card->NumWaitingPackets == 0)     Threads_Yield();
+       
+       // Make sure that the card is in page 0
+       outb(Card->IOBase + CMD, 0|0x22);       // Page 0, Start, NoDMA
+       
+       // Get BOUNDARY
+       page = Card->NextRXPage;
+       
+       // Set up transfer
+       outb(Card->IOBase + RBCR0, 0);
+       outb(Card->IOBase + RBCR1, 1);  // 256-bytes
+       outb(Card->IOBase + RSAR0, 0x00);       // Page Offset
+       outb(Card->IOBase + RSAR1, page);       // Page Number
+       
+       outb(Card->IOBase + CMD, 0|0x08|0x2);   // Page 0, Remote Read, Start
+       
+       // Clear Remote DMA Flag
+       outb(Card->IOBase + ISR, 0x40); // Bit 6
+       
+       // Read data
+       for(i = 0; i < 128; i ++)
+               ((Uint16*)data)[i] = inw(Card->IOBase + 0x10);
+       
+       pktHdr = (void*)data;
+       //Log("Ne2k_Read: Recieved packet (%i bytes)", pktHdr->Length);
+       
+       // Have we read all the required bytes yet?
+       if(pktHdr->Length < 256 - 4)
+       {
+               if(Length > pktHdr->Length)
+                       Length = pktHdr->Length;
+               memcpy(Buffer, &data[4], Length);
+               page ++;
+               if(page == RX_LAST+1)   page = RX_FIRST;
+       }
+       // No? oh damn, now we need to allocate a buffer
+       else {
+                int    j = 256/2;
+               char    *buf = malloc( (pktHdr->Length + 4 + 255) & ~255 );
+               
+               if(!buf) {
+                       LEAVE('i', -1);
+                       return -1;
+               }
+               
+               memcpy(buf, data, 256);
+               
+               page ++;
+               while(page != pktHdr->NextPacketPage)
+               {
+                       if(page == RX_LAST+1)   page = RX_FIRST;
+                       
+                       outb(Card->IOBase + RBCR0, 0);
+                       outb(Card->IOBase + RBCR1, 1);  // 256-bytes
+                       outb(Card->IOBase + RSAR0, 0x00);       // Page Offset
+                       outb(Card->IOBase + RSAR1, page);       // Page Number
+                       outb(Card->IOBase + CMD, 0|0x08|0x2);   // Page 0, Remote Read, Start
+                       
+                       for(i = 0; i < 128; i ++)
+                               ((Uint16*)buf)[j+i] = inw(Card->IOBase + 0x10);
+                       j += 128;
+                       page ++;
+               }
+               
+               if(Length > pktHdr->Length)
+                       Length = pktHdr->Length;
+               memcpy(Buffer, &buf[4], Length);
+       }
+       
+       // Write BNRY
+       if(page == RX_FIRST)
+               outb( Card->IOBase + BNRY, RX_LAST );
+       else
+               outb( Card->IOBase + BNRY, page-1 );
+       // Set next RX Page and decrement the waiting list
+       Card->NextRXPage = page;
+       Card->NumWaitingPackets --;
+       
+       LEAVE('i', Length);
+       return Length;
+}
+
 /**
  * \fn Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length)
  */
@@ -339,10 +480,28 @@ Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length)
 void Ne2k_IRQHandler(int IntNum)
 {
         int    i;
+       Uint8   byte;
        for( i = 0; i < giNe2k_CardCount; i++ )
        {
-               if(gpNe2k_Cards[i].IRQ == IntNum) {
-                       LOG("Clearing interrupts on card %i (0x%x)\n", i, inb( gpNe2k_Cards[i].IOBase + ISR ));
+               if(gpNe2k_Cards[i].IRQ == IntNum)
+               {
+                       byte = inb( gpNe2k_Cards[i].IOBase + ISR );
+                       
+                       // 0: Packet recieved (no error)
+                       if( byte & 1 )
+                       {
+                               gpNe2k_Cards[i].NumWaitingPackets ++;
+                               if( gpNe2k_Cards[i].NumWaitingPackets > MAX_PACKET_QUEUE )
+                                       gpNe2k_Cards[i].NumWaitingPackets = MAX_PACKET_QUEUE;
+                       }
+                       // 1: Packet sent (no error)
+                       // 2: Recieved with error
+                       // 3: Transmission Halted (Excessive Collisions)
+                       // 4: Recieve Buffer Exhausted
+                       // 5: 
+                       // 6: Remote DMA Complete
+                       // 7: Reset
+                       //LOG("Clearing interrupts on card %i (was 0x%x)\n", i, byte);
                        outb( gpNe2k_Cards[i].IOBase + ISR, 0xFF );     // Reset All
                        return ;
                }

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