X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Modules%2FNetwork%2FNE2000%2Fne2000.c;h=d05b2a339e01943fc8acdf898d4aca58961e5a62;hb=5f2024e5977e0cca0993a20dad5ab794c94d5711;hp=14314b8347b3aafe8139f6633ab81e9a4b34f8f8;hpb=2639d91d3b55b1ac724ae84793f389b8ffce363c;p=tpg%2Facess2.git diff --git a/Modules/Network/NE2000/ne2000.c b/Modules/Network/NE2000/ne2000.c index 14314b83..d05b2a33 100644 --- a/Modules/Network/NE2000/ne2000.c +++ b/Modules/Network/NE2000/ne2000.c @@ -3,13 +3,14 @@ * * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc */ -#define DEBUG 0 +#define DEBUG 1 #define VERSION ((0<<8)|50) #include #include #include #include -#include +#include +#include // === CONSTANTS === #define MEM_START 0x40 @@ -29,7 +30,7 @@ static const struct { {0x10EC, 0x8029}, // Realtek 8029 {0x10EC, 0x8129} // Realtek 8129 }; -#define NUM_COMPAT_DEVICES (sizeof(csaCOMPAT_DEVICES)/sizeof(csaCOMPAT_DEVICES[0])) +#define NUM_COMPAT_DEVICES ((int)(sizeof(csaCOMPAT_DEVICES)/sizeof(csaCOMPAT_DEVICES[0]))) enum eNe2k_Page0Read { CMD = 0, //!< the master command register @@ -70,39 +71,47 @@ typedef struct sNe2k_Card { Uint16 IOBase; //!< IO Port Address from PCI Uint8 IRQ; //!< IRQ Assigned from PCI - int NumWaitingPackets; - int NextRXPage; + tSemaphore Semaphore; //!< Semaphore for incoming packets + int NextRXPage; //!< Next expected RX page int NextMemPage; //!< Next Card Memory page to use - - Uint8 Buffer[RX_BUF_SIZE*256]; - + char Name[2]; // "0" - tVFS_Node Node; - Uint8 MacAddr[6]; + tVFS_Node Node; //!< VFS Node + Uint8 MacAddr[6]; //!< Cached MAC address } tCard; // === PROTOTYPES === int Ne2k_Install(char **Arguments); char *Ne2k_ReadDir(tVFS_Node *Node, int Pos); -tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, char *Name); +tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, const char *Name); int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data); -Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); +Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buffer); Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); + + int Ne2k_int_ReadDMA(tCard *Card, int FirstPage, int NumPages, void *Buffer); Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length); -void Ne2k_IRQHandler(int IntNum); +void Ne2k_IRQHandler(int IntNum, void *Ptr); // === GLOBALS === MODULE_DEFINE(0, VERSION, Ne2k, Ne2k_Install, NULL, NULL); +tVFS_NodeType gNe2K_RootNodeType = { + .ReadDir = Ne2k_ReadDir, + .FindDir = Ne2k_FindDir, + .IOCtl = Ne2k_IOCtl + }; +tVFS_NodeType gNe2K_DevNodeType = { + .Write = Ne2k_Write, + .Read = Ne2k_Read, + .IOCtl = Ne2k_IOCtl + }; tDevFS_Driver gNe2k_DriverInfo = { NULL, "ne2k", { .NumACLs = 1, .ACLs = &gVFS_ACL_EveryoneRX, .Flags = VFS_FFLAG_DIRECTORY, - .ReadDir = Ne2k_ReadDir, - .FindDir = Ne2k_FindDir, - .IOCtl = Ne2k_IOCtl + .Type = &gNe2K_RootNodeType } }; Uint16 gNe2k_BaseAddress; @@ -117,35 +126,38 @@ tCard *gpNe2k_Cards = NULL; int Ne2k_Install(char **Options) { int i, j, k; - int count, id, base; + int count, base; + tPCIDev id; // --- Scan PCI Bus --- // Count Cards giNe2k_CardCount = 0; for( i = 0; i < NUM_COMPAT_DEVICES; i ++ ) { - giNe2k_CardCount += PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0 ); + giNe2k_CardCount += PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device ); } + if( giNe2k_CardCount == 0 ) return MODULE_ERR_NOTNEEDED; + // Enumerate Cards k = 0; gpNe2k_Cards = calloc( giNe2k_CardCount, sizeof(tCard) ); for( i = 0; i < NUM_COMPAT_DEVICES; i ++ ) { - count = PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0 ); + count = PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device ); for( j = 0; j < count; j ++,k ++ ) { - id = PCI_GetDevice( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0, j ); + id = PCI_GetDevice( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, j ); // Create Structure - base = PCI_AssignPort( id, 0, 0x20 ); + base = PCI_GetBAR( id, 0 ); gpNe2k_Cards[ k ].IOBase = base; gpNe2k_Cards[ k ].IRQ = PCI_GetIRQ( id ); gpNe2k_Cards[ k ].NextMemPage = 64; gpNe2k_Cards[ k ].NextRXPage = RX_FIRST; // Install IRQ Handler - IRQ_AddHandler(gpNe2k_Cards[ k ].IRQ, Ne2k_IRQHandler); + IRQ_AddHandler(gpNe2k_Cards[ k ].IRQ, Ne2k_IRQHandler, &gpNe2k_Cards[k]); // Reset Card outb( base + 0x1F, inb(base + 0x1F) ); @@ -157,17 +169,17 @@ int Ne2k_Install(char **Options) outb( base + CURR, RX_FIRST ); // Current RX page outb( base + CMD, 0x21 ); // No DMA and Stop outb( base + DCR, 0x49 ); // Set WORD mode - outb( base + IMR, 0x00 ); + outb( base + IMR, 0x00 ); // Interrupt Mask Register outb( base + ISR, 0xFF ); outb( base + RCR, 0x20 ); // Reciever to Monitor outb( base + TCR, 0x02 ); // Transmitter OFF (TCR.LB = 1, Internal Loopback) + + // Read MAC Address outb( base + RBCR0, 6*4 ); // Remote Byte Count outb( base + RBCR1, 0 ); outb( base + RSAR0, 0 ); // Clear Source Address outb( base + RSAR1, 0 ); outb( base + CMD, 0x0A ); // Remote Read, Start - - // Read MAC Address gpNe2k_Cards[ k ].MacAddr[0] = inb(base+0x10);// inb(base+0x10); gpNe2k_Cards[ k ].MacAddr[1] = inb(base+0x10);// inb(base+0x10); gpNe2k_Cards[ k ].MacAddr[2] = inb(base+0x10);// inb(base+0x10); @@ -184,22 +196,12 @@ int Ne2k_Install(char **Options) outb( base+RCR, 0x0F ); // Set WRAP and allow all packet matches outb( base+TCR, 0x00 ); // Set Normal Transmitter mode outb( base+TPSR, 0x40); // Set Transmit Start - // Set MAC Address - /* - Ne2k_WriteReg(base, MAC0, gpNe2k_Cards[ k ].MacAddr[0]); - Ne2k_WriteReg(base, MAC1, gpNe2k_Cards[ k ].MacAddr[1]); - Ne2k_WriteReg(base, MAC2, gpNe2k_Cards[ k ].MacAddr[2]); - Ne2k_WriteReg(base, MAC3, gpNe2k_Cards[ k ].MacAddr[3]); - Ne2k_WriteReg(base, MAC4, gpNe2k_Cards[ k ].MacAddr[4]); - Ne2k_WriteReg(base, MAC5, gpNe2k_Cards[ k ].MacAddr[5]); - */ - Log("[NE2K]: Card #%i: IRQ=%i, IOBase=0x%x", - k, gpNe2k_Cards[ k ].IRQ, gpNe2k_Cards[ k ].IOBase); - Log("MAC Address %x:%x:%x:%x:%x:%x", - gpNe2k_Cards[ k ].MacAddr[0], gpNe2k_Cards[ k ].MacAddr[1], - gpNe2k_Cards[ k ].MacAddr[2], gpNe2k_Cards[ k ].MacAddr[3], - gpNe2k_Cards[ k ].MacAddr[4], gpNe2k_Cards[ k ].MacAddr[5] + Log_Log("Ne2k", "Card %i 0x%04x IRQ%i %02x:%02x:%02x:%02x:%02x:%02x", + k, base, gpNe2k_Cards[ k ].IRQ, + gpNe2k_Cards[k].MacAddr[0], gpNe2k_Cards[k].MacAddr[1], + gpNe2k_Cards[k].MacAddr[2], gpNe2k_Cards[k].MacAddr[3], + gpNe2k_Cards[k].MacAddr[4], gpNe2k_Cards[k].MacAddr[5] ); // Set VFS Node @@ -208,15 +210,17 @@ int Ne2k_Install(char **Options) gpNe2k_Cards[ k ].Node.ImplPtr = &gpNe2k_Cards[ k ]; gpNe2k_Cards[ k ].Node.NumACLs = 0; // Root Only gpNe2k_Cards[ k ].Node.CTime = now(); - gpNe2k_Cards[ k ].Node.Write = Ne2k_Write; - gpNe2k_Cards[ k ].Node.Read = Ne2k_Read; - gpNe2k_Cards[ k ].Node.IOCtl = Ne2k_IOCtl; + gpNe2k_Cards[ k ].Node.Type = &gNe2K_DevNodeType; + + // Initialise packet semaphore + // - Start at zero, no max + Semaphore_Init( &gpNe2k_Cards[k].Semaphore, 0, 0, "NE2000", gpNe2k_Cards[ k ].Name ); } } gNe2k_DriverInfo.RootNode.Size = giNe2k_CardCount; DevFS_AddDevice( &gNe2k_DriverInfo ); - return 1; + return MODULE_ERR_OK; } /** @@ -232,9 +236,9 @@ char *Ne2k_ReadDir(tVFS_Node *Node, int Pos) } /** - * \fn tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, char *Name) + * \fn tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, const char *Name) */ -tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, char *Name) +tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, const char *Name) { if(Name[0] == '\0' || Name[1] != '\0') return NULL; @@ -248,27 +252,10 @@ static const char *casIOCtls[] = { DRV_IOCTLNAMES, DRV_NETWORK_IOCTLNAMES, NULL */ int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data) { - int tmp; ENTER("pNode iID pData", Node, ID, Data); switch( ID ) { - case DRV_IOCTL_TYPE: - LEAVE('i', DRV_TYPE_NETWORK); - return DRV_TYPE_NETWORK; - - case DRV_IOCTL_IDENT: - tmp = ModUtil_SetIdent(Data, "Ne2k"); - LEAVE('i', tmp); - return tmp; - - case DRV_IOCTL_VERSION: - LEAVE('x', VERSION); - return VERSION; - - case DRV_IOCTL_LOOKUP: - tmp = ModUtil_LookupString( (char**)casIOCtls, Data ); - LEAVE('i', tmp); - return tmp; + BASE_IOCTLS(DRV_TYPE_NETWORK, "NE2000", VERSION, casIOCtls); } // If this is the root, return @@ -294,21 +281,24 @@ int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data) } /** - * \fn Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) + * \fn Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buffer) * \brief Send a packet from the network card */ -Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) +Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buffer) { tCard *Card = (tCard*)Node->ImplPtr; - Uint16 *buf = Buffer; + const Uint16 *buf = Buffer; int rem = Length; int page; ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); + // TODO: Lock + // Sanity Check Length if(Length > TX_BUF_SIZE*256) { - Warning( + Log_Warning( + "Ne2k", "Ne2k_Write - Attempting to send over TX_BUF_SIZE*256 (%i) bytes (%i)", TX_BUF_SIZE*256, Length ); @@ -322,7 +312,7 @@ Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) // Clear Remote DMA Flag outb(Card->IOBase + ISR, 0x40); // Bit 6 - // Send Size - Remote Byte Count Register + // Send Size - Transfer Byte Count Register outb(Card->IOBase + TBCR0, Length & 0xFF); outb(Card->IOBase + TBCR1, Length >> 8); @@ -335,7 +325,6 @@ Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) page = Ne2k_int_GetWritePage(Card, Length); outb(Card->IOBase + RSAR1, page); // Page Offset // Start - //outb(Card->IOBase + CMD, 0|0x18|0x4|0x2); // Page 0, Transmit Packet, TXP, Start outb(Card->IOBase + CMD, 0|0x10|0x2); // Page 0, Remote Write, Start // Send Data @@ -343,7 +332,7 @@ Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) outw(Card->IOBase + 0x10, *buf++); } - while( inb(Card->IOBase + ISR) == 0 ) // Wait for Remote DMA Complete + while( !(inb(Card->IOBase + ISR) & 0x40) ) // Wait for Remote DMA Complete ; //Proc_Yield(); outb( Card->IOBase + ISR, 0x40 ); // ACK Interrupt @@ -368,7 +357,6 @@ Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) tCard *Card = (tCard*)Node->ImplPtr; Uint8 page; Uint8 data[256]; - int i; struct { Uint8 Status; Uint8 NextPacketPage; @@ -377,31 +365,27 @@ Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); - while(Card->NumWaitingPackets == 0) Threads_Yield(); + // Wait for packets + if( Semaphore_Wait( &Card->Semaphore, 1 ) != 1 ) + { + // Error or interrupted + LEAVE_RET('i', 0); + } - // Make sure that the card is in page 0 - outb(Card->IOBase + CMD, 0|0x22); // Page 0, Start, NoDMA + outb(Card->IOBase, 0x22 | (1 << 6)); // Page 6 + LOG("CURR : 0x%02x", inb(Card->IOBase + CURR)); - // Get BOUNDARY + // Get current read page page = Card->NextRXPage; + LOG("page = %i", page); - // Set up transfer - outb(Card->IOBase + RBCR0, 0); - outb(Card->IOBase + RBCR1, 1); // 256-bytes - outb(Card->IOBase + RSAR0, 0x00); // Page Offset - outb(Card->IOBase + RSAR1, page); // Page Number - - outb(Card->IOBase + CMD, 0|0x08|0x2); // Page 0, Remote Read, Start - - // Clear Remote DMA Flag - outb(Card->IOBase + ISR, 0x40); // Bit 6 - - // Read data - for(i = 0; i < 128; i ++) - ((Uint16*)data)[i] = inw(Card->IOBase + 0x10); + Ne2k_int_ReadDMA(Card, page, 1, data); pktHdr = (void*)data; - //Log("Ne2k_Read: Recieved packet (%i bytes)", pktHdr->Length); + + LOG("pktHdr->Status = 0x%x", pktHdr->Status); + LOG("pktHdr->NextPacketPage = %i", pktHdr->NextPacketPage); + LOG("pktHdr->Length = 0x%03x", pktHdr->Length); // Have we read all the required bytes yet? if(pktHdr->Length < 256 - 4) @@ -409,56 +393,104 @@ Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) if(Length > pktHdr->Length) Length = pktHdr->Length; memcpy(Buffer, &data[4], Length); - page ++; - if(page == RX_LAST+1) page = RX_FIRST; } // No? oh damn, now we need to allocate a buffer - else { - int j = 256/2; - char *buf = malloc( (pktHdr->Length + 4 + 255) & ~255 ); + else + { + int pages = pktHdr->NextPacketPage - page; + char *buf = malloc( pages*256 ); - if(!buf) { - LEAVE('i', -1); - return -1; - } + LOG("pktHdr->Length (%i) > 256 - 4, allocated buffer %p", pktHdr->Length, buf); + + if(!buf) LEAVE_RET('i', -1); + // Copy the already read data memcpy(buf, data, 256); + // Read all the needed pages page ++; - while(page != pktHdr->NextPacketPage) + if(page == RX_LAST+1) page = RX_FIRST; + + if( page + pages > RX_LAST ) { - if(page == RX_LAST+1) page = RX_FIRST; - - outb(Card->IOBase + RBCR0, 0); - outb(Card->IOBase + RBCR1, 1); // 256-bytes - outb(Card->IOBase + RSAR0, 0x00); // Page Offset - outb(Card->IOBase + RSAR1, page); // Page Number - outb(Card->IOBase + CMD, 0|0x08|0x2); // Page 0, Remote Read, Start - - for(i = 0; i < 128; i ++) - ((Uint16*)buf)[j+i] = inw(Card->IOBase + 0x10); - j += 128; - page ++; + int first_count = RX_LAST+1 - page; + int tmp = 0; + tmp += Ne2k_int_ReadDMA(Card, page, first_count, buf+256); + tmp += Ne2k_int_ReadDMA(Card, RX_FIRST, pages-1-first_count, buf+(first_count+1)*256); + LOG("composite return count = %i", tmp); } + else + Ne2k_int_ReadDMA(Card, page, pages-1, buf+256); + // Wrap length to the packet length if(Length > pktHdr->Length) Length = pktHdr->Length; + else if( Length < pktHdr->Length ) { + Log_Warning("NE2000", "Packet truncated! (%i bytes truncated to %i)", + pktHdr->Length, Length); + } memcpy(Buffer, &buf[4], Length); + + free(buf); } - // Write BNRY - if(page == RX_FIRST) - outb( Card->IOBase + BNRY, RX_LAST ); + // Write BNRY (maximum page for incoming packets) + if(pktHdr->NextPacketPage == RX_FIRST) + outb( Card->IOBase + BNRY, RX_LAST-1 ); else - outb( Card->IOBase + BNRY, page-1 ); + outb( Card->IOBase + BNRY, pktHdr->NextPacketPage-1 ); // Set next RX Page and decrement the waiting list - Card->NextRXPage = page; - Card->NumWaitingPackets --; + Card->NextRXPage = pktHdr->NextPacketPage; LEAVE('i', Length); return Length; } +int Ne2k_int_ReadDMA(tCard *Card, int FirstPage, int NumPages, void *Buffer) +{ + int i; + + // Sanity check + if( !(0 <= FirstPage && FirstPage < 256) ) { + Log_Warning("NE2000", "Ne2k_int_ReadDMA: BUG - FirstPage(%i) not 8-bit", FirstPage); + return -1; + } + if( !(0 <= NumPages && NumPages < 256) ) { + Log_Warning("NE2000", "Ne2k_int_ReadDMA: BUG - NumPages(%i) not 8-bit", NumPages); + return -1; + } + + ENTER("pCard iFirstPage iNumPages pBuffer", Card, FirstPage, NumPages, Buffer); + + // Make sure that the card is in bank 0 + outb(Card->IOBase + CMD, 0|0x22); // Bank 0, Start, NoDMA + outb(Card->IOBase + ISR, 0x40); // Clear Remote DMA Flag + + // Set up transfer + outb(Card->IOBase + RBCR0, 0); + outb(Card->IOBase + RBCR1, NumPages); // page count + outb(Card->IOBase + RSAR0, 0x00); // Page Offset + outb(Card->IOBase + RSAR1, FirstPage); // Page Number + outb(Card->IOBase + CMD, 0|0x08|0x2); // Bank 0, Remote Read, Start + + // TODO: Less expensive + //while( !(inb(Card->IOBase + ISR) & 0x40) ) { + // HALT(); + // LOG("inb(ISR) = 0x%02x", inb(Card->IOBase + ISR)); + //} + HALT(); // Small delay? + + // Read data + for(i = 0; i < 128*NumPages; i ++) + ((Uint16*)Buffer)[i] = inw(Card->IOBase + 0x10); + + + outb(Card->IOBase + ISR, 0x40); // Clear Remote DMA Flag + + LEAVE('i', NumPages); + return NumPages; +} + /** * \fn Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length) */ @@ -477,34 +509,35 @@ Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length) /** * \fn void Ne2k_IRQHandler(int IntNum) */ -void Ne2k_IRQHandler(int IntNum) +void Ne2k_IRQHandler(int IntNum, void *Ptr) { - int i; Uint8 byte; - for( i = 0; i < giNe2k_CardCount; i++ ) - { - if(gpNe2k_Cards[i].IRQ == IntNum) - { - byte = inb( gpNe2k_Cards[i].IOBase + ISR ); + tCard *card = Ptr; + + if(card->IRQ != IntNum) return; + + byte = inb( card->IOBase + ISR ); + + LOG("byte = 0x%02x", byte); + - // 0: Packet recieved (no error) - if( byte & 1 ) - { - gpNe2k_Cards[i].NumWaitingPackets ++; - if( gpNe2k_Cards[i].NumWaitingPackets > MAX_PACKET_QUEUE ) - gpNe2k_Cards[i].NumWaitingPackets = MAX_PACKET_QUEUE; - } - // 1: Packet sent (no error) - // 2: Recieved with error - // 3: Transmission Halted (Excessive Collisions) - // 4: Recieve Buffer Exhausted - // 5: - // 6: Remote DMA Complete - // 7: Reset - //LOG("Clearing interrupts on card %i (was 0x%x)\n", i, byte); - outb( gpNe2k_Cards[i].IOBase + ISR, 0xFF ); // Reset All - return ; + // Reset All (save for RDMA), that's polled + outb( card->IOBase + ISR, 0xFF&(~0x40) ); + + // 0: Packet recieved (no error) + if( byte & 1 ) + { + //if( card->NumWaitingPackets > MAX_PACKET_QUEUE ) + // card->NumWaitingPackets = MAX_PACKET_QUEUE; + if( Semaphore_Signal( &card->Semaphore, 1 ) != 1 ) { + // Oops? } } - Warning("[NE2K ] Recieved Unknown IRQ %i", IntNum); + // 1: Packet sent (no error) + // 2: Recieved with error + // 3: Transmission Halted (Excessive Collisions) + // 4: Recieve Buffer Exhausted + // 5: + // 6: Remote DMA Complete + // 7: Reset }