Modules/VIARhineII - RX and TX works, but TX is a hack atm
authorJohn Hodge <[email protected]>
Wed, 16 May 2012 03:01:40 +0000 (11:01 +0800)
committerJohn Hodge <[email protected]>
Wed, 16 May 2012 03:01:40 +0000 (11:01 +0800)
KernelLand/Modules/Network/VIARhineII/rhine2.c
KernelLand/Modules/Network/VIARhineII/rhine2_hw.h

index 4a152fe..3d8a4fa 100644 (file)
 #include "rhine2_hw.h"
 #include <IPStack/include/adapters_api.h>
 
+#define DESC_SIZE      16
 #define N_RX_DESCS     16
 #define RX_BUF_SIZE    1024
 #define N_RX_PAGES     ((N_RX_DESCS*RX_BUF_SIZE)/PAGE_SIZE)
-#define N_TX_DESCS     ((PAGE_SIZE/16)-N_RX_DESCS)
+#define N_TX_DESCS     ((PAGE_SIZE/DESC_SIZE)-N_RX_DESCS)
+
+#define CR0_BASEVAL    (CR0_STRT|CR0_TXON|CR0_RXON)
 
 // === CONSTANTS ===
 #define VENDOR_ID      0x1106
@@ -27,6 +30,7 @@ typedef struct sCard
        Uint8   IRQ;
        
        tSemaphore      ReadSemaphore;
+       tSemaphore      SendSemaphore;
 
        struct {
                Uint32  Phys;
@@ -37,9 +41,8 @@ typedef struct sCard
        void    *DescTable;
 
        struct sTXDesc  *TXDescs;
-       
-       struct sTXDesc  *FirstTX;
-       struct sTXDesc  *LastTX;        // Most recent unsent packet
+        int    NextTX;
+        int    nFreeTX;
        
        struct sRXDesc  *FirstRX;       // Most recent unread packet
        struct sRXDesc  *LastRX;        // End of RX descriptor queue
@@ -58,7 +61,6 @@ void  Rhine2_IRQHandler(int Num, void *Pt);
 struct sRXDesc *Rhine2_int_GetDescFromPhys(tCard *Card, Uint32 Addr);
 void   *Rhine2_int_GetBufferFromPhys(tCard *Card, Uint32 Addr);
 void   Rhine2_int_FreeRXDesc(void *Desc, size_t, size_t, const void*);
-struct sTXDesc *Rhine2_int_AllocTXDesc(tCard *Card);
 
 // === GLOBALS ===
 MODULE_DEFINE(0, VERSION, VIARhineII, Rhine2_Install, NULL, NULL);
@@ -82,8 +84,6 @@ int Rhine2_Install(char **Options)
        tCard   *card;
        
        giRhine2_CardCount = PCI_CountDevices(VENDOR_ID, DEVICE_ID);
-       Log_Debug("Rhine2", "%i cards", giRhine2_CardCount);
-       
        if( giRhine2_CardCount == 0 )   return MODULE_ERR_NOTNEEDED;
        
        gaRhine2_Cards = calloc( giRhine2_CardCount, sizeof(tCard) );
@@ -113,6 +113,8 @@ int Rhine2_Install(char **Options)
                
                Rhine2_int_InitialiseCard(card);
        
+               card->IPHandle = IPStack_Adapter_Add(&gRhine2_AdapterType, card, card->MacAddr);
+       
                Log_Log("Rhine2", "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],
@@ -135,11 +137,13 @@ void Rhine2_int_InitialiseCard(tCard *Card)
        Card->MacAddr[3] = inb(Card->IOBase + REG_PAR3);
        Card->MacAddr[4] = inb(Card->IOBase + REG_PAR4);
        Card->MacAddr[5] = inb(Card->IOBase + REG_PAR5);
-       
+
+       LOG("Resetting card");  
        outb(Card->IOBase + REG_CR1, CR1_SFRST);
        // TODO: Timeout
        while( inb(Card->IOBase + REG_CR1) & CR1_SFRST ) ;
        
+       LOG("Allocaating RX buffers");
        // Allocate memory for things
        for( int i = 0; i < N_RX_PAGES; i ++ )
        {
@@ -147,6 +151,7 @@ void Rhine2_int_InitialiseCard(tCard *Card)
                Card->RXBuffers[i].Phys = phys;
        }
        
+       LOG("Allocating and filling RX/TX Descriptors");
        Card->DescTable = (void*)MM_AllocDMA(1, 32, &phys);
        Card->DescTablePhys = phys;
 
@@ -158,23 +163,37 @@ void Rhine2_int_InitialiseCard(tCard *Card)
                rxdescs[i].BufferSize = RX_BUF_SIZE;
                rxdescs[i].RXBufferStart = Card->RXBuffers[i/(PAGE_SIZE/RX_BUF_SIZE)].Phys
                        + (i % (PAGE_SIZE/RX_BUF_SIZE)) * RX_BUF_SIZE;
-               rxdescs[i].RDBranchAddress = Card->DescTablePhys + (i+1) * sizeof(struct sRXDesc);
+               rxdescs[i].RDBranchAddress = Card->DescTablePhys + (i+1) * DESC_SIZE;
                rxdescs[i].Length = (1 << 15);  // set OWN
        }
-       rxdescs[ N_RX_DESCS - 1 ].RDBranchAddress = 0;
+       rxdescs[ N_RX_DESCS - 1 ].RDBranchAddress = Card->DescTablePhys;
        Card->FirstRX = &rxdescs[0];
        Card->LastRX = &rxdescs[N_RX_DESCS - 1];
 
        Card->TXDescs = (void*)(rxdescs + N_RX_DESCS);
        memset(Card->TXDescs, 0, sizeof(struct sTXDesc)*N_TX_DESCS);
-       
+       for( int i = 0; i < N_TX_DESCS; i ++ )
+       {
+               Card->TXDescs[i].TDBranchAddress = Card->DescTablePhys + (N_RX_DESCS + i + 1) * DESC_SIZE;
+       }
+       Card->TXDescs[N_TX_DESCS-1].TDBranchAddress = Card->DescTablePhys + N_RX_DESCS * DESC_SIZE;
+       Card->nFreeTX = N_TX_DESCS;
+       Card->NextTX = 0;
        
        // - Initialise card state
+       LOG("Initialising card state");
        outb(Card->IOBase + REG_IMR0, 0xFF);
        outb(Card->IOBase + REG_IMR1, 0xFF);
        outd(Card->IOBase + REG_CUR_RX_DESC, Card->DescTablePhys);
+       outd(Card->IOBase + REG_CUR_TX_DESC, Card->DescTablePhys + N_RX_DESCS * DESC_SIZE);
+
+       outb(Card->IOBase + REG_TCR, TCR_TRSF(4));
        
-       outb(Card->IOBase + REG_CR0, CR0_STRT|CR0_RXON);
+       LOG("RX started");
+       outb(Card->IOBase + REG_CR0, CR0_BASEVAL);
+       outb(Card->IOBase + REG_CR1, CR1_DPOLL);        // Disabled TX polling only?
+       
+       LOG("ISR state: %02x %02x", inb(Card->IOBase + REG_ISR0), inb(Card->IOBase + REG_ISR1));
 }
 
 // --- File Functions ---
@@ -187,6 +206,7 @@ tIPStackBuffer *Rhine2_WaitPacket(void *Ptr)
        
        ENTER("pPtr", Ptr);
 
+       LOG("CR0 state: %02x", inb(card->IOBase + REG_CR0));
        if( Semaphore_Wait( &card->ReadSemaphore, 1 ) != 1 )
        {
                LEAVE('n');
@@ -195,8 +215,11 @@ tIPStackBuffer *Rhine2_WaitPacket(void *Ptr)
        
        nDesc = 0;
        desc = card->FirstRX;
-       while( desc->BufferSize & (1 << 15) )
+       while( !(desc->Length & (1 << 15)) )
        {
+//             LOG("desc(%p) = {RSR:%04x,Length:%04x,BufferSize:%04x,RXBufferStart:%08x,RDBranchAddress:%08x}",
+//                     desc, desc->RSR, desc->Length, desc->BufferSize, desc->RXBufferStart, desc->RDBranchAddress);
+               // TODO: This kinda expensive call can be changed for an increment, but cbf
                desc = Rhine2_int_GetDescFromPhys(card, desc->RDBranchAddress);
                nDesc ++;
        }
@@ -205,7 +228,7 @@ tIPStackBuffer *Rhine2_WaitPacket(void *Ptr)
 
        ret = IPStack_Buffer_CreateBuffer(nDesc);
        desc = card->FirstRX;
-       while( desc->BufferSize & (1 << 15) )
+       while( !(desc->Length & (1 << 15)) )
        {
                void    *data = Rhine2_int_GetBufferFromPhys(card, desc->RXBufferStart);
                IPStack_Buffer_AppendSubBuffer(ret,
@@ -225,66 +248,151 @@ int Rhine2_SendPacket(void *Ptr, tIPStackBuffer *Buffer)
        tCard   *card = Ptr;
        size_t  len;
        const void      *data;
+        int    nDescs, first_desc_id;
+       struct sTXDesc  *desc = NULL;
        struct sTXDesc  *first_desc = NULL;
        struct sTXDesc  *last_desc = NULL;
 
        ENTER("pPtr pBuffer", Ptr, Buffer);     
 
+       #if 0
        // Iterate buffers
+       nDescs = 0;
+       for( int id = -1; -1 != (id = IPStack_Buffer_GetBuffer(Buffer, id, &len, &data)); )
+       {
+               if( ((tVAddr)data & (PAGE_SIZE-1)) + len > PAGE_SIZE )
+                       nDescs ++;
+               nDescs ++;
+       }
+       if( nDescs == 0 ) {
+               LEAVE('i', -1);
+               return -1;
+       }
+
+       LOG("%i descriptors needed", nDescs);
+       
+       if( card->nFreeTX < nDescs ) {
+               // Oops... wait?
+               // TODO: Semaphore instead?
+               LEAVE('i', 1);
+               return 1;
+       }
+
+       first_desc_id = card->NextTX;
+       card->NextTX = (card->NextTX + nDescs) % N_TX_DESCS;
+
+       desc = card->TXDescs + first_desc_id;
+       
+       nDescs = 0;
        for( int id = -1; -1 != (id = IPStack_Buffer_GetBuffer(Buffer, id, &len, &data)); )
        {
                tPAddr  pdata = MM_GetPhysAddr( (tVAddr)data );
-               struct sTXDesc  *desc;
                #if PHYS_BITS > 32
                if( pdata >> 32 ) {
                        // TODO: re-map
+                       Log_Warning("Rhine2", "TODO: Bounce-buffer >32 pbit buffers");
                } 
                #endif
+       
+               if( (pdata & (PAGE_SIZE-1)) + len > PAGE_SIZE )
+               {
+                       // Need to split into to descriptors
+                       Log_Warning("Rhine2", "TODO: Split cross-page buffers");
+               }
                
-               desc = Rhine2_int_AllocTXDesc(card);
-               if(!last_desc)
-                       first_desc = desc;
-               else
-                       last_desc->TDBranchAddress = MM_GetPhysAddr( (tVAddr)desc );
+               LOG("Buffer %i (%p+0x%x) placed in %p", id-1, data, len, desc);
 
+               // TODO: Rhine I requires 4-byte alignment (fsck that, I don't have one)
+       
                desc->TXBufferStart = pdata;
-               desc->BufferSize = len;
+               desc->BufferSize = len | (1 << 15);
                // TODO: TCR
                desc->TCR = 0;
-               desc->TSR = TD_TSR_OWN;
-               desc->TDBranchAddress = 0;
+               if( nDescs == 0 )
+                       desc->TSR = 0;  // OWN will be set below
+               else
+                       desc->TSR = TD_TSR_OWN;
 
-               last_desc = desc;
+               nDescs ++;
+               if(first_desc_id + nDescs == N_TX_DESCS)
+                       desc = card->TXDescs;
+               else
+                       desc ++;
        }
+       #else
+       data = IPStack_Buffer_CompactBuffer(Buffer, &len);
+       
+       nDescs = 1;
+       first_desc_id = card->NextTX;
+       card->NextTX = (card->NextTX + nDescs) % N_TX_DESCS;
+       desc = card->TXDescs + first_desc_id;
+       
+       desc->TXBufferStart = MM_GetPhysAddr( (tVAddr)data );
+       desc->BufferSize = len | (1 << 15);
+       desc->TSR = 0;
+       desc->TCR = 0;
+       #endif
+       
+       first_desc = card->TXDescs + first_desc_id;
+       last_desc = desc;
        
-       if( !first_desc ) {
-               LEAVE('i', -1);
-               return -1;
-       }
-
        first_desc->TCR |= TD_TCR_STP;
-       last_desc->TCR |= TD_TCR_EDP;
-
-       if( card->LastTX )
-               card->LastTX->TDBranchAddress = MM_GetPhysAddr( (tVAddr)first_desc );
-       else {
-               card->FirstTX = first_desc;
-               card->LastTX = first_desc;
-               outd(card->IOBase + REG_CUR_TX_DESC, MM_GetPhysAddr( (tVAddr)first_desc ));
-       }
+       last_desc->TCR |= TD_TCR_EDP|TD_TCR_IC;
+//     last_desc->BufferSize &= ~(1 << 15);
+
+       first_desc->TSR |= TD_TSR_OWN;
+
+       LOG("%i descriptors allocated, first = %p, last = %p", nDescs, first_desc, last_desc);
 
-       outb(card->IOBase + REG_CR1, CR1_TDMD);
-       
-       // TODO: Wait until the packet has sent, then clean up
-       while( inb(card->IOBase + REG_CR1) & CR1_TDMD )
-               ;
 
+       LOG("Waiting for TX to complete");
+       outb(card->IOBase + REG_CR0, CR0_TDMD|CR0_BASEVAL);
+       Semaphore_Wait(&card->SendSemaphore, 1);
+
+       #if 1
+       free((void*)data);
+       #endif
+
+       LEAVE('i', 0);
        return 0;
 }
 
 void Rhine2_IRQHandler(int Num, void *Ptr)
 {
+       tCard   *card = Ptr;
+       Uint8   isr0 = inb(card->IOBase + REG_ISR0);
+       Uint8   isr1 = inb(card->IOBase + REG_ISR1);
+
+       if( isr0 == 0 ) return ;        
+
+       LOG("ISR0 = 0x%02x, ISR1 = 0x%02x", isr0, isr1);
+
+       if( isr0 & ISR0_PRX )
+       {
+               LOG("PRX");
+               Semaphore_Signal(&card->ReadSemaphore, 1);
+       }
        
+       if( isr0 & ISR0_PTX )
+       {
+               LOG("PTX");
+               Semaphore_Signal(&card->SendSemaphore, 1);
+       }
+       
+       if( isr0 & ISR0_TXE )
+       {
+               LOG("TX Error... oops");
+               Semaphore_Signal(&card->SendSemaphore, 1);
+       }
+       
+       if( isr0 & ISR0_TU )
+       {
+               LOG("Transmit buffer underflow");
+       }
+
+       LOG("Acking interrupts");
+       outb(card->IOBase + REG_ISR0, isr0);
+       outb(card->IOBase + REG_ISR1, isr1);
 }
 
 // --- Helpers ---
@@ -315,14 +423,3 @@ void Rhine2_int_FreeRXDesc(void *Ptr, size_t u1, size_t u2, const void *u3)
        desc->Length = (1 << 15);       // Reset OWN
 }
 
-struct sTXDesc *Rhine2_int_AllocTXDesc(tCard *Card)
-{
-       for( int i = 0; i < N_TX_DESCS; i ++ )
-       {
-               if( Card->TXDescs[i].TSR & TD_TSR_OWN ) continue ;
-               Card->TXDescs[i].TSR = TD_TSR_OWN;
-               return &Card->TXDescs[i];
-       }
-       return NULL;
-}
-
index dd3f9ac..f6a92f4 100644 (file)
@@ -63,6 +63,24 @@ enum eRegs
 #define CR1_RDMD       (1 << 6)
 #define CR1_SFRST      (1 << 7)        // Software reset
 
+#define ISR0_PRX       (1 << 0)        // Packet recieved
+#define ISR0_PTX       (1 << 1)        // Packet transmitted successfully
+#define ISR0_RXE       (1 << 2)        // RX Error
+#define ISR0_TXE       (1 << 3)        // TX Error
+#define ISR0_TU        (1 << 4)        // Transmit buffer underflow
+#define ISR0_RU        (1 << 5)        // Recieve buffer link error
+#define ISR0_BE        (1 << 6)        // PCI Bus error
+#define ISR0_CNT       (1 << 7)        // CRC error / missed packet counter overflow
+
+#define ISR1_ERI       (1 << 0)        // Early recieve interrupt
+#define ISR1_UDFI      (1 << 1)        // TX FIFO underflow event
+#define ISR1_OVFI      (1 << 2)        // Recieve overflow
+#define ISR1_PKTR      (1 << 3)        // FIFO overflow (?"next packet race with current packet")
+#define ISR1_NORBF     (1 << 4)        // No more recieve buffers avaiable (overflow essentialy)
+#define ISR1_ABTI      (1 << 5)        // Transmission abort due to excessive collisions
+#define ISR1_SRCI      (1 << 6)        // Port state change
+#define ISR1_GENI      (1 << 7)        // General purpose interrupt
+
 // TODO: Other Regs?
 
 struct sRXDesc
@@ -73,7 +91,7 @@ struct sRXDesc
        Uint16  _resvd;
        Uint32  RXBufferStart;
        Uint32  RDBranchAddress;        // ? - I'm guessing it's the next descriptor in the chain
-};
+} PACKED;
 
 #define RSR_RERR       (1 << 0)        // Receiver error
 #define RSR_CRC        (1 << 1)        // CRC Error
@@ -100,7 +118,7 @@ struct sTXDesc
        Uint8   _resvd;
        Uint32  TXBufferStart;
        Uint32  TDBranchAddress;        // Bit 0: Disable interrupt
-};
+} PACKED;
 
 #define TD_TCR_CRC     (1 << 0)        // Disable CRC generation
 #define TD_TCR_STP     (1 << 5)        // First descriptor in packet

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