+/**
+ * \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)
+{
+ tCard *Card = (tCard*)Node->ImplPtr;
+ Uint8 page;
+ Uint8 data[256];
+ int i;
+ struct {
+ Uint8 Status;
+ Uint8 NextPacketPage;
+ Uint16 Length; // Little Endian
+ } *pktHdr;
+
+ ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
+
+ while(Card->NumWaitingPackets == 0) Threads_Yield();
+
+ // Make sure that the card is in page 0
+ outb(Card->IOBase + CMD, 0|0x22); // Page 0, Start, NoDMA
+
+ // Get BOUNDARY
+ page = Card->NextRXPage;
+
+ // 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);
+
+ pktHdr = (void*)data;
+ //Log("Ne2k_Read: Recieved packet (%i bytes)", pktHdr->Length);
+
+ // 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);
+ 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 );
+
+ if(!buf) {
+ LEAVE('i', -1);
+ return -1;
+ }
+
+ memcpy(buf, data, 256);
+
+ page ++;
+ while(page != pktHdr->NextPacketPage)
+ {
+ 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 ++;
+ }
+
+ if(Length > pktHdr->Length)
+ Length = pktHdr->Length;
+ memcpy(Buffer, &buf[4], Length);
+ }
+
+ // Write BNRY
+ if(page == RX_FIRST)
+ outb( Card->IOBase + BNRY, RX_LAST );
+ else
+ outb( Card->IOBase + BNRY, page-1 );
+ // Set next RX Page and decrement the waiting list
+ Card->NextRXPage = page;
+ Card->NumWaitingPackets --;
+
+ LEAVE('i', Length);
+ return Length;
+}
+