-/* 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 <acess.h>
#include <modules.h>
-#include <fs_devfs.h>
#include <drv_pci.h>
-#include <api_drv_network.h>
#include <semaphore.h>
+#include <IPStack/include/adapters_api.h>
// === CONSTANTS ===
#define MEM_START 0x40
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);
// === 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;
{
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;
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
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
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
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
// 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
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)
// 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)