From: John Hodge Date: Wed, 16 May 2012 03:01:40 +0000 (+0800) Subject: Modules/VIARhineII - RX and TX works, but TX is a hack atm X-Git-Tag: rel0.15~611^2~106 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=b0a26ff18cc1e7df2442a8a967017d8c81f1de38;p=tpg%2Facess2.git Modules/VIARhineII - RX and TX works, but TX is a hack atm --- diff --git a/KernelLand/Modules/Network/VIARhineII/rhine2.c b/KernelLand/Modules/Network/VIARhineII/rhine2.c index 4a152fef..3d8a4fa6 100644 --- a/KernelLand/Modules/Network/VIARhineII/rhine2.c +++ b/KernelLand/Modules/Network/VIARhineII/rhine2.c @@ -11,10 +11,13 @@ #include "rhine2_hw.h" #include +#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; -} - diff --git a/KernelLand/Modules/Network/VIARhineII/rhine2_hw.h b/KernelLand/Modules/Network/VIARhineII/rhine2_hw.h index dd3f9ac1..f6a92f47 100644 --- a/KernelLand/Modules/Network/VIARhineII/rhine2_hw.h +++ b/KernelLand/Modules/Network/VIARhineII/rhine2_hw.h @@ -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