X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FModules%2FNetwork%2FNE2000%2Fne2000.c;h=c8ea019eea998d300112a5e1bf02e54ea856647c;hb=845b6f9d90bb87b5e760e4d49aa93b0e003ab750;hp=d05b2a339e01943fc8acdf898d4aca58961e5a62;hpb=51ab5f489bc356940c95cc936fd0508e8f07ea97;p=tpg%2Facess2.git diff --git a/KernelLand/Modules/Network/NE2000/ne2000.c b/KernelLand/Modules/Network/NE2000/ne2000.c index d05b2a33..c8ea019e 100644 --- a/KernelLand/Modules/Network/NE2000/ne2000.c +++ b/KernelLand/Modules/Network/NE2000/ne2000.c @@ -1,16 +1,16 @@ -/* Acess2 - * NE2000 Driver +/* + * Acess2 NE2000 Driver + * - By John Hodge (thePowersGang) * * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc */ #define DEBUG 1 -#define VERSION ((0<<8)|50) +#define VERSION VER2(0,6) #include #include -#include #include -#include #include +#include // === CONSTANTS === #define MEM_START 0x40 @@ -76,18 +76,15 @@ typedef struct sNe2k_Card { int NextMemPage; //!< Next Card Memory page to use - char Name[2]; // "0" - tVFS_Node Node; //!< VFS Node + void *IPStackHandle; 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, const char *Name); - int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data); -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_SendPacket(void *Ptr, tIPStackBuffer *Buffer); +tIPStackBuffer *Ne2k_WaitForPacket(void *Ptr); int Ne2k_int_ReadDMA(tCard *Card, int FirstPage, int NumPages, void *Buffer); Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length); @@ -95,26 +92,13 @@ 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, - .Type = &gNe2K_RootNodeType - } +tIPStack_AdapterType gNe2k_AdapterType = { + .Name = "Ne2k", + .Type = 0, // TODO: Differentiate differnet wire protos and speeds + .Flags = 0, // TODO: IP checksum offloading, MAC checksum offloading etc + .SendPacket = Ne2k_SendPacket, + .WaitForPacket = Ne2k_WaitForPacket }; -Uint16 gNe2k_BaseAddress; int giNe2k_CardCount = 0; tCard *gpNe2k_Cards = NULL; @@ -136,8 +120,9 @@ int Ne2k_Install(char **Options) { giNe2k_CardCount += PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device ); } - if( giNe2k_CardCount == 0 ) return MODULE_ERR_NOTNEEDED; + + LOG("%i NE2K cards found", giNe2k_CardCount); // Enumerate Cards k = 0; @@ -146,24 +131,35 @@ int Ne2k_Install(char **Options) for( i = 0; i < NUM_COMPAT_DEVICES; i ++ ) { count = PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device ); - for( j = 0; j < count; j ++,k ++ ) + for( j = 0; j < count; j ++, k ++ ) { + tCard *card = &gpNe2k_Cards[k]; + id = PCI_GetDevice( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, j ); // Create Structure 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; + LOG("%i: %i/%i id = %i, base = 0x%x", k, i, j, id, base); + if( !(base & 1) ) { + Log_Warning("Ne2k", "PCI %i's BARs are incorrect (BAR0 is not IO)", id); + continue ; + } + base &= ~1; + card->IOBase = base; + card->IRQ = PCI_GetIRQ( id ); + card->NextMemPage = 64; + card->NextRXPage = RX_FIRST; // Install IRQ Handler - IRQ_AddHandler(gpNe2k_Cards[ k ].IRQ, Ne2k_IRQHandler, &gpNe2k_Cards[k]); + IRQ_AddHandler(card->IRQ, Ne2k_IRQHandler, &gpNe2k_Cards[k]); + LOG("%i: IRQ %i mapped, IOBase = 0x%x", k, card->IRQ, card->IOBase); // Reset Card outb( base + 0x1F, inb(base + 0x1F) ); - while( (inb( base+ISR ) & 0x80) == 0 ); + while( (inb( base + ISR ) & 0x80) == 0 ); outb( base + ISR, 0x80 ); - + + LOG("Reset done"); + // Initialise Card outb( base + CMD, 0x40|0x21 ); // Page 1, No DMA, Stop outb( base + CURR, RX_FIRST ); // Current RX page @@ -180,12 +176,12 @@ int Ne2k_Install(char **Options) outb( base + RSAR0, 0 ); // Clear Source Address outb( base + RSAR1, 0 ); outb( base + CMD, 0x0A ); // Remote Read, Start - 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); - gpNe2k_Cards[ k ].MacAddr[3] = inb(base+0x10);// inb(base+0x10); - gpNe2k_Cards[ k ].MacAddr[4] = inb(base+0x10);// inb(base+0x10); - gpNe2k_Cards[ k ].MacAddr[5] = inb(base+0x10);// inb(base+0x10); + card->MacAddr[0] = inb(base+0x10);// inb(base+0x10); + card->MacAddr[1] = inb(base+0x10);// inb(base+0x10); + card->MacAddr[2] = inb(base+0x10);// inb(base+0x10); + card->MacAddr[3] = inb(base+0x10);// inb(base+0x10); + card->MacAddr[4] = inb(base+0x10);// inb(base+0x10); + card->MacAddr[5] = inb(base+0x10);// inb(base+0x10); outb( base+PSTART, RX_FIRST); // Set Receive Start outb( base+BNRY, RX_LAST-1); // Set Boundary Page @@ -198,112 +194,49 @@ int Ne2k_Install(char **Options) outb( base+TPSR, 0x40); // Set Transmit Start 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] + k, base, card->IRQ, + card->MacAddr[0], card->MacAddr[1], + card->MacAddr[2], card->MacAddr[3], + card->MacAddr[4], card->MacAddr[5] ); - // Set VFS Node - gpNe2k_Cards[ k ].Name[0] = '0'+k; - gpNe2k_Cards[ k ].Name[1] = '\0'; - 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.Type = &gNe2K_DevNodeType; + card->IPStackHandle = IPStack_Adapter_Add(&gNe2k_AdapterType, card, card->MacAddr); // Initialise packet semaphore // - Start at zero, no max - Semaphore_Init( &gpNe2k_Cards[k].Semaphore, 0, 0, "NE2000", gpNe2k_Cards[ k ].Name ); + char name[10]; + sprintf(name, "%i", k-1); + Semaphore_Init( &card->Semaphore, 0, 0, "NE2000", name ); } } - gNe2k_DriverInfo.RootNode.Size = giNe2k_CardCount; - DevFS_AddDevice( &gNe2k_DriverInfo ); return MODULE_ERR_OK; } /** - * \fn char *Ne2k_ReadDir(tVFS_Node *Node, int Pos) - */ -char *Ne2k_ReadDir(tVFS_Node *Node, int Pos) -{ - char ret[2]; - if(Pos < 0 || Pos >= giNe2k_CardCount) return NULL; - ret[0] = '0'+Pos; - ret[1] = '\0'; - return strdup(ret); -} - -/** - * \fn tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, const char *Name) - */ -tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, const char *Name) -{ - if(Name[0] == '\0' || Name[1] != '\0') return NULL; - - return &gpNe2k_Cards[ Name[0]-'0' ].Node; -} - -static const char *casIOCtls[] = { DRV_IOCTLNAMES, DRV_NETWORK_IOCTLNAMES, NULL }; -/** - * \fn int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data) - * \brief IOCtl calls for a network device - */ -int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data) -{ - ENTER("pNode iID pData", Node, ID, Data); - switch( ID ) - { - BASE_IOCTLS(DRV_TYPE_NETWORK, "NE2000", VERSION, casIOCtls); - } - - // If this is the root, return - if( Node == &gNe2k_DriverInfo.RootNode ) { - LEAVE('i', 0); - return 0; - } - - // Device specific settings - switch( ID ) - { - case NET_IOCTL_GETMAC: - if( !CheckMem(Data, 6) ) { - LEAVE('i', -1); - return -1; - } - memcpy( Data, ((tCard*)Node->ImplPtr)->MacAddr, 6 ); - LEAVE('i', 1); - return 1; - } - LEAVE('i', 0); - return 0; -} - -/** - * \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, const void *Buffer) +int Ne2k_SendPacket(void *Ptr, tIPStackBuffer *Buffer) { - tCard *Card = (tCard*)Node->ImplPtr; - const Uint16 *buf = Buffer; - int rem = Length; + tCard *Card = Ptr; + int length; int page; - ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); + ENTER("pPtr pBuffer", Ptr, Buffer); + length = IPStack_Buffer_GetLength(Buffer); + // TODO: Lock // Sanity Check Length - if(Length > TX_BUF_SIZE*256) { + if(length > TX_BUF_SIZE*256) { Log_Warning( "Ne2k", "Ne2k_Write - Attempting to send over TX_BUF_SIZE*256 (%i) bytes (%i)", - TX_BUF_SIZE*256, Length + TX_BUF_SIZE*256, length ); - LEAVE('i', 0); - return 0; + LEAVE('i', -1); + return -1; } // Make sure that the card is in page 0 @@ -313,23 +246,31 @@ Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buf outb(Card->IOBase + ISR, 0x40); // Bit 6 // Send Size - Transfer Byte Count Register - outb(Card->IOBase + TBCR0, Length & 0xFF); - outb(Card->IOBase + TBCR1, Length >> 8); + outb(Card->IOBase + TBCR0, length & 0xFF); + outb(Card->IOBase + TBCR1, length >> 8); // Send Size - Remote Byte Count Register - outb(Card->IOBase + RBCR0, Length & 0xFF); - outb(Card->IOBase + RBCR1, Length >> 8); + outb(Card->IOBase + RBCR0, length & 0xFF); + outb(Card->IOBase + RBCR1, length >> 8); // Set up transfer outb(Card->IOBase + RSAR0, 0x00); // Page Offset - page = Ne2k_int_GetWritePage(Card, Length); + page = Ne2k_int_GetWritePage(Card, length); outb(Card->IOBase + RSAR1, page); // Page Offset // Start outb(Card->IOBase + CMD, 0|0x10|0x2); // Page 0, Remote Write, Start // Send Data - for(rem = Length; rem > 0; rem -= 2) { - outw(Card->IOBase + 0x10, *buf++); + size_t buflen; + const void *bufptr; + for(int id = -1; (id = IPStack_Buffer_GetBuffer(Buffer, -1, &buflen, &bufptr)) != -1; ) + { + const Uint16 *buf = bufptr; + if( buflen & 1 ) + Log_Notice("NE2000", "Alignment issue in TX buffer"); + buflen = (buflen + 1) / 2; + while(buflen --) + outw(Card->IOBase + 0x10, *buf++); } while( !(inb(Card->IOBase + ISR) & 0x40) ) // Wait for Remote DMA Complete @@ -344,32 +285,39 @@ Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buf // Complete DMA //outb(Card->IOBase + CMD, 0|0x20); - LEAVE('i', Length); - return Length; + LEAVE('i', 0); + return 0; +} + +void _FreeHeapSubBuf(void *Arg, size_t Pre, size_t Post, const void *DataBuf) +{ + free(Arg); } /** - * \fn Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) * \brief Wait for and read a packet from the network card */ -Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) +tIPStackBuffer *Ne2k_WaitForPacket(void *Ptr) { - tCard *Card = (tCard*)Node->ImplPtr; + tCard *Card = Ptr; Uint8 page; Uint8 data[256]; + void *buf; + tIPStackBuffer *ret; struct { Uint8 Status; Uint8 NextPacketPage; Uint16 Length; // Little Endian } *pktHdr; - ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); + ENTER("pPtr", Ptr); // Wait for packets if( Semaphore_Wait( &Card->Semaphore, 1 ) != 1 ) { // Error or interrupted - LEAVE_RET('i', 0); + LEAVE('n'); + return NULL; } outb(Card->IOBase, 0x22 | (1 << 6)); // Page 6 @@ -386,52 +334,60 @@ Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) LOG("pktHdr->Status = 0x%x", pktHdr->Status); LOG("pktHdr->NextPacketPage = %i", pktHdr->NextPacketPage); LOG("pktHdr->Length = 0x%03x", pktHdr->Length); - + + ret = IPStack_Buffer_CreateBuffer(1); + if(!ret) LEAVE_RET('n', NULL); + buf = malloc( pktHdr->Length ); + if(!buf) LEAVE_RET('n', NULL); + IPStack_Buffer_AppendSubBuffer(ret, pktHdr->Length, 0, buf, _FreeHeapSubBuf, buf); + // Have we read all the required bytes yet? if(pktHdr->Length < 256 - 4) { - if(Length > pktHdr->Length) - Length = pktHdr->Length; - memcpy(Buffer, &data[4], Length); + memcpy(buf, &data[4], pktHdr->Length); } // No? oh damn, now we need to allocate a buffer else { int pages = pktHdr->NextPacketPage - page; - char *buf = malloc( pages*256 ); + Uint8 *writepos = buf; + int rem_bytes = pktHdr->Length; 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); + memcpy(writepos, data+4, 256-4); + writepos += 256-4; + rem_bytes -= 256-4; // Read all the needed pages page ++; if(page == RX_LAST+1) page = RX_FIRST; - - if( page + pages > RX_LAST ) + + // - Body Pages + if( pages > 2 ) { - 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); + if( page + pages - 2 > RX_LAST ) + { + int first_count = RX_LAST - page + 1; + Ne2k_int_ReadDMA(Card, page, first_count, writepos); + Ne2k_int_ReadDMA(Card, RX_FIRST, pages-2-first_count, writepos + first_count*256); + writepos += (pages-2-first_count) * 256; + } + else + Ne2k_int_ReadDMA(Card, page, pages - 2, writepos); + page += pages - 2; + if(page > RX_LAST) page -= (RX_LAST-RX_FIRST)+1; + writepos += (pages-2) * 256; + rem_bytes -= (pages-2) * 256; } - 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); + + ASSERT(rem_bytes > 0 && rem_bytes <= 0x100); + + // Final page + Ne2k_int_ReadDMA(Card, page, 1, data); + memcpy(writepos, data, rem_bytes); } // Write BNRY (maximum page for incoming packets) @@ -442,8 +398,8 @@ Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) // Set next RX Page and decrement the waiting list Card->NextRXPage = pktHdr->NextPacketPage; - LEAVE('i', Length); - return Length; + LEAVE('p', ret); + return ret; } int Ne2k_int_ReadDMA(tCard *Card, int FirstPage, int NumPages, void *Buffer)