X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Modules%2FNetwork%2FRTL8139%2Frtl8139.c;h=707b2eb1937cbbeb6613e6554f5dadfb7f5b46e9;hb=71b1271511ad01f042d2e51673dd57cce1b0fd9c;hp=32aa7d4554edc9b75673bd02692f5a41a99b19e8;hpb=9cae7d64750db729b6bee582a8e7203ec3de36b4;p=tpg%2Facess2.git diff --git a/Modules/Network/RTL8139/rtl8139.c b/Modules/Network/RTL8139/rtl8139.c index 32aa7d45..707b2eb1 100644 --- a/Modules/Network/RTL8139/rtl8139.c +++ b/Modules/Network/RTL8139/rtl8139.c @@ -3,7 +3,7 @@ * - By John Hodge (thePowersGang) */ #define DEBUG 0 -#define VERSION ((0<<8)|50) +#define VERSION ((0<<8)|20) #include #include #include @@ -12,6 +12,9 @@ #include // === CONSTANTS === +#define VENDOR_ID 0x10EC +#define DEVICE_ID 0x8139 + enum eRTL8139_Regs { // MAC Address @@ -77,7 +80,9 @@ typedef struct sCard char *TransmitBuffers[4]; tPAddr PhysTransmitBuffers[4]; - BOOL TransmitInUse; // Flags for each transmit descriptor + tMutex TransmitInUse[4]; + tMutex CurTXProtector; //!< Protects \a .CurTXDescriptor + int CurTXDescriptor; char Name[2]; tVFS_Node Node; @@ -121,15 +126,25 @@ int RTL8139_Install(char **Options) Uint16 base; tCard *card; - giRTL8139_CardCount = PCI_CountDevices( 0x10EC, 0x8139, 0 ); + giRTL8139_CardCount = PCI_CountDevices(VENDOR_ID, DEVICE_ID); + Log_Debug("RTL8139", "%i cards", giRTL8139_CardCount); - gaRTL8139_Cards = calloc( giRTL8139_CardCount, sizeof(tCard) ); + if( giRTL8139_CardCount == 0 ) return MODULE_ERR_NOTNEEDED; + gaRTL8139_Cards = calloc( giRTL8139_CardCount, sizeof(tCard) ); - while( (id = PCI_GetDevice(0x10EC, 0x8139, 0, id)) != -1 ) + //while( (id = PCI_GetDevice(0x10EC, 0x8139, 0, id)) != -1 ) + while( (id = PCI_GetDevice(VENDOR_ID, DEVICE_ID, i)) != -1 ) { - base = PCI_AssignPort( id, 0, 0x100 ); card = &gaRTL8139_Cards[i]; + base = PCI_GetBAR( id, 0 ); + if( !(base & 1) ) { + Log_Warning("RTL8139", "Driver does not support MMIO, skipping card"); + card->IOBase = 0; + card->IRQ = 0; + continue ; + } + base &= ~1; card->IOBase = base; card->IRQ = PCI_GetIRQ( id ); @@ -146,7 +161,10 @@ int RTL8139_Install(char **Options) // Set up recieve buffer // - Allocate 3 pages below 4GiB for the recieve buffer (Allows 8k+16+1500) card->ReceiveBuffer = (void*)MM_AllocDMA( 3, 32, &card->PhysReceiveBuffer ); + card->ReceiveBufferLength = 8*1024; 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); @@ -156,7 +174,7 @@ int RTL8139_Install(char **Options) card->TransmitBuffers[1] = card->TransmitBuffers[0] + 0x800; card->PhysTransmitBuffers[1] = card->PhysTransmitBuffers[0] + 0x800; - card->TransmitBuffers[2] = (void*)MM_AllocDMA( 1, 32, &card->PhysTransmitBuffers[1] ); + card->TransmitBuffers[2] = (void*)MM_AllocDMA( 1, 32, &card->PhysTransmitBuffers[2] ); card->TransmitBuffers[3] = card->TransmitBuffers[2] + 0x800; card->PhysTransmitBuffers[3] = card->PhysTransmitBuffers[2] + 0x800; @@ -166,10 +184,10 @@ int RTL8139_Install(char **Options) outd(base + TSAD3, card->PhysTransmitBuffers[3]); // Set recieve buffer size and recieve mask - // - Bit 7 being unset tells the card to overflow the recieve buffer if needed + // - 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, 0x0F); + outd(base + RCR, 0x8F); // Recive Enable and Transmit Enable outb(base + CMD, 0x0C); @@ -192,14 +210,18 @@ int RTL8139_Install(char **Options) card->Node.Read = RTL8139_Read; card->Node.IOCtl = RTL8139_IOCtl; - Log_Log("RTL8139", "Card %i 0x%04x %02x:%02x:%02x:%02x:%02x:%02x", - i, base, + 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], card->MacAddr[3], card->MacAddr[4], card->MacAddr[5] ); i ++; } + + gRTL8139_DriverInfo.RootNode.Size = giRTL8139_CardCount; + DevFS_AddDevice( &gRTL8139_DriverInfo ); + return MODULE_ERR_OK; } @@ -214,7 +236,7 @@ char *RTL8139_ReadDir(tVFS_Node *Node, int Pos) 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[0] != '\0') return NULL; + 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; } @@ -222,10 +244,12 @@ tVFS_Node *RTL8139_FindDir(tVFS_Node *Node, const char *Filename) 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; } @@ -233,35 +257,55 @@ int RTL8139_RootIOCtl(tVFS_Node *Node, int ID, void *Data) Uint64 RTL8139_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) { tCard *card = Node->ImplPtr; - int read_ofs, pkt_length; + Uint16 read_ofs, pkt_length; + int new_read_ofs; + + ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); retry: - Semaphore_Wait( &card->ReadSemaphore, 1 ); + if( Semaphore_Wait( &card->ReadSemaphore, 1 ) != 1 ) + { + LEAVE_RET('i', 0); + } Mutex_Acquire( &card->ReadMutex ); - read_ofs = ind( card->IOBase + CAPR ) - card->PhysReceiveBuffer; + read_ofs = inw( card->IOBase + CAPR ); + LOG("raw read_ofs = %i", read_ofs); + read_ofs = (read_ofs + 0x10) & 0xFFFF; + LOG("read_ofs = %i", read_ofs); + + pkt_length = *(Uint16*)&card->ReceiveBuffer[read_ofs+2]; + + // Calculate new read offset + new_read_ofs = read_ofs + pkt_length + 4; + new_read_ofs = (new_read_ofs + 3) & ~3; // Align + if(new_read_ofs > card->ReceiveBufferLength) { + LOG("wrapping read_ofs"); + new_read_ofs -= card->ReceiveBufferLength; + } + 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 } - pkt_length = *(Uint16*)&card->ReceiveBuffer[read_ofs+2]; - // Get packet if( Length > pkt_length ) Length = pkt_length; memcpy(Buffer, &card->ReceiveBuffer[read_ofs+4], Length); - // Update read offset - read_ofs += pkt_length + 4; - read_ofs = (read_ofs + 3) & ~3; // Align - if(read_ofs > card->ReceiveBufferLength) read_ofs = 0; - outd(card->IOBase + CAPR, read_ofs + card->PhysReceiveBuffer); + // Update CAPR + outw(card->IOBase + CAPR, new_read_ofs); Mutex_Release( &card->ReadMutex ); + LEAVE('i', Length); + return Length; } @@ -273,18 +317,25 @@ Uint64 RTL8139_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer if( Length > 1500 ) return 0; // MTU exceeded - // TODO: Implement a semaphore for avaliable tranmit buffers + ENTER("pNode XLength pBuffer", Node, Length, Buffer); + // TODO: Implement a semaphore for avaliable transmit buffers + // Find an avaliable descriptor - do { - for( td = 0; td < 4; td ++ ) { - if( !(card->TransmitInUse & (1 << td)) ) - break; - } - } while(td == 4 && (Threads_Yield(),1)); + Mutex_Acquire(&card->CurTXProtector); + td = card->CurTXDescriptor; + card->CurTXDescriptor ++; + card->CurTXDescriptor %= 4; + Mutex_Release(&card->CurTXProtector); + // - Lock it + Mutex_Acquire( &card->TransmitInUse[td] ); + + LOG("td = %i", td); // Transmit using descriptor `td` - card->TransmitInUse |= (1 << 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); // Start @@ -292,18 +343,32 @@ Uint64 RTL8139_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer 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) - outd(card->IOBase + TSD0 + td, status); + LOG("status = 0x%08x", status); + outd(card->IOBase + TSD0 + td*4, status); - return 0; + 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); return 0; } @@ -311,25 +376,29 @@ void RTL8139_IRQHandler(int Num) { int i, j; tCard *card; - Uint8 status; + Uint16 status; + + LOG("Num = %i", Num); + for( i = 0; i < giRTL8139_CardCount; i ++ ) { card = &gaRTL8139_Cards[i]; if( Num != card->IRQ ) break; - status = inb(card->IOBase + ISR); + status = inw(card->IOBase + ISR); + LOG("status = 0x%02x", status); // Transmit OK, a transmit descriptor is now free if( status & FLAG_ISR_TOK ) { - outb(card->IOBase + ISR, FLAG_ISR_TOK); for( j = 0; j < 4; j ++ ) { - if( ind(card->IOBase + TSD0 + j) & 0x8000 ) { // TSD TOK - card->TransmitInUse &= ~(1 << j); + if( ind(card->IOBase + TSD0 + j*4) & 0x8000 ) { // TSD TOK + Mutex_Release( &card->TransmitInUse[j] ); // TODO: Update semaphore once implemented } } + outw(card->IOBase + ISR, FLAG_ISR_TOK); } // Recieve OK, inform read @@ -337,31 +406,60 @@ void RTL8139_IRQHandler(int Num) { int read_ofs, end_ofs; int packet_count = 0; + int len; // Scan recieve buffer for packets - end_ofs = ind(card->IOBase + CBA) - card->PhysReceiveBuffer; + end_ofs = inw(card->IOBase + CBA); read_ofs = card->SeenOfs; + LOG("read_ofs = %i, end_ofs = %i", read_ofs, end_ofs); if( read_ofs > end_ofs ) { while( read_ofs < card->ReceiveBufferLength ) { packet_count ++; - read_ofs += *(Uint16*)&card->ReceiveBuffer[read_ofs+1] + 2; + len = *(Uint16*)&card->ReceiveBuffer[read_ofs+2]; + LOG("%i 0x%x Pkt Hdr: 0x%04x, len: 0x%04x", + packet_count, read_ofs, + *(Uint16*)&card->ReceiveBuffer[read_ofs], + len + ); + if(len > 2000) { + Log_Warning("RTL8139", "IRQ: Packet in buffer exceeds sanity (%i>2000)", len); + } + read_ofs += len + 4; + read_ofs = (read_ofs + 3) & ~3; // Align } - read_ofs = 0; + read_ofs -= card->ReceiveBufferLength; + LOG("wrapped read_ofs"); } while( read_ofs < end_ofs ) { packet_count ++; - read_ofs += *(Uint16*)&card->ReceiveBuffer[read_ofs+1] + 2; + LOG("%i 0x%x Pkt Hdr: 0x%04x, len: 0x%04x", + packet_count, read_ofs, + *(Uint16*)&card->ReceiveBuffer[read_ofs], + *(Uint16*)&card->ReceiveBuffer[read_ofs+2] + ); + read_ofs += *(Uint16*)&card->ReceiveBuffer[read_ofs+2] + 4; + read_ofs = (read_ofs + 3) & ~3; // Align + } + if( read_ofs != end_ofs ) { + Log_Warning("RTL8139", "IRQ: read_ofs (%i) != end_ofs(%i)", read_ofs, end_ofs); + read_ofs = end_ofs; } card->SeenOfs = read_ofs; - Semaphore_Signal( &card->ReadSemaphore, packet_count ); + LOG("packet_count = %i, read_ofs = 0x%x", packet_count, read_ofs); + if( packet_count ) + { + if( Semaphore_Signal( &card->ReadSemaphore, packet_count ) != packet_count ) { + // Oops? + } VFS_MarkAvaliable( &card->Node, 1 ); + } - outb(card->IOBase + ISR, FLAG_ISR_ROK); + outw(card->IOBase + ISR, FLAG_ISR_ROK); } } }