Renamed tpl_drv_* to api_drv_* (a more fitting name)
[tpg/acess2.git] / Modules / Network / NE2000 / ne2000.c
index 40d9b82..eb3673f 100644 (file)
@@ -3,13 +3,14 @@
  * 
  * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc
  */
-#define        DEBUG   0
+#define        DEBUG   1
 #define VERSION        ((0<<8)|50)
 #include <acess.h>
 #include <modules.h>
 #include <fs_devfs.h>
 #include <drv_pci.h>
-#include <tpl_drv_network.h>
+#include <api_drv_network.h>
+#include <semaphore.h>
 
 // === CONSTANTS ===
 #define        MEM_START       0x40
@@ -29,7 +30,7 @@ static const struct {
        {0x10EC, 0x8029},       // Realtek 8029
        {0x10EC, 0x8129}        // Realtek 8129
 };
-#define NUM_COMPAT_DEVICES     (sizeof(csaCOMPAT_DEVICES)/sizeof(csaCOMPAT_DEVICES[0]))
+#define NUM_COMPAT_DEVICES     ((int)(sizeof(csaCOMPAT_DEVICES)/sizeof(csaCOMPAT_DEVICES[0])))
 
 enum eNe2k_Page0Read {
        CMD = 0,        //!< the master command register
@@ -70,25 +71,25 @@ typedef struct sNe2k_Card {
        Uint16  IOBase; //!< IO Port Address from PCI
        Uint8   IRQ;    //!< IRQ Assigned from PCI
        
-        int    NumWaitingPackets;
-        int    NextRXPage;
+       tSemaphore      Semaphore;      //!< Semaphore for incoming packets
+        int    NextRXPage;     //!< Next expected RX page
        
         int    NextMemPage;    //!< Next Card Memory page to use
-       
-       Uint8   Buffer[RX_BUF_SIZE*256];
-       
+               
        char    Name[2];        // "0"
-       tVFS_Node       Node;
-       Uint8   MacAddr[6];
+       tVFS_Node       Node;   //!< VFS Node
+       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, char *Name);
+tVFS_Node      *Ne2k_FindDir(tVFS_Node *Node, const 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);
+
+ int   Ne2k_int_ReadDMA(tCard *Card, int FirstPage, int NumPages, void *Buffer);
 Uint8  Ne2k_int_GetWritePage(tCard *Card, Uint16 Length);
 void   Ne2k_IRQHandler(int IntNum);
 
@@ -117,18 +118,19 @@ tCard     *gpNe2k_Cards = NULL;
 int Ne2k_Install(char **Options)
 {
         int    i, j, k;
-        int    count, id, base;
+        int    count, base;
+       tPCIDev id;
        
        // --- Scan PCI Bus ---
        // Count Cards
        giNe2k_CardCount = 0;
        for( i = 0; i < NUM_COMPAT_DEVICES; i ++ )
        {
-               giNe2k_CardCount += PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0 );
+               giNe2k_CardCount += PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device );
        }
        
        if( giNe2k_CardCount == 0 ) {
-               Warning("[Ne2k ] No cards detected");
+               Log_Warning("Ne2k", "No cards detected");
                return MODULE_ERR_NOTNEEDED;
        }
        
@@ -138,12 +140,12 @@ int Ne2k_Install(char **Options)
        
        for( i = 0; i < NUM_COMPAT_DEVICES; i ++ )
        {
-               count = PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0 );
+               count = PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device );
                for( j = 0; j < count; j ++,k ++ )
                {
-                       id = PCI_GetDevice( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0, j );
+                       id = PCI_GetDevice( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, j );
                        // Create Structure
-                       base = PCI_AssignPort( id, 0, 0x20 );
+                       base = PCI_GetBAR( id, 0 );
                        gpNe2k_Cards[ k ].IOBase = base;
                        gpNe2k_Cards[ k ].IRQ = PCI_GetIRQ( id );
                        gpNe2k_Cards[ k ].NextMemPage = 64;
@@ -162,17 +164,17 @@ int Ne2k_Install(char **Options)
                        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 );
+                       outb( base + IMR, 0x00 );       // Interrupt Mask Register
                        outb( base + ISR, 0xFF );
                        outb( base + RCR, 0x20 );       // Reciever to Monitor
                        outb( base + TCR, 0x02 );       // Transmitter OFF (TCR.LB = 1, Internal Loopback)
+                       
+                       // Read MAC Address
                        outb( base + RBCR0, 6*4 );      // Remote Byte Count
                        outb( base + RBCR1, 0 );
                        outb( base + RSAR0, 0 );        // Clear Source Address
                        outb( base + RSAR1, 0 );
                        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);
@@ -189,22 +191,12 @@ int Ne2k_Install(char **Options)
                        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
-                       /*
-                       Ne2k_WriteReg(base, MAC0, gpNe2k_Cards[ k ].MacAddr[0]);
-                       Ne2k_WriteReg(base, MAC1, gpNe2k_Cards[ k ].MacAddr[1]);
-                       Ne2k_WriteReg(base, MAC2, gpNe2k_Cards[ k ].MacAddr[2]);
-                       Ne2k_WriteReg(base, MAC3, gpNe2k_Cards[ k ].MacAddr[3]);
-                       Ne2k_WriteReg(base, MAC4, gpNe2k_Cards[ k ].MacAddr[4]);
-                       Ne2k_WriteReg(base, MAC5, gpNe2k_Cards[ k ].MacAddr[5]);
-                       */
                        
-                       Log("[NE2K]: Card #%i: IRQ=%i, IOBase=0x%x",
-                               k, gpNe2k_Cards[ k ].IRQ, gpNe2k_Cards[ k ].IOBase);
-                       Log("MAC Address %x:%x:%x:%x:%x:%x",
-                               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]
+                       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]
                                );
                        
                        // Set VFS Node
@@ -216,6 +208,10 @@ int Ne2k_Install(char **Options)
                        gpNe2k_Cards[ k ].Node.Write = Ne2k_Write;
                        gpNe2k_Cards[ k ].Node.Read = Ne2k_Read;
                        gpNe2k_Cards[ k ].Node.IOCtl = Ne2k_IOCtl;
+                       
+                       // Initialise packet semaphore
+                       // - Start at zero, no max
+                       Semaphore_Init( &gpNe2k_Cards[k].Semaphore, 0, 0, "NE2000", gpNe2k_Cards[ k ].Name );
                }
        }
        
@@ -237,9 +233,9 @@ char *Ne2k_ReadDir(tVFS_Node *Node, int Pos)
 }
 
 /**
- * \fn tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, char *Name)
+ * \fn tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, const char *Name)
  */
-tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, char *Name)
+tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, const char *Name)
 {
        if(Name[0] == '\0' || Name[1] != '\0')  return NULL;
        
@@ -253,27 +249,10 @@ 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:
-               LEAVE('i', DRV_TYPE_NETWORK);
-               return DRV_TYPE_NETWORK;
-       
-       case DRV_IOCTL_IDENT:
-               tmp = ModUtil_SetIdent(Data, "Ne2k");
-               LEAVE('i', tmp);
-               return tmp;
-       
-       case DRV_IOCTL_VERSION:
-               LEAVE('x', VERSION);
-               return VERSION;
-       
-       case DRV_IOCTL_LOOKUP:
-               tmp = ModUtil_LookupString( (char**)casIOCtls, Data );
-               LEAVE('i', tmp);
-               return tmp;
+       BASE_IOCTLS(DRV_TYPE_NETWORK, "NE2000", VERSION, casIOCtls);
        }
        
        // If this is the root, return
@@ -311,9 +290,12 @@ Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
        
        ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
        
+       // TODO: Lock
+       
        // Sanity Check Length
        if(Length > TX_BUF_SIZE*256) {
-               Warning(
+               Log_Warning(
+                       "Ne2k",
                        "Ne2k_Write - Attempting to send over TX_BUF_SIZE*256 (%i) bytes (%i)",
                        TX_BUF_SIZE*256, Length
                        );
@@ -327,7 +309,7 @@ Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
        // Clear Remote DMA Flag
        outb(Card->IOBase + ISR, 0x40); // Bit 6
        
-       // Send Size - Remote Byte Count Register
+       // Send Size - Transfer Byte Count Register
        outb(Card->IOBase + TBCR0, Length & 0xFF);
        outb(Card->IOBase + TBCR1, Length >> 8);
        
@@ -340,7 +322,6 @@ Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
        page = Ne2k_int_GetWritePage(Card, Length);
        outb(Card->IOBase + RSAR1, page);       // Page Offset
        // Start
-       //outb(Card->IOBase + CMD, 0|0x18|0x4|0x2);     // Page 0, Transmit Packet, TXP, Start
        outb(Card->IOBase + CMD, 0|0x10|0x2);   // Page 0, Remote Write, Start
        
        // Send Data
@@ -348,7 +329,7 @@ Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
                outw(Card->IOBase + 0x10, *buf++);
        }
        
-       while( inb(Card->IOBase + ISR) == 0 )   // Wait for Remote DMA Complete
+       while( !(inb(Card->IOBase + ISR) & 0x40) )      // Wait for Remote DMA Complete
                ;       //Proc_Yield();
        
        outb( Card->IOBase + ISR, 0x40 );       // ACK Interrupt
@@ -373,7 +354,6 @@ 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;
@@ -382,31 +362,27 @@ Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
        
        ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
        
-       while(Card->NumWaitingPackets == 0)     Threads_Yield();
+       // Wait for packets
+       if( Semaphore_Wait( &Card->Semaphore, 1 ) != 1 )
+       {
+               // Error or interrupted
+               LEAVE_RET('i', 0);
+       }
        
-       // Make sure that the card is in page 0
-       outb(Card->IOBase + CMD, 0|0x22);       // Page 0, Start, NoDMA
+       outb(Card->IOBase, 0x22 | (1 << 6));    // Page 6
+       LOG("CURR : 0x%02x", inb(Card->IOBase + CURR));
        
-       // Get BOUNDARY
+       // Get current read page
        page = Card->NextRXPage;
+       LOG("page = %i", page);
        
-       // 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);
+       Ne2k_int_ReadDMA(Card, page, 1, data);
        
        pktHdr = (void*)data;
-       //Log("Ne2k_Read: Recieved packet (%i bytes)", pktHdr->Length);
+       
+       LOG("pktHdr->Status = 0x%x", pktHdr->Status);
+       LOG("pktHdr->NextPacketPage = %i", pktHdr->NextPacketPage);
+       LOG("pktHdr->Length = 0x%03x", pktHdr->Length);
        
        // Have we read all the required bytes yet?
        if(pktHdr->Length < 256 - 4)
@@ -414,56 +390,104 @@ Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
                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 );
+       else
+       {
+                int    pages = pktHdr->NextPacketPage - page;
+               char    *buf = malloc( pages*256 );
                
-               if(!buf) {
-                       LEAVE('i', -1);
-                       return -1;
-               }
+               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);
                
+               // Read all the needed pages
                page ++;
-               while(page != pktHdr->NextPacketPage)
+               if(page == RX_LAST+1)   page = RX_FIRST;
+               
+               if( page + pages > RX_LAST )
                {
-                       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 ++;
+                        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);
                }
+               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);
        }
        
-       // Write BNRY
-       if(page == RX_FIRST)
-               outb( Card->IOBase + BNRY, RX_LAST );
+       // Write BNRY (maximum page for incoming packets)
+       if(pktHdr->NextPacketPage == RX_FIRST)
+               outb( Card->IOBase + BNRY, RX_LAST-1 );
        else
-               outb( Card->IOBase + BNRY, page-1 );
+               outb( Card->IOBase + BNRY, pktHdr->NextPacketPage-1 );
        // Set next RX Page and decrement the waiting list
-       Card->NextRXPage = page;
-       Card->NumWaitingPackets --;
+       Card->NextRXPage = pktHdr->NextPacketPage;
        
        LEAVE('i', Length);
        return Length;
 }
 
+int Ne2k_int_ReadDMA(tCard *Card, int FirstPage, int NumPages, void *Buffer)
+{
+        int    i;
+       
+       // Sanity check
+       if( !(0 <= FirstPage && FirstPage < 256) ) {
+               Log_Warning("NE2000", "Ne2k_int_ReadDMA: BUG - FirstPage(%i) not 8-bit", FirstPage);
+               return -1;
+       }
+       if( !(0 <= NumPages && NumPages < 256) ) {
+               Log_Warning("NE2000", "Ne2k_int_ReadDMA: BUG - NumPages(%i) not 8-bit", NumPages);
+               return -1;
+       }
+       
+       ENTER("pCard iFirstPage iNumPages pBuffer", Card, FirstPage, NumPages, Buffer);
+       
+       // Make sure that the card is in bank 0
+       outb(Card->IOBase + CMD, 0|0x22);       // Bank 0, Start, NoDMA
+       outb(Card->IOBase + ISR, 0x40); // Clear Remote DMA Flag
+       
+       // Set up transfer
+       outb(Card->IOBase + RBCR0, 0);
+       outb(Card->IOBase + RBCR1, NumPages);   // page count
+       outb(Card->IOBase + RSAR0, 0x00);       // Page Offset
+       outb(Card->IOBase + RSAR1, FirstPage);  // Page Number
+       outb(Card->IOBase + CMD, 0|0x08|0x2);   // Bank 0, Remote Read, Start
+       
+       // TODO: Less expensive
+       //while( !(inb(Card->IOBase + ISR) & 0x40) ) {
+       //      HALT();
+       //      LOG("inb(ISR) = 0x%02x", inb(Card->IOBase + ISR));
+       //}
+       HALT(); // Small delay?
+       
+       // Read data
+       for(i = 0; i < 128*NumPages; i ++)
+               ((Uint16*)Buffer)[i] = inw(Card->IOBase + 0x10);
+               
+       
+       outb(Card->IOBase + ISR, 0x40); // Clear Remote DMA Flag
+       
+       LEAVE('i', NumPages);
+       return NumPages;
+}
+
 /**
  * \fn Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length)
  */
@@ -492,12 +516,20 @@ void Ne2k_IRQHandler(int IntNum)
                {
                        byte = inb( gpNe2k_Cards[i].IOBase + ISR );
                        
+                       LOG("byte = 0x%02x", byte);
+                       
+                       
+                       // Reset All (save for RDMA), that's polled
+                       outb( gpNe2k_Cards[i].IOBase + ISR, 0xFF&(~0x40) );
+                       
                        // 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;
+                               //if( gpNe2k_Cards[i].NumWaitingPackets > MAX_PACKET_QUEUE )
+                               //      gpNe2k_Cards[i].NumWaitingPackets = MAX_PACKET_QUEUE;
+                               if( Semaphore_Signal( &gpNe2k_Cards[i].Semaphore, 1 ) != 1 ) {
+                                       // Oops?
+                               }
                        }
                        // 1: Packet sent (no error)
                        // 2: Recieved with error
@@ -506,10 +538,9 @@ void Ne2k_IRQHandler(int IntNum)
                        // 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 ;
                }
        }
-       Warning("[NE2K ] Recieved Unknown IRQ %i", IntNum);
+       Log_Warning("Ne2k", "Recieved Unknown IRQ %i", IntNum);
 }

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