Modules/VGA - Start on a generic VGA driver (VGA driver, and library for derivatives)
[tpg/acess2.git] / KernelLand / Modules / Network / RTL8139 / rtl8139.c
index 1e9ac89..84f141f 100644 (file)
@@ -6,10 +6,9 @@
 #define VERSION        ((0<<8)|20)
 #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 VENDOR_ID      0x10EC
@@ -38,7 +37,7 @@ enum eRTL8139_Regs
        // Early RX Status Register
        ERSR = 0x36,
        
-       // ??, ??, ??, RST, RE, TE, ??, ??
+       // -, -, -, RST, RE, TE, -, BUFE
        CMD     = 0x37,
        
        CAPR    = 0x38, // Current address of packet read
@@ -60,8 +59,16 @@ enum eRTL8139_Regs
        
 };
 
-#define FLAG_ISR_TOK   0x04
-#define FLAG_ISR_ROK   0x01
+#define FLAG_ISR_SERR  0x8000  // System error
+#define FLAG_ISR_TIMEO 0x4000  // Timer timeout (See TIMERINT)
+#define FLAG_ISR_LENCHG        0x2000  // Cable length changed
+#define FLAG_ISR_FOVW  0x0040  // Rx FIFO Underflow
+#define FLAG_ISR_PUN   0x0020  // Packet Underrung
+#define FLAG_ISR_RXOVW 0x0010  // Rx Buffer Overflow
+#define FLAG_ISR_TER   0x0008  // Tx Error
+#define FLAG_ISR_TOK   0x0004  // Tx OK
+#define FLAG_ISR_RER   0x0002  // Rx Error
+#define FLAG_ISR_ROK   0x0001  // Rx OK
 
 // === TYPES ===
 typedef struct sCard
@@ -84,42 +91,26 @@ typedef struct sCard
        tMutex  CurTXProtector; //!< Protects \a .CurTXDescriptor
         int    CurTXDescriptor;
        
-       char    Name[2];
-       tVFS_Node       Node;
+       void    *IPStackHandle;
        Uint8   MacAddr[6];
 }      tCard;
 
 // === PROTOTYPES ===
  int   RTL8139_Install(char **Options);
-char   *RTL8139_ReadDir(tVFS_Node *Node, int Pos);
-tVFS_Node      *RTL8139_FindDir(tVFS_Node *Node, const char *Filename);
- int   RTL8139_RootIOCtl(tVFS_Node *Node, int ID, void *Arg);
-Uint64 RTL8139_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
-Uint64 RTL8139_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buffer);
- int   RTL8139_IOCtl(tVFS_Node *Node, int ID, void *Arg);
+tIPStackBuffer *RTL8139_WaitForPacket(void *Ptr);
+void   RTL8139_int_UpdateCAPR(void *Ptr, size_t pkt_length, size_t Unused, const void *DataPtr);
+ int   RTL8139_SendPacket(void *Ptr, tIPStackBuffer *Buffer);
 void   RTL8139_IRQHandler(int Num, void *Ptr);
 
 // === GLOBALS ===
 MODULE_DEFINE(0, VERSION, RTL8139, RTL8139_Install, NULL, NULL);
-tVFS_NodeType  gRTL8139_RootNodeType = {
-       .ReadDir = RTL8139_ReadDir,
-       .FindDir = RTL8139_FindDir,
-       .IOCtl = RTL8139_IOCtl
+tIPStack_AdapterType   gRTL8139_AdapterType = {
+       .Name = "RTL8139",
+       .Type = 0,      // TODO: Differentiate differnet wire protos and speeds
+       .Flags = 0,     // TODO: IP checksum offloading, MAC checksum offloading etc
+       .SendPacket = RTL8139_SendPacket,
+       .WaitForPacket = RTL8139_WaitForPacket
        };
-tVFS_NodeType  gRTL8139_DevNodeType = {
-       .Write = RTL8139_Write,
-       .Read = RTL8139_Read,
-       .IOCtl = RTL8139_IOCtl  
-       };
-tDevFS_Driver  gRTL8139_DriverInfo = {
-       NULL, "RTL8139",
-       {
-       .NumACLs = 1,
-       .ACLs = &gVFS_ACL_EveryoneRX,
-       .Flags = VFS_FFLAG_DIRECTORY,
-       .Type = &gRTL8139_RootNodeType
-       }
-};
  int   giRTL8139_CardCount;
 tCard  *gaRTL8139_Cards;
 
@@ -165,6 +156,9 @@ int RTL8139_Install(char **Options)
                // Reset (0x10 to CMD)
                outb( base + CMD, 0x10 );       
                while( inb(base + CMD) & 0x10 ) ;
+
+               // Set IMR to all interrupts!
+               outw(base + IMR, 0xE07F);
                
                // Set up recieve buffer
                // - Allocate 3 pages below 4GiB for the recieve buffer (Allows 8k+16+1500)
@@ -173,8 +167,6 @@ int RTL8139_Install(char **Options)
                outd(base + RBSTART, (Uint32)card->PhysReceiveBuffer);
                outd(base + CBA, 0);
                outd(base + CAPR, 0);
-               // Set IMR to Transmit OK and Receive OK
-               outw(base + IMR, 0x5);
                
                // Set up transmit buffers
                // - 2 non-contiguous pages (each page can fit 2 1500 byte packets)
@@ -195,7 +187,10 @@ int RTL8139_Install(char **Options)
                // - Bit 7 being set tells the card to overflow the recieve buffer if needed
                //   (i.e. when the packet starts at the end of the bufffer, it overflows up
                //    to 1500 bytes)
-               outd(base + RCR, 0x8F);
+               // Bits 10: 8 set the max DMA burst size (6=1024)
+               // Bits 12:11 set the size (8k+16 -> 64k+16)
+               // Bits 15:13 set the FIFO threshold (6 = 1024)
+               outd(base + RCR, (6<<13)|(6<<8)|0x80|0x1F);     // All valid + runt packets
        
                // Recive Enable and Transmit Enable    
                outb(base + CMD, 0x0C);
@@ -208,14 +203,9 @@ int RTL8139_Install(char **Options)
                card->MacAddr[4] = inb(base+MAC4);
                card->MacAddr[5] = inb(base+MAC5);
                
-               // Set VFS Node
-               card->Name[0] = '0'+i;
-               card->Name[1] = '\0';
-               card->Node.ImplPtr = card;
-               card->Node.NumACLs = 0;
-               card->Node.CTime = now();
-               card->Node.Type = &gRTL8139_DevNodeType;
-               
+               // Interface with IPStack
+               card->IPStackHandle = IPStack_Adapter_Add(&gRTL8139_AdapterType, card, card->MacAddr);
+
                Log_Log("RTL8139", "Card %i 0x%04x, IRQ %i %02x:%02x:%02x:%02x:%02x:%02x",
                        i, card->IOBase, card->IRQ,
                        card->MacAddr[0], card->MacAddr[1], card->MacAddr[2],
@@ -223,53 +213,24 @@ int RTL8139_Install(char **Options)
                        );
        }
        
-       gRTL8139_DriverInfo.RootNode.Size = giRTL8139_CardCount;
-       DevFS_AddDevice( &gRTL8139_DriverInfo );
-       
        return MODULE_ERR_OK;
 }
 
-// --- Root Functions ---
-char *RTL8139_ReadDir(tVFS_Node *Node, int Pos)
-{
-       if( Pos < 0 || Pos >= giRTL8139_CardCount )     return NULL;
-       
-       return strdup( gaRTL8139_Cards[Pos].Name );
-}
-
-tVFS_Node *RTL8139_FindDir(tVFS_Node *Node, const char *Filename)
-{
-       //TODO: It might be an idea to supprt >10 cards
-       if(Filename[0] == '\0' || Filename[1] != '\0')  return NULL;
-       if(Filename[0] < '0' || Filename[0] > '9')      return NULL;
-       return &gaRTL8139_Cards[ Filename[0]-'0' ].Node;
-}
-
-const char *csaRTL8139_RootIOCtls[] = {DRV_IOCTLNAMES, NULL};
-int RTL8139_RootIOCtl(tVFS_Node *Node, int ID, void *Data)
-{
-       ENTER("pNode iID pData", Node, ID, Data);
-       switch(ID)
-       {
-       BASE_IOCTLS(DRV_TYPE_NETWORK, "RTL8139", VERSION, csaRTL8139_RootIOCtls);
-       }
-       LEAVE('i', 0);
-       return 0;
-}
-
 // --- File Functions ---
-Uint64 RTL8139_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+tIPStackBuffer *RTL8139_WaitForPacket(void *Ptr)
 {
-       tCard   *card = Node->ImplPtr;
+       tCard   *card = Ptr;
        Uint16  read_ofs, pkt_length;
-        int    new_read_ofs;
+       tIPStackBuffer  *ret;
 
-       ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
+       ENTER("pPtr", Ptr);
 
 retry:
+       LOG("IMR = %x, ISR = %x", inw(card->IOBase + IMR), inw(card->IOBase + ISR));
        if( Semaphore_Wait( &card->ReadSemaphore, 1 ) != 1 )
        {
-               LEAVE_RET('i', 0);
+               LEAVE('n');
+               return NULL;
        }
        
        Mutex_Acquire( &card->ReadMutex );
@@ -281,6 +242,37 @@ retry:
        
        pkt_length = *(Uint16*)&card->ReceiveBuffer[read_ofs+2];
        
+       // Check for errors
+       if( *(Uint16*)&card->ReceiveBuffer[read_ofs] & 0x1E )
+       {
+               // Update CAPR
+               RTL8139_int_UpdateCAPR( card, pkt_length, 0, &card->ReceiveBuffer[read_ofs+4] );
+               Mutex_Release( &card->ReadMutex );
+               goto retry;     // I feel evil
+       }
+       
+       ret = IPStack_Buffer_CreateBuffer(1);
+       IPStack_Buffer_AppendSubBuffer(ret,
+               pkt_length, 0, &card->ReceiveBuffer[read_ofs+4],
+               RTL8139_int_UpdateCAPR, card
+               );
+       
+       Mutex_Release( &card->ReadMutex );
+       
+       LEAVE('p', ret);
+       return ret;
+}
+
+/**
+ * \brief Updates CAPR after a packet has been read
+ * \note Assumes that buffers are freed in the order we allocate them
+ */
+void RTL8139_int_UpdateCAPR(void *Ptr, size_t pkt_length, size_t Unused, const void *DataPtr)
+{
+       tCard   *card = Ptr;
+        int    read_ofs = DataPtr - (const void *)card->ReceiveBuffer - 4;
+        int    new_read_ofs;
+
        // Calculate new read offset
        new_read_ofs = read_ofs + pkt_length + 4;
        new_read_ofs = (new_read_ofs + 3) & ~3; // Align
@@ -290,38 +282,24 @@ retry:
        }
        new_read_ofs -= 0x10;   // I dunno
        LOG("new_read_ofs = %i", new_read_ofs);
-       
-       // Check for errors
-       if( *(Uint16*)&card->ReceiveBuffer[read_ofs] & 0x1E ) {
-               // Update CAPR
-               outw(card->IOBase + CAPR, new_read_ofs);
-               Mutex_Release( &card->ReadMutex );
-               goto retry;     // I feel evil
-       }
-       
-       // Get packet
-       if( Length > pkt_length )       Length = pkt_length;
-       memcpy(Buffer, &card->ReceiveBuffer[read_ofs+4], Length);
-       
+
        // Update CAPR
        outw(card->IOBase + CAPR, new_read_ofs);
-       
-       Mutex_Release( &card->ReadMutex );
-       
-       LEAVE('i', Length);
-       
-       return Length;
 }
 
-Uint64 RTL8139_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buffer)
+int RTL8139_SendPacket(void *Ptr, tIPStackBuffer *Buffer)
 {
-        int    td;
+        int    td, length;
        Uint32  status;
-       tCard   *card = Node->ImplPtr;
-       
-       if( Length > 1500 )     return 0;       // MTU exceeded
+       tCard   *card = Ptr;
        
-       ENTER("pNode XLength pBuffer", Node, Length, Buffer);
+       ENTER("pPtr pBuffer", Ptr, Buffer);
+
+       length = IPStack_Buffer_GetLength(Buffer);
+       if( length > 1500 ) {
+               LEAVE('i', -1);
+               return -1;      // MTU exceeded
+       }
        
        // TODO: Implement a semaphore for avaliable transmit buffers
 
@@ -339,40 +317,20 @@ Uint64 RTL8139_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *
        // Transmit using descriptor `td`
        LOG("card->PhysTransmitBuffers[td] = %P", card->PhysTransmitBuffers[td]);
        outd(card->IOBase + TSAD0 + td*4, card->PhysTransmitBuffers[td]);
-       LOG("card->TransmitBuffers[td] = %p", card->TransmitBuffers[td]);
+       
        // Copy to buffer
-       memcpy(card->TransmitBuffers[td], Buffer, Length);
+       LOG("card->TransmitBuffers[td] = %p", card->TransmitBuffers[td]);
+       IPStack_Buffer_GetData(Buffer, card->TransmitBuffers[td], length);
+       
        // Start
        status = 0;
-       status |= Length & 0x1FFF;      // 0-12: Length
+       status |= length & 0x1FFF;      // 0-12: Length
        status |= 0 << 13;      // 13: OWN bit
        status |= (0 & 0x3F) << 16;     // 16-21: Early TX threshold (zero atm, TODO: check)
        LOG("status = 0x%08x", status);
        outd(card->IOBase + TSD0 + td*4, status);
        
-       LEAVE('i', (int)Length);
-       
-       return Length;
-}
-
-const char *csaRTL8139_NodeIOCtls[] = {DRV_IOCTLNAMES, NULL};
-int RTL8139_IOCtl(tVFS_Node *Node, int ID, void *Data)
-{
-       tCard   *card = Node->ImplPtr;
-       ENTER("pNode iID pData", Node, ID, Data);
-       switch(ID)
-       {
-       BASE_IOCTLS(DRV_TYPE_NETWORK, "RTL8139", VERSION, csaRTL8139_NodeIOCtls);
-       case NET_IOCTL_GETMAC:
-               if( !CheckMem(Data, 6) ) {
-                       LEAVE('i', -1);
-                       return -1;
-               }
-               memcpy( Data, card->MacAddr, 6 );
-               LEAVE('i', 1);
-               return 1;
-       }
-       LEAVE('i', 0);
+       LEAVE('i', 0);  
        return 0;
 }
 
@@ -382,11 +340,10 @@ void RTL8139_IRQHandler(int Num, void *Ptr)
        tCard   *card = Ptr;
        Uint16  status;
 
-       LOG("Num = %i", Num);
-       
        if( Num != card->IRQ )  return;
                
        status = inw(card->IOBase + ISR);
+       if( !status )   return ;
        LOG("status = 0x%02x", status);
                
        // Transmit OK, a transmit descriptor is now free
@@ -401,6 +358,13 @@ void RTL8139_IRQHandler(int Num, void *Ptr)
                }
                outw(card->IOBase + ISR, FLAG_ISR_TOK);
        }
+
+       // Transmit error, ... oops
+       if( status & FLAG_ISR_TER )
+       {
+               Log_Error("RTK8139", "Tx Error, dunno what to do");
+               outw(card->IOBase + ISR, FLAG_ISR_TER);
+       }
        
        // Recieve OK, inform read
        if( status & FLAG_ISR_ROK )
@@ -436,6 +400,7 @@ void RTL8139_IRQHandler(int Num, void *Ptr)
                while( read_ofs < end_ofs )
                {
                        packet_count ++;
+//                     Log_Debug("RTL8139", "RX %i at 0x%x", packet_count, read_ofs);
                        LOG("%i 0x%x Pkt Hdr: 0x%04x, len: 0x%04x",
                                packet_count, read_ofs,
                                *(Uint16*)&card->ReceiveBuffer[read_ofs],
@@ -456,10 +421,39 @@ void RTL8139_IRQHandler(int Num, void *Ptr)
                {
                        if( Semaphore_Signal( &card->ReadSemaphore, packet_count ) != packet_count ) {
                                // Oops?
+                               Log_Warning("RTL8139", "IRQ: signalling read semaphore failed, Oops?");
                        }
-                       VFS_MarkAvaliable( &card->Node, 1 );
                }
                
                outw(card->IOBase + ISR, FLAG_ISR_ROK);
-       }       
+       }
+       
+       // Recieve error, ... oops
+       if( status & FLAG_ISR_RER )
+       {
+               Log_Error("RTL8139", "Rx Error, dunno what to do");
+               outw(card->IOBase + ISR, FLAG_ISR_RER);
+       }
+
+       // Packet Underrun/Link Change
+       if( status & FLAG_ISR_PUN )
+       {
+               // Set when CAPR is written but Rx is empty, OR when the link status changes
+               Log_Notice("RTL8139", "ISR[PUN] set... hmmm");
+               outw(card->IOBase + ISR, FLAG_ISR_PUN);
+       }
+
+       // Rx Overflow
+       if( status & FLAG_ISR_RXOVW )
+       {
+               Log_Error("RTL8139", "Rx Overflow... oh fsck");
+               outw(card->IOBase + ISR, FLAG_ISR_RXOVW);
+       }
+
+       // Rx FIFO Overflow
+       if( status & FLAG_ISR_FOVW )
+       {
+               Log_Error("RTL8139", "Rx FIFO Overflow... huh?");
+               outw(card->IOBase + ISR, FLAG_ISR_FOVW);
+       }
 }

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