Uint16 IOBase; //!< IO Port Address from PCI
Uint8 IRQ; //!< IRQ Assigned from PCI
- tSemaphore Semaphore;
-// 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];
+ //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_IOCtl(tVFS_Node *Node, int ID, void *Data);
Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, 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);
// 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);
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
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
tCard *Card = (tCard*)Node->ImplPtr;
Uint8 page;
Uint8 data[256];
- int i;
struct {
Uint8 Status;
Uint8 NextPacketPage;
// Wait for packets
Semaphore_Wait( &Card->Semaphore, 1 );
- // Make sure that the card is in bank 0
- outb(Card->IOBase + CMD, 0|0x22); // Bank 0, Start, NoDMA
+ outb(Card->IOBase, 0x22 | (1 << 6)); // Page 6
+ LOG("CURR : 0x%02x", inb(Card->IOBase + CURR));
// 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 + ISR, 0x40); // Bit 6 - Clear Remote DMA Flag
-
- outb(Card->IOBase + CMD, 0|0x08|0x2); // Bank 0, Remote Read, Start
-
- // TODO: Less expensive
- while( inb(Card->IOBase + ISR) & 0x40 )
- HALT();
-
- // Read data
- for(i = 0; i < 128; i ++)
- ((Uint16*)data)[i] = inw(Card->IOBase + 0x10);
-
-
- // Clear Remote DMA Flag
- outb(Card->IOBase + ISR, 0x40); // Bit 6
+ Ne2k_int_ReadDMA(Card, page, 1, data);
pktHdr = (void*)data;
+ 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)
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 ofs = 256/2; // buffer write offset
int pages = pktHdr->NextPacketPage - page;
- // int bufLen = (pktHdr->Length + 4 + 255) & ~255;
char *buf = malloc( pages*256 );
LOG("pktHdr->Length (%i) > 256 - 4, allocated buffer %p", pktHdr->Length, buf);
memcpy(buf, data, 256);
// Read all the needed pages
-// do
-// {
- page ++;
- if(page == RX_LAST+1) page = RX_FIRST;
-
- outb(Card->IOBase + RBCR0, 0); // 256-bytes (low)
- outb(Card->IOBase + RBCR1, pages-1); // 256-bytes (high)
- outb(Card->IOBase + RSAR0, 0x00); // Page Offset
- outb(Card->IOBase + RSAR1, page); // Page Number
- outb(Card->IOBase + ISR, 0x40); // Bit 6 - Clear Remote DMA Flag
- outb(Card->IOBase + CMD, 0|0x08|0x2); // Bank 0, Remote Read, Start
- // TODO: Less expensive
- while( inb(Card->IOBase + ISR) & 0x40 ) HALT();
-
- for(i = 0; i < 128*(pages-1); i ++)
- ((Uint16*)buf)[ofs+i] = inw(Card->IOBase + 0x10);
-
- outb(Card->IOBase + ISR, 0x40); // Bit 6 - Clear Remote DMA Flag
-// ofs += 128;
-// } while(page != pktHdr->NextPacketPage-1);
+ page ++;
+ if(page == RX_LAST+1) page = RX_FIRST;
+
+ if( page + pages > RX_LAST )
+ {
+ 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)
}
// Write BNRY (maximum page for incoming packets)
- if(page == RX_FIRST)
+ 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 = pktHdr->NextPacketPage;
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)
*/
{
byte = inb( gpNe2k_Cards[i].IOBase + ISR );
+ LOG("byte = 0x%02x", byte);
+
+
+ // Reset All (save for RDMA), that's polled
+ outb( gpNe2k_Cards[i].IOBase + ISR, 0xFF&(~0x40) );
+
// 0: Packet recieved (no error)
if( byte & 1 )
{
// 5:
// 6: Remote DMA Complete
// 7: Reset
- //LOG("Clearing interrupts on card %i (was 0x%x)", i, byte);
- outb( gpNe2k_Cards[i].IOBase + ISR, 0xFF ); // Reset All
+
return ;
}
}