X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FModules%2FNetwork%2FVIARhineII%2Frhine2.c;h=f9f4d254d0e9b5b335f7bddfd0e1cb2df91101a3;hb=e02f66c7125bf18f77c6c53587238cbd49da2c89;hp=4a152fef0b1d1898a3c6406271d2ef13794b3da7;hpb=761956dfbdf60c0289a3133cab7bb939f98e70b5;p=tpg%2Facess2.git diff --git a/KernelLand/Modules/Network/VIARhineII/rhine2.c b/KernelLand/Modules/Network/VIARhineII/rhine2.c index 4a152fef..f9f4d254 100644 --- a/KernelLand/Modules/Network/VIARhineII/rhine2.c +++ b/KernelLand/Modules/Network/VIARhineII/rhine2.c @@ -11,10 +11,14 @@ #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_RX_BUF_PER_PAGE (PAGE_SIZE/RX_BUF_SIZE) +#define N_RX_BUF_PAGES ((N_RX_DESCS*RX_BUF_SIZE)/PAGE_SIZE) +#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,22 +31,21 @@ typedef struct sCard Uint8 IRQ; tSemaphore ReadSemaphore; + tSemaphore SendSemaphore; struct { Uint32 Phys; void *Virt; - } RXBuffers[N_RX_PAGES]; + } RXBuffers[N_RX_BUF_PAGES]; Uint32 DescTablePhys; void *DescTable; struct sTXDesc *TXDescs; + int NextTX; + int nFreeTX; - struct sTXDesc *FirstTX; - struct sTXDesc *LastTX; // Most recent unsent packet - - struct sRXDesc *FirstRX; // Most recent unread packet - struct sRXDesc *LastRX; // End of RX descriptor queue + struct sRXDesc *NextRX; // Most recent unread packet void *IPHandle; Uint8 MacAddr[6]; @@ -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,7 @@ int Rhine2_Install(char **Options) tCard *card; giRhine2_CardCount = PCI_CountDevices(VENDOR_ID, DEVICE_ID); - Log_Debug("Rhine2", "%i cards", giRhine2_CardCount); - + Log_Debug("Rhine2", "giRhine2_CardCount = %i", giRhine2_CardCount); if( giRhine2_CardCount == 0 ) return MODULE_ERR_NOTNEEDED; gaRhine2_Cards = calloc( giRhine2_CardCount, sizeof(tCard) ); @@ -113,6 +114,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,18 +138,21 @@ 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 ++ ) + for( int i = 0; i < N_RX_BUF_PAGES; i ++ ) { Card->RXBuffers[i].Virt = (void*)MM_AllocDMA(1, 32, &phys); Card->RXBuffers[i].Phys = phys; } + LOG("Allocating and filling RX/TX Descriptors"); Card->DescTable = (void*)MM_AllocDMA(1, 32, &phys); Card->DescTablePhys = phys; @@ -156,25 +162,41 @@ void Rhine2_int_InitialiseCard(tCard *Card) { rxdescs[i].RSR = 0; 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].RXBufferStart = Card->RXBuffers[i/N_RX_BUF_PER_PAGE].Phys + + (i % N_RX_BUF_PER_PAGE) * RX_BUF_SIZE; + rxdescs[i].RDBranchAddress = Card->DescTablePhys + (i+1) * DESC_SIZE; rxdescs[i].Length = (1 << 15); // set OWN + LOG("RX Desc %p = {Buf:0x%8x, Next:0x%x}", rxdescs, + rxdescs[i].RXBufferStart, rxdescs[i].RDBranchAddress + ); } - rxdescs[ N_RX_DESCS - 1 ].RDBranchAddress = 0; - Card->FirstRX = &rxdescs[0]; - Card->LastRX = &rxdescs[N_RX_DESCS - 1]; + rxdescs[ N_RX_DESCS - 1 ].RDBranchAddress = Card->DescTablePhys; + Card->NextRX = &rxdescs[0]; 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)); + + LOG("RX started"); + outb(Card->IOBase + REG_CR0, CR0_BASEVAL); + outb(Card->IOBase + REG_CR1, 0); // Disabled TX polling only? - outb(Card->IOBase + REG_CR0, CR0_STRT|CR0_RXON); + LOG("ISR state: %02x %02x", inb(Card->IOBase + REG_ISR0), inb(Card->IOBase + REG_ISR1)); } // --- File Functions --- @@ -187,6 +209,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'); @@ -194,9 +217,12 @@ tIPStackBuffer *Rhine2_WaitPacket(void *Ptr) } nDesc = 0; - desc = card->FirstRX; - while( desc->BufferSize & (1 << 15) ) + desc = card->NextRX; + 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 ++; } @@ -204,8 +230,8 @@ tIPStackBuffer *Rhine2_WaitPacket(void *Ptr) LOG("%i descriptors in packet", nDesc); ret = IPStack_Buffer_CreateBuffer(nDesc); - desc = card->FirstRX; - while( desc->BufferSize & (1 << 15) ) + desc = card->NextRX; + while( !(desc->Length & (1 << 15)) ) { void *data = Rhine2_int_GetBufferFromPhys(card, desc->RXBufferStart); IPStack_Buffer_AppendSubBuffer(ret, @@ -214,7 +240,7 @@ tIPStackBuffer *Rhine2_WaitPacket(void *Ptr) ); desc = Rhine2_int_GetDescFromPhys(card, desc->RDBranchAddress); } - card->FirstRX = desc; + card->NextRX = desc; LEAVE('p', ret); return ret; @@ -225,66 +251,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( 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); - 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 ) - ; + first_desc->TSR |= TD_TSR_OWN; + + LOG("%i descriptors allocated, first = %p, last = %p", nDescs, first_desc, last_desc); + + + 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 --- @@ -298,7 +409,7 @@ struct sRXDesc *Rhine2_int_GetDescFromPhys(tCard *Card, Uint32 Addr) void *Rhine2_int_GetBufferFromPhys(tCard *Card, Uint32 Addr) { - for( int i = 0; i < N_RX_PAGES; i ++ ) + for( int i = 0; i < N_RX_BUF_PAGES; i ++ ) { if( Card->RXBuffers[i].Phys > Addr ) continue; if( Card->RXBuffers[i].Phys + PAGE_SIZE <= Addr ) continue; @@ -310,19 +421,10 @@ void *Rhine2_int_GetBufferFromPhys(tCard *Card, Uint32 Addr) void Rhine2_int_FreeRXDesc(void *Ptr, size_t u1, size_t u2, const void *u3) { struct sRXDesc *desc = Ptr; + + LOG("Descriptor %p returned to card", desc); desc->RSR = 0; 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; -} -