IPStack - Reworking of network device API
[tpg/acess2.git] / KernelLand / Modules / Network / NE2000 / ne2000.c
index 01f5f1f..c8ea019 100644 (file)
@@ -1,16 +1,16 @@
-/* Acess2
- * NE2000 Driver
+/*
+ * Acess2 NE2000 Driver
+ * - By John Hodge (thePowersGang)
  * 
  * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc
  */
 #define        DEBUG   1
-#define VERSION        ((0<<8)|50)
+#define VERSION        VER2(0,6)
 #include <acess.h>
 #include <modules.h>
-#include <fs_devfs.h>
 #include <drv_pci.h>
-#include <api_drv_network.h>
 #include <semaphore.h>
+#include <IPStack/include/adapters_api.h>
 
 // === CONSTANTS ===
 #define        MEM_START       0x40
@@ -76,18 +76,15 @@ typedef struct sNe2k_Card {
        
         int    NextMemPage;    //!< Next Card Memory page to use
                
-       char    Name[2];        // "0"
-       tVFS_Node       Node;   //!< VFS Node
+       void    *IPStackHandle;
        Uint8   MacAddr[6];     //!< Cached MAC address
 } tCard;
 
 // === PROTOTYPES ===
  int   Ne2k_Install(char **Arguments);
-char   *Ne2k_ReadDir(tVFS_Node *Node, int Pos);
-tVFS_Node      *Ne2k_FindDir(tVFS_Node *Node, const char *Name);
- int   Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data);
-size_t Ne2k_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);
-size_t Ne2k_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
+
+ int   Ne2k_SendPacket(void *Ptr, tIPStackBuffer *Buffer);
+tIPStackBuffer *Ne2k_WaitForPacket(void *Ptr);
 
  int   Ne2k_int_ReadDMA(tCard *Card, int FirstPage, int NumPages, void *Buffer);
 Uint8  Ne2k_int_GetWritePage(tCard *Card, Uint16 Length);
@@ -95,26 +92,13 @@ void        Ne2k_IRQHandler(int IntNum, void *Ptr);
 
 // === GLOBALS ===
 MODULE_DEFINE(0, VERSION, Ne2k, Ne2k_Install, NULL, NULL);
-tVFS_NodeType  gNe2K_RootNodeType = {
-       .ReadDir = Ne2k_ReadDir,
-       .FindDir = Ne2k_FindDir,
-       .IOCtl = Ne2k_IOCtl
-       };
-tVFS_NodeType  gNe2K_DevNodeType = {
-       .Write = Ne2k_Write,
-       .Read = Ne2k_Read,
-       .IOCtl = Ne2k_IOCtl     
-       };
-tDevFS_Driver  gNe2k_DriverInfo = {
-       NULL, "ne2k",
-       {
-       .NumACLs = 1,
-       .ACLs = &gVFS_ACL_EveryoneRX,
-       .Flags = VFS_FFLAG_DIRECTORY,
-       .Type = &gNe2K_RootNodeType
-       }
+tIPStack_AdapterType   gNe2k_AdapterType = {
+       .Name = "Ne2k",
+       .Type = 0,      // TODO: Differentiate differnet wire protos and speeds
+       .Flags = 0,     // TODO: IP checksum offloading, MAC checksum offloading etc
+       .SendPacket = Ne2k_SendPacket,
+       .WaitForPacket = Ne2k_WaitForPacket
 };
-Uint16 gNe2k_BaseAddress;
  int   giNe2k_CardCount = 0;
 tCard  *gpNe2k_Cards = NULL;
 
@@ -136,8 +120,9 @@ int Ne2k_Install(char **Options)
        {
                giNe2k_CardCount += PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device );
        }
-       
        if( giNe2k_CardCount == 0 )     return MODULE_ERR_NOTNEEDED;
+
+       LOG("%i NE2K cards found", giNe2k_CardCount);
        
        // Enumerate Cards
        k = 0;
@@ -146,24 +131,35 @@ int Ne2k_Install(char **Options)
        for( i = 0; i < NUM_COMPAT_DEVICES; i ++ )
        {
                count = PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device );
-               for( j = 0; j < count; j ++,k ++ )
+               for( j = 0; j < count; j ++, k ++ )
                {
+                       tCard   *card = &gpNe2k_Cards[k];
+                       
                        id = PCI_GetDevice( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, j );
                        // Create Structure
                        base = PCI_GetBAR( id, 0 );
-                       gpNe2k_Cards[ k ].IOBase = base;
-                       gpNe2k_Cards[ k ].IRQ = PCI_GetIRQ( id );
-                       gpNe2k_Cards[ k ].NextMemPage = 64;
-                       gpNe2k_Cards[ k ].NextRXPage = RX_FIRST;
+                       LOG("%i: %i/%i id = %i, base = 0x%x", k, i, j, id, base);
+                       if( !(base & 1) ) {
+                               Log_Warning("Ne2k", "PCI %i's BARs are incorrect (BAR0 is not IO)", id);
+                               continue ;
+                       }
+                       base &= ~1;
+                       card->IOBase = base;
+                       card->IRQ = PCI_GetIRQ( id );
+                       card->NextMemPage = 64;
+                       card->NextRXPage = RX_FIRST;
                        
                        // Install IRQ Handler
-                       IRQ_AddHandler(gpNe2k_Cards[ k ].IRQ, Ne2k_IRQHandler, &gpNe2k_Cards[k]);
+                       IRQ_AddHandler(card->IRQ, Ne2k_IRQHandler, &gpNe2k_Cards[k]);
+                       LOG("%i: IRQ %i mapped, IOBase = 0x%x", k, card->IRQ, card->IOBase);
                        
                        // Reset Card
                        outb( base + 0x1F, inb(base + 0x1F) );
-                       while( (inb( base+ISR ) & 0x80) == 0 );
+                       while( (inb( base + ISR ) & 0x80) == 0 );
                        outb( base + ISR, 0x80 );
-                       
+               
+                       LOG("Reset done");
+       
                        // Initialise Card
                        outb( base + CMD, 0x40|0x21 );  // Page 1, No DMA, Stop
                        outb( base + CURR, RX_FIRST );  // Current RX page
@@ -180,12 +176,12 @@ int Ne2k_Install(char **Options)
                        outb( base + RSAR0, 0 );        // Clear Source Address
                        outb( base + RSAR1, 0 );
                        outb( base + CMD, 0x0A );       // Remote Read, Start
-                       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);
+                       card->MacAddr[0] = inb(base+0x10);//    inb(base+0x10);
+                       card->MacAddr[1] = inb(base+0x10);//    inb(base+0x10);
+                       card->MacAddr[2] = inb(base+0x10);//    inb(base+0x10);
+                       card->MacAddr[3] = inb(base+0x10);//    inb(base+0x10);
+                       card->MacAddr[4] = inb(base+0x10);//    inb(base+0x10);
+                       card->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
@@ -198,111 +194,49 @@ int Ne2k_Install(char **Options)
                        outb( base+TPSR, 0x40); // Set Transmit Start
                        
                        Log_Log("Ne2k", "Card %i 0x%04x IRQ%i %02x:%02x:%02x:%02x:%02x:%02x",
-                               k, base, gpNe2k_Cards[ k ].IRQ,
-                               gpNe2k_Cards[k].MacAddr[0], gpNe2k_Cards[k].MacAddr[1],
-                               gpNe2k_Cards[k].MacAddr[2], gpNe2k_Cards[k].MacAddr[3],
-                               gpNe2k_Cards[k].MacAddr[4], gpNe2k_Cards[k].MacAddr[5]
+                               k, base, card->IRQ,
+                               card->MacAddr[0], card->MacAddr[1],
+                               card->MacAddr[2], card->MacAddr[3],
+                               card->MacAddr[4], card->MacAddr[5]
                                );
                        
-                       // Set VFS Node
-                       gpNe2k_Cards[ k ].Name[0] = '0'+k;
-                       gpNe2k_Cards[ k ].Name[1] = '\0';
-                       gpNe2k_Cards[ k ].Node.ImplPtr = &gpNe2k_Cards[ k ];
-                       gpNe2k_Cards[ k ].Node.NumACLs = 0;     // Root Only
-                       gpNe2k_Cards[ k ].Node.CTime = now();
-                       gpNe2k_Cards[ k ].Node.Type = &gNe2K_DevNodeType;
+                       card->IPStackHandle = IPStack_Adapter_Add(&gNe2k_AdapterType, card, card->MacAddr);
                        
                        // Initialise packet semaphore
                        // - Start at zero, no max
-                       Semaphore_Init( &gpNe2k_Cards[k].Semaphore, 0, 0, "NE2000", gpNe2k_Cards[ k ].Name );
+                       char    name[10];
+                       sprintf(name, "%i", k-1);
+                       Semaphore_Init( &card->Semaphore, 0, 0, "NE2000", name );
                }
        }
        
-       gNe2k_DriverInfo.RootNode.Size = giNe2k_CardCount;
-       DevFS_AddDevice( &gNe2k_DriverInfo );
        return MODULE_ERR_OK;
 }
 
-/**
- * \fn char *Ne2k_ReadDir(tVFS_Node *Node, int Pos)
- */
-char *Ne2k_ReadDir(tVFS_Node *Node, int Pos)
-{
-       char    ret[2];
-       if(Pos < 0 || Pos >= giNe2k_CardCount)  return NULL;
-       ret[0] = '0'+Pos;
-       ret[1] = '\0';
-       return strdup(ret);
-}
-
-/**
- * \fn tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, const char *Name)
- */
-tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, const char *Name)
-{
-       if(Name[0] == '\0' || Name[1] != '\0')  return NULL;
-       
-       return &gpNe2k_Cards[ Name[0]-'0' ].Node;
-}
-
-static const char *casIOCtls[] = { DRV_IOCTLNAMES, DRV_NETWORK_IOCTLNAMES, NULL };
-/**
- * \fn int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data)
- * \brief IOCtl calls for a network device
- */
-int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data)
-{
-       ENTER("pNode iID pData", Node, ID, Data);
-       switch( ID )
-       {
-       BASE_IOCTLS(DRV_TYPE_NETWORK, "NE2000", VERSION, casIOCtls);
-       }
-       
-       // If this is the root, return
-       if( Node == &gNe2k_DriverInfo.RootNode ) {
-               LEAVE('i', 0);
-               return 0;
-       }
-       
-       // Device specific settings
-       switch( ID )
-       {
-       case NET_IOCTL_GETMAC:
-               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;
-}
-
 /**
  * \brief Send a packet from the network card
  */
-size_t Ne2k_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
+int Ne2k_SendPacket(void *Ptr, tIPStackBuffer *Buffer)
 {
-       tCard   *Card = (tCard*)Node->ImplPtr;
-       const Uint16    *buf = Buffer;
-        int    rem = Length;
+       tCard   *Card = Ptr;
+        int    length;
         int    page;
        
-       ENTER("pNode XOffset xLength pBuffer", Node, Offset, Length, Buffer);
+       ENTER("pPtr pBuffer", Ptr, Buffer);
        
+       length = IPStack_Buffer_GetLength(Buffer);
+
        // TODO: Lock
        
        // Sanity Check Length
-       if(Length > TX_BUF_SIZE*256) {
+       if(length > TX_BUF_SIZE*256) {
                Log_Warning(
                        "Ne2k",
                        "Ne2k_Write - Attempting to send over TX_BUF_SIZE*256 (%i) bytes (%i)",
-                       TX_BUF_SIZE*256, Length
+                       TX_BUF_SIZE*256, length
                        );
-               LEAVE('i', 0);
-               return 0;
+               LEAVE('i', -1);
+               return -1;
        }
        
        // Make sure that the card is in page 0
@@ -312,23 +246,31 @@ size_t Ne2k_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buff
        outb(Card->IOBase + ISR, 0x40); // Bit 6
        
        // Send Size - Transfer Byte Count Register
-       outb(Card->IOBase + TBCR0, Length & 0xFF);
-       outb(Card->IOBase + TBCR1, Length >> 8);
+       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);
+       outb(Card->IOBase + RBCR0, length & 0xFF);
+       outb(Card->IOBase + RBCR1, length >> 8);
        
        // Set up transfer
        outb(Card->IOBase + RSAR0, 0x00);       // Page Offset
-       page = Ne2k_int_GetWritePage(Card, Length);
+       page = Ne2k_int_GetWritePage(Card, length);
        outb(Card->IOBase + RSAR1, page);       // Page Offset
        // Start
        outb(Card->IOBase + CMD, 0|0x10|0x2);   // Page 0, Remote Write, Start
        
        // Send Data
-       for(rem = Length; rem > 0; rem -= 2) {
-               outw(Card->IOBase + 0x10, *buf++);
+       size_t  buflen;
+       const void      *bufptr;
+       for(int id = -1; (id = IPStack_Buffer_GetBuffer(Buffer, -1, &buflen, &bufptr)) != -1; )
+       {
+               const Uint16    *buf = bufptr;
+               if( buflen & 1 )
+                       Log_Notice("NE2000", "Alignment issue in TX buffer");
+               buflen = (buflen + 1) / 2;
+               while(buflen --)
+                       outw(Card->IOBase + 0x10, *buf++);
        }
        
        while( !(inb(Card->IOBase + ISR) & 0x40) )      // Wait for Remote DMA Complete
@@ -343,31 +285,39 @@ size_t Ne2k_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buff
        // Complete DMA
        //outb(Card->IOBase + CMD, 0|0x20);
        
-       LEAVE('i', Length);
-       return Length;
+       LEAVE('i', 0);
+       return 0;
+}
+
+void _FreeHeapSubBuf(void *Arg, size_t Pre, size_t Post, const void *DataBuf)
+{
+       free(Arg);
 }
 
 /**
  * \brief Wait for and read a packet from the network card
  */
-size_t Ne2k_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
+tIPStackBuffer *Ne2k_WaitForPacket(void *Ptr)
 {
-       tCard   *Card = Node->ImplPtr;
+       tCard   *Card = Ptr;
        Uint8   page;
        Uint8   data[256];
+       void    *buf;
+       tIPStackBuffer  *ret;
        struct {
                Uint8   Status;
                Uint8   NextPacketPage;
                Uint16  Length; // Little Endian
        }       *pktHdr;
        
-       ENTER("pNode XOffset xLength pBuffer", Node, Offset, Length, Buffer);
+       ENTER("pPtr", Ptr);
        
        // Wait for packets
        if( Semaphore_Wait( &Card->Semaphore, 1 ) != 1 )
        {
                // Error or interrupted
-               LEAVE_RET('i', 0);
+               LEAVE('n');
+               return NULL;
        }
        
        outb(Card->IOBase, 0x22 | (1 << 6));    // Page 6
@@ -384,52 +334,60 @@ size_t Ne2k_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
        LOG("pktHdr->Status = 0x%x", pktHdr->Status);
        LOG("pktHdr->NextPacketPage = %i", pktHdr->NextPacketPage);
        LOG("pktHdr->Length = 0x%03x", pktHdr->Length);
-       
+
+       ret = IPStack_Buffer_CreateBuffer(1);
+       if(!ret)        LEAVE_RET('n', NULL);
+       buf = malloc( pktHdr->Length );
+       if(!buf)        LEAVE_RET('n', NULL);
+       IPStack_Buffer_AppendSubBuffer(ret, pktHdr->Length, 0, buf, _FreeHeapSubBuf, buf);
+
        // 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);
+               memcpy(buf, &data[4], pktHdr->Length);
        }
        // No? oh damn, now we need to allocate a buffer
        else
        {
                 int    pages = pktHdr->NextPacketPage - page;
-               char    *buf = malloc( pages*256 );
+               Uint8   *writepos = buf;
+                int    rem_bytes = pktHdr->Length;
                
                LOG("pktHdr->Length (%i) > 256 - 4, allocated buffer %p", pktHdr->Length, buf);
                
-               if(!buf)        LEAVE_RET('i', -1);
                
                // Copy the already read data
-               memcpy(buf, data, 256);
+               memcpy(writepos, data+4, 256-4);
+               writepos += 256-4;
+               rem_bytes -= 256-4;
                
                // Read all the needed pages
                page ++;
                if(page == RX_LAST+1)   page = RX_FIRST;
-               
-               if( page + pages > RX_LAST )
+
+               // - Body Pages
+               if( pages > 2 )
                {
-                        int    first_count = RX_LAST+1 - page;
-                        int    tmp = 0;
-                       tmp += Ne2k_int_ReadDMA(Card, page, first_count, buf+256);
-                       tmp += Ne2k_int_ReadDMA(Card, RX_FIRST, pages-1-first_count, buf+(first_count+1)*256);
-                       LOG("composite return count = %i", tmp);
+                       if( page + pages - 2 > RX_LAST )
+                       {
+                                int    first_count = RX_LAST - page + 1;
+                               Ne2k_int_ReadDMA(Card, page, first_count, writepos);
+                               Ne2k_int_ReadDMA(Card, RX_FIRST, pages-2-first_count, writepos + first_count*256);
+                               writepos += (pages-2-first_count) * 256;
+                       }
+                       else
+                               Ne2k_int_ReadDMA(Card, page, pages - 2, writepos);
+                       page += pages - 2;
+                       if(page > RX_LAST)      page -= (RX_LAST-RX_FIRST)+1;
+                       writepos += (pages-2) * 256;
+                       rem_bytes -= (pages-2) * 256;
                }
-               else
-                       Ne2k_int_ReadDMA(Card, page, pages-1, buf+256);
-               
-               // Wrap length to the packet length
-               if(Length > pktHdr->Length)
-                       Length = pktHdr->Length;
-               else if( Length < pktHdr->Length ) {
-                       Log_Warning("NE2000", "Packet truncated! (%i bytes truncated to %i)",
-                               pktHdr->Length, Length);
-               }
-               memcpy(Buffer, &buf[4], Length);
-               
-               free(buf);
+
+               ASSERT(rem_bytes > 0 && rem_bytes <= 0x100);
+
+               // Final page
+               Ne2k_int_ReadDMA(Card, page, 1, data);
+               memcpy(writepos, data, rem_bytes);
        }
        
        // Write BNRY (maximum page for incoming packets)
@@ -440,8 +398,8 @@ size_t Ne2k_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
        // Set next RX Page and decrement the waiting list
        Card->NextRXPage = pktHdr->NextPacketPage;
        
-       LEAVE('i', Length);
-       return Length;
+       LEAVE('p', ret);
+       return ret;
 }
 
 int Ne2k_int_ReadDMA(tCard *Card, int FirstPage, int NumPages, void *Buffer)

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