X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FModules%2FNetwork%2FVIARhineII%2Frhine2.c;h=f9f4d254d0e9b5b335f7bddfd0e1cb2df91101a3;hb=bd5e8623e509a443d7d6e1b959b79f85b0c285b7;hp=d351a4dc74d6e42bfdad01a61f9d5e1dc96f612f;hpb=5e38128725e578f32103c28bb0d3ff387a944770;p=tpg%2Facess2.git diff --git a/KernelLand/Modules/Network/VIARhineII/rhine2.c b/KernelLand/Modules/Network/VIARhineII/rhine2.c index d351a4dc..f9f4d254 100644 --- a/KernelLand/Modules/Network/VIARhineII/rhine2.c +++ b/KernelLand/Modules/Network/VIARhineII/rhine2.c @@ -2,76 +2,79 @@ * Acess2 VIA Rhine II Driver (VT6102) * - By John Hodge (thePowersGang) */ -#define DEBUG 0 +#define DEBUG 1 #define VERSION ((0<<8)|10) #include #include -#include #include -#include #include +#include "rhine2_hw.h" +#include + +#define DESC_SIZE 16 +#define N_RX_DESCS 16 +#define RX_BUF_SIZE 1024 +#define N_RX_BUF_PER_PAGE (PAGE_SIZE/RX_BUF_SIZE) +#define N_RX_BUF_PAGES ((N_RX_DESCS*RX_BUF_SIZE)/PAGE_SIZE) +#define N_TX_DESCS ((PAGE_SIZE/DESC_SIZE)-N_RX_DESCS) + +#define CR0_BASEVAL (CR0_STRT|CR0_TXON|CR0_RXON) // === CONSTANTS === #define VENDOR_ID 0x1106 #define DEVICE_ID 0x3065 -enum eRegs -{ - REG_PAR0, REG_PAR1, - REG_PAR2, REG_PAR3, - REG_PAR4, REG_PAR5, - REG_RCR, REG_TCR, - REG_CR0, REG_CR1, - REG_rsv0, REG_rsv1, - REG_ISR0, REG_ISR1, - REG_IMR0, REG_IMR1, -}; - // === TYPES === typedef struct sCard { Uint16 IOBase; Uint8 IRQ; - int NumWaitingPackets; + tSemaphore ReadSemaphore; + tSemaphore SendSemaphore; + + struct { + Uint32 Phys; + void *Virt; + } RXBuffers[N_RX_BUF_PAGES]; + + Uint32 DescTablePhys; + void *DescTable; + + struct sTXDesc *TXDescs; + int NextTX; + int nFreeTX; - char Name[2]; - tVFS_Node Node; + struct sRXDesc *NextRX; // Most recent unread packet + + void *IPHandle; Uint8 MacAddr[6]; } tCard; // === PROTOTYPES === int Rhine2_Install(char **Options); -char *Rhine2_ReadDir(tVFS_Node *Node, int Pos); -tVFS_Node *Rhine2_FindDir(tVFS_Node *Node, const char *Filename); - int Rhine2_RootIOCtl(tVFS_Node *Node, int ID, void *Arg); -Uint64 Rhine2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); -Uint64 Rhine2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); - int Rhine2_IOCtl(tVFS_Node *Node, int ID, void *Arg); -void Rhine2_IRQHandler(int Num); +void Rhine2_int_InitialiseCard(tCard *Card); +tIPStackBuffer *Rhine2_WaitPacket(void *Ptr); + int Rhine2_SendPacket(void *Ptr, tIPStackBuffer *Buffer); +void Rhine2_IRQHandler(int Num, void *Pt); +// --- Helpers --- +struct sRXDesc *Rhine2_int_GetDescFromPhys(tCard *Card, Uint32 Addr); +void *Rhine2_int_GetBufferFromPhys(tCard *Card, Uint32 Addr); +void Rhine2_int_FreeRXDesc(void *Desc, size_t, size_t, const void*); // === GLOBALS === MODULE_DEFINE(0, VERSION, VIARhineII, Rhine2_Install, NULL, NULL); -tVFS_NodeType gRhine2_DirType = { - .ReadDir = Rhine2_ReadDir, - .FindDir = Rhine2_FindDir, - .IOCtl = Rhine2_RootIOCtl - }; -tDevFS_Driver gRhine2_DriverInfo = { - NULL, "Rhine2", - { - .NumACLs = 1, - .ACLs = &gVFS_ACL_EveryoneRX, - .Flags = VFS_FFLAG_DIRECTORY, - .Type = &gRhine2_DirType - } +tIPStack_AdapterType gRhine2_AdapterType = { + .Name = "VIA Rhine II", + .SendPacket = Rhine2_SendPacket, + .WaitForPacket = Rhine2_WaitPacket, }; int giRhine2_CardCount; tCard *gaRhine2_Cards; // === CODE === /** - * \brief Installs the PCnet3 Driver + * \brief Initialises the driver */ int Rhine2_Install(char **Options) { @@ -81,8 +84,7 @@ int Rhine2_Install(char **Options) tCard *card; giRhine2_CardCount = PCI_CountDevices(VENDOR_ID, DEVICE_ID); - Log_Debug("PCnet3", "%i cards", giRhine2_CardCount); - + Log_Debug("Rhine2", "giRhine2_CardCount = %i", giRhine2_CardCount); if( giRhine2_CardCount == 0 ) return MODULE_ERR_NOTNEEDED; gaRhine2_Cards = calloc( giRhine2_CardCount, sizeof(tCard) ); @@ -98,270 +100,331 @@ int Rhine2_Install(char **Options) LOG("BAR4 = 0x%08x", PCI_GetBAR(id, 4)); LOG("BAR5 = 0x%08x", PCI_GetBAR(id, 5)); -// card->IOBase = base; -// card->IRQ = PCI_GetIRQ( id ); + card->IOBase = PCI_GetBAR(id, 0); + if( !(card->IOBase & 1) ) { + // Oops? + Log_Warning("Rhine2", "BAR0 is not in IO space"); + continue ; + } + card->IOBase &= ~1; + card->IRQ = PCI_GetIRQ( id ); // Install IRQ Handler -// IRQ_AddHandler(card->IRQ, Rhine2_IRQHandler); - - + IRQ_AddHandler(card->IRQ, Rhine2_IRQHandler, card); -// Log_Log("PCnet3", "Card %i 0x%04x, IRQ %i %02x:%02x:%02x:%02x:%02x:%02x", -// i, card->IOBase, card->IRQ, -// card->MacAddr[0], card->MacAddr[1], card->MacAddr[2], -// card->MacAddr[3], card->MacAddr[4], card->MacAddr[5] -// ); + Rhine2_int_InitialiseCard(card); + + card->IPHandle = IPStack_Adapter_Add(&gRhine2_AdapterType, card, card->MacAddr); + + Log_Log("Rhine2", "Card %i 0x%04x, IRQ %i %02x:%02x:%02x:%02x:%02x:%02x", + i, card->IOBase, card->IRQ, + card->MacAddr[0], card->MacAddr[1], card->MacAddr[2], + card->MacAddr[3], card->MacAddr[4], card->MacAddr[5] + ); i ++; } - gRhine2_DriverInfo.RootNode.Size = giRhine2_CardCount; - DevFS_AddDevice( &gRhine2_DriverInfo ); - return MODULE_ERR_OK; } -// --- Root Functions --- -char *Rhine2_ReadDir(tVFS_Node *Node, int Pos) +void Rhine2_int_InitialiseCard(tCard *Card) { - if( Pos < 0 || Pos >= giRhine2_CardCount ) return NULL; + tPAddr phys; - return strdup( gaRhine2_Cards[Pos].Name ); -} + Card->MacAddr[0] = inb(Card->IOBase + REG_PAR0); + Card->MacAddr[1] = inb(Card->IOBase + REG_PAR1); + Card->MacAddr[2] = inb(Card->IOBase + REG_PAR2); + Card->MacAddr[3] = inb(Card->IOBase + REG_PAR3); + Card->MacAddr[4] = inb(Card->IOBase + REG_PAR4); + Card->MacAddr[5] = inb(Card->IOBase + REG_PAR5); -tVFS_Node *Rhine2_FindDir(tVFS_Node *Node, const char *Filename) -{ - //TODO: It might be an idea to supprt >10 cards - if(Filename[0] == '\0' || Filename[1] != '\0') return NULL; - if(Filename[0] < '0' || Filename[0] > '9') return NULL; - return &gaRhine2_Cards[ Filename[0]-'0' ].Node; -} + LOG("Resetting card"); + outb(Card->IOBase + REG_CR1, CR1_SFRST); + // TODO: Timeout + while( inb(Card->IOBase + REG_CR1) & CR1_SFRST ) ; + + LOG("Allocaating RX buffers"); + // Allocate memory for things + for( int i = 0; i < N_RX_BUF_PAGES; i ++ ) + { + Card->RXBuffers[i].Virt = (void*)MM_AllocDMA(1, 32, &phys); + Card->RXBuffers[i].Phys = phys; + } + + LOG("Allocating and filling RX/TX Descriptors"); + Card->DescTable = (void*)MM_AllocDMA(1, 32, &phys); + Card->DescTablePhys = phys; -const char *csaRhine2_RootIOCtls[] = {DRV_IOCTLNAMES, NULL}; -int Rhine2_RootIOCtl(tVFS_Node *Node, int ID, void *Data) -{ - ENTER("pNode iID pData", Node, ID, Data); - switch(ID) + // Initialise RX Descriptors + struct sRXDesc *rxdescs = Card->DescTable; + for( int i = 0; i < N_RX_DESCS; i ++ ) { - BASE_IOCTLS(DRV_TYPE_NETWORK, "PCnet3", VERSION, csaRhine2_RootIOCtls); + rxdescs[i].RSR = 0; + rxdescs[i].BufferSize = RX_BUF_SIZE; + rxdescs[i].RXBufferStart = Card->RXBuffers[i/N_RX_BUF_PER_PAGE].Phys + + (i % N_RX_BUF_PER_PAGE) * RX_BUF_SIZE; + rxdescs[i].RDBranchAddress = Card->DescTablePhys + (i+1) * DESC_SIZE; + rxdescs[i].Length = (1 << 15); // set OWN + LOG("RX Desc %p = {Buf:0x%8x, Next:0x%x}", rxdescs, + rxdescs[i].RXBufferStart, rxdescs[i].RDBranchAddress + ); } - LEAVE('i', 0); - return 0; + rxdescs[ N_RX_DESCS - 1 ].RDBranchAddress = Card->DescTablePhys; + Card->NextRX = &rxdescs[0]; + + Card->TXDescs = (void*)(rxdescs + N_RX_DESCS); + memset(Card->TXDescs, 0, sizeof(struct sTXDesc)*N_TX_DESCS); + for( int i = 0; i < N_TX_DESCS; i ++ ) + { + Card->TXDescs[i].TDBranchAddress = Card->DescTablePhys + (N_RX_DESCS + i + 1) * DESC_SIZE; + } + Card->TXDescs[N_TX_DESCS-1].TDBranchAddress = Card->DescTablePhys + N_RX_DESCS * DESC_SIZE; + Card->nFreeTX = N_TX_DESCS; + Card->NextTX = 0; + + // - Initialise card state + LOG("Initialising card state"); + outb(Card->IOBase + REG_IMR0, 0xFF); + outb(Card->IOBase + REG_IMR1, 0xFF); + outd(Card->IOBase + REG_CUR_RX_DESC, Card->DescTablePhys); + outd(Card->IOBase + REG_CUR_TX_DESC, Card->DescTablePhys + N_RX_DESCS * DESC_SIZE); + + outb(Card->IOBase + REG_TCR, TCR_TRSF(4)); + + LOG("RX started"); + outb(Card->IOBase + REG_CR0, CR0_BASEVAL); + outb(Card->IOBase + REG_CR1, 0); // Disabled TX polling only? + + LOG("ISR state: %02x %02x", inb(Card->IOBase + REG_ISR0), inb(Card->IOBase + REG_ISR1)); } // --- File Functions --- -Uint64 Rhine2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) +tIPStackBuffer *Rhine2_WaitPacket(void *Ptr) { - #if 0 - tCard *card = Node->ImplPtr; - Uint16 read_ofs, pkt_length; - int new_read_ofs; - - ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); + tCard *card = Ptr; + tIPStackBuffer *ret; + struct sRXDesc *desc; + int nDesc; + + ENTER("pPtr", Ptr); -retry: + LOG("CR0 state: %02x", inb(card->IOBase + REG_CR0)); if( Semaphore_Wait( &card->ReadSemaphore, 1 ) != 1 ) { - LEAVE_RET('i', 0); + LEAVE('n'); + return NULL; } - Mutex_Acquire( &card->ReadMutex ); + nDesc = 0; + desc = card->NextRX; + while( !(desc->Length & (1 << 15)) ) + { +// LOG("desc(%p) = {RSR:%04x,Length:%04x,BufferSize:%04x,RXBufferStart:%08x,RDBranchAddress:%08x}", +// desc, desc->RSR, desc->Length, desc->BufferSize, desc->RXBufferStart, desc->RDBranchAddress); + // TODO: This kinda expensive call can be changed for an increment, but cbf + desc = Rhine2_int_GetDescFromPhys(card, desc->RDBranchAddress); + nDesc ++; + } + + LOG("%i descriptors in packet", nDesc); + + ret = IPStack_Buffer_CreateBuffer(nDesc); + desc = card->NextRX; + while( !(desc->Length & (1 << 15)) ) + { + void *data = Rhine2_int_GetBufferFromPhys(card, desc->RXBufferStart); + IPStack_Buffer_AppendSubBuffer(ret, + desc->Length, 0, data, + Rhine2_int_FreeRXDesc, desc + ); + desc = Rhine2_int_GetDescFromPhys(card, desc->RDBranchAddress); + } + card->NextRX = desc; + + LEAVE('p', ret); + return ret; +} + +int Rhine2_SendPacket(void *Ptr, tIPStackBuffer *Buffer) +{ + tCard *card = Ptr; + size_t len; + const void *data; + int nDescs, first_desc_id; + struct sTXDesc *desc = NULL; + struct sTXDesc *first_desc = NULL; + struct sTXDesc *last_desc = NULL; + + ENTER("pPtr pBuffer", Ptr, Buffer); + + #if 0 + // Iterate buffers + nDescs = 0; + for( int id = -1; -1 != (id = IPStack_Buffer_GetBuffer(Buffer, id, &len, &data)); ) + { + if( ((tVAddr)data & (PAGE_SIZE-1)) + len > PAGE_SIZE ) + nDescs ++; + nDescs ++; + } + if( nDescs == 0 ) { + LEAVE('i', -1); + return -1; + } + + LOG("%i descriptors needed", nDescs); - read_ofs = inw( card->IOBase + CAPR ); - LOG("raw read_ofs = %i", read_ofs); - read_ofs = (read_ofs + 0x10) & 0xFFFF; - LOG("read_ofs = %i", read_ofs); + if( card->nFreeTX < nDescs ) { + // Oops... wait? + // TODO: Semaphore instead? + LEAVE('i', 1); + return 1; + } + + first_desc_id = card->NextTX; + card->NextTX = (card->NextTX + nDescs) % N_TX_DESCS; + + desc = card->TXDescs + first_desc_id; - pkt_length = *(Uint16*)&card->ReceiveBuffer[read_ofs+2]; + nDescs = 0; + for( int id = -1; -1 != (id = IPStack_Buffer_GetBuffer(Buffer, id, &len, &data)); ) + { + tPAddr pdata = MM_GetPhysAddr( (tVAddr)data ); + #if PHYS_BITS > 32 + if( pdata >> 32 ) { + // TODO: re-map + Log_Warning("Rhine2", "TODO: Bounce-buffer >32 pbit buffers"); + } + #endif - // Calculate new read offset - new_read_ofs = read_ofs + pkt_length + 4; - new_read_ofs = (new_read_ofs + 3) & ~3; // Align - if(new_read_ofs > card->ReceiveBufferLength) { - LOG("wrapping read_ofs"); - new_read_ofs -= card->ReceiveBufferLength; - } - new_read_ofs -= 0x10; // I dunno - LOG("new_read_ofs = %i", new_read_ofs); + if( (pdata & (PAGE_SIZE-1)) + len > PAGE_SIZE ) + { + // Need to split into to descriptors + Log_Warning("Rhine2", "TODO: Split cross-page buffers"); + } + + LOG("Buffer %i (%p+0x%x) placed in %p", id-1, data, len, desc); + + // TODO: Rhine I requires 4-byte alignment (fsck that, I don't have one) - // Check for errors - if( *(Uint16*)&card->ReceiveBuffer[read_ofs] & 0x1E ) { - // Update CAPR - outw(card->IOBase + CAPR, new_read_ofs); - Mutex_Release( &card->ReadMutex ); - goto retry; // I feel evil + desc->TXBufferStart = pdata; + desc->BufferSize = len | (1 << 15); + // TODO: TCR + desc->TCR = 0; + if( nDescs == 0 ) + desc->TSR = 0; // OWN will be set below + else + desc->TSR = TD_TSR_OWN; + + nDescs ++; + if(first_desc_id + nDescs == N_TX_DESCS) + desc = card->TXDescs; + else + desc ++; } + #else + data = IPStack_Buffer_CompactBuffer(Buffer, &len); - // Get packet - if( Length > pkt_length ) Length = pkt_length; - memcpy(Buffer, &card->ReceiveBuffer[read_ofs+4], Length); + nDescs = 1; + first_desc_id = card->NextTX; + card->NextTX = (card->NextTX + nDescs) % N_TX_DESCS; + desc = card->TXDescs + first_desc_id; - // Update CAPR - outw(card->IOBase + CAPR, new_read_ofs); + desc->TXBufferStart = MM_GetPhysAddr( data ); + desc->BufferSize = len | (1 << 15); + desc->TSR = 0; + desc->TCR = 0; + #endif - Mutex_Release( &card->ReadMutex ); + first_desc = card->TXDescs + first_desc_id; + last_desc = desc; - LEAVE('i', Length); + first_desc->TCR |= TD_TCR_STP; + last_desc->TCR |= TD_TCR_EDP|TD_TCR_IC; +// last_desc->BufferSize &= ~(1 << 15); + + first_desc->TSR |= TD_TSR_OWN; + + LOG("%i descriptors allocated, first = %p, last = %p", nDescs, first_desc, last_desc); + + + LOG("Waiting for TX to complete"); + outb(card->IOBase + REG_CR0, CR0_TDMD|CR0_BASEVAL); + Semaphore_Wait(&card->SendSemaphore, 1); + + #if 1 + free((void*)data); #endif - - return Length; + + LEAVE('i', 0); + return 0; } -Uint64 Rhine2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) +void Rhine2_IRQHandler(int Num, void *Ptr) { - #if 0 - int td; - Uint32 status; - tCard *card = Node->ImplPtr; - - if( Length > 1500 ) return 0; // MTU exceeded - - ENTER("pNode XLength pBuffer", Node, Length, Buffer); - - // TODO: Implement a semaphore for avaliable transmit buffers - - // Find an avaliable descriptor - Mutex_Acquire(&card->CurTXProtector); - td = card->CurTXDescriptor; - card->CurTXDescriptor ++; - card->CurTXDescriptor %= 4; - Mutex_Release(&card->CurTXProtector); - // - Lock it - Mutex_Acquire( &card->TransmitInUse[td] ); - - LOG("td = %i", td); + tCard *card = Ptr; + Uint8 isr0 = inb(card->IOBase + REG_ISR0); + Uint8 isr1 = inb(card->IOBase + REG_ISR1); + + if( isr0 == 0 ) return ; + + LOG("ISR0 = 0x%02x, ISR1 = 0x%02x", isr0, isr1); + + if( isr0 & ISR0_PRX ) + { + LOG("PRX"); + Semaphore_Signal(&card->ReadSemaphore, 1); + } - // Transmit using descriptor `td` - LOG("card->PhysTransmitBuffers[td] = %P", card->PhysTransmitBuffers[td]); - outd(card->IOBase + TSAD0 + td*4, card->PhysTransmitBuffers[td]); - LOG("card->TransmitBuffers[td] = %p", card->TransmitBuffers[td]); - // Copy to buffer - memcpy(card->TransmitBuffers[td], Buffer, Length); - // Start - status = 0; - status |= Length & 0x1FFF; // 0-12: Length - status |= 0 << 13; // 13: OWN bit - status |= (0 & 0x3F) << 16; // 16-21: Early TX threshold (zero atm, TODO: check) - LOG("status = 0x%08x", status); - outd(card->IOBase + TSD0 + td*4, status); + if( isr0 & ISR0_PTX ) + { + LOG("PTX"); + Semaphore_Signal(&card->SendSemaphore, 1); + } - LEAVE('i', (int)Length); - #endif + if( isr0 & ISR0_TXE ) + { + LOG("TX Error... oops"); + Semaphore_Signal(&card->SendSemaphore, 1); + } - return Length; + if( isr0 & ISR0_TU ) + { + LOG("Transmit buffer underflow"); + } + + LOG("Acking interrupts"); + outb(card->IOBase + REG_ISR0, isr0); + outb(card->IOBase + REG_ISR1, isr1); } -const char *csaRhine2_NodeIOCtls[] = {DRV_IOCTLNAMES, NULL}; -int Rhine2_IOCtl(tVFS_Node *Node, int ID, void *Data) +// --- Helpers --- +struct sRXDesc *Rhine2_int_GetDescFromPhys(tCard *Card, Uint32 Addr) { - tCard *card = Node->ImplPtr; - ENTER("pNode iID pData", Node, ID, Data); - switch(ID) + if( Card->DescTablePhys > Addr ) return NULL; + if( Card->DescTablePhys + PAGE_SIZE <= Addr ) return NULL; + if( Addr & 15 ) return NULL; + return (struct sRXDesc*)Card->DescTable + ((Addr & (PAGE_SIZE-1)) / 16); +} + +void *Rhine2_int_GetBufferFromPhys(tCard *Card, Uint32 Addr) +{ + for( int i = 0; i < N_RX_BUF_PAGES; i ++ ) { - BASE_IOCTLS(DRV_TYPE_NETWORK, "PCnet3", VERSION, csaRhine2_NodeIOCtls); - case NET_IOCTL_GETMAC: - if( !CheckMem(Data, 6) ) { - LEAVE('i', -1); - return -1; - } - memcpy( Data, card->MacAddr, 6 ); - LEAVE('i', 1); - return 1; + if( Card->RXBuffers[i].Phys > Addr ) continue; + if( Card->RXBuffers[i].Phys + PAGE_SIZE <= Addr ) continue; + return Card->RXBuffers[i].Virt + (Addr & (PAGE_SIZE-1)); } - LEAVE('i', 0); - return 0; + return NULL; } -void Rhine2_IRQHandler(int Num) +void Rhine2_int_FreeRXDesc(void *Ptr, size_t u1, size_t u2, const void *u3) { - #if 0 - int i, j; - tCard *card; - Uint16 status; + struct sRXDesc *desc = Ptr; - LOG("Num = %i", Num); + LOG("Descriptor %p returned to card", desc); - for( i = 0; i < giRhine2_CardCount; i ++ ) - { - card = &gaRhine2_Cards[i]; - if( Num != card->IRQ ) break; - - status = inw(card->IOBase + ISR); - LOG("status = 0x%02x", status); - - // Transmit OK, a transmit descriptor is now free - if( status & FLAG_ISR_TOK ) - { - for( j = 0; j < 4; j ++ ) - { - if( ind(card->IOBase + TSD0 + j*4) & 0x8000 ) { // TSD TOK - Mutex_Release( &card->TransmitInUse[j] ); - // TODO: Update semaphore once implemented - } - } - outw(card->IOBase + ISR, FLAG_ISR_TOK); - } - - // Recieve OK, inform read - if( status & FLAG_ISR_ROK ) - { - int read_ofs, end_ofs; - int packet_count = 0; - int len; - - // Scan recieve buffer for packets - end_ofs = inw(card->IOBase + CBA); - read_ofs = card->SeenOfs; - LOG("read_ofs = %i, end_ofs = %i", read_ofs, end_ofs); - if( read_ofs > end_ofs ) - { - while( read_ofs < card->ReceiveBufferLength ) - { - packet_count ++; - len = *(Uint16*)&card->ReceiveBuffer[read_ofs+2]; - LOG("%i 0x%x Pkt Hdr: 0x%04x, len: 0x%04x", - packet_count, read_ofs, - *(Uint16*)&card->ReceiveBuffer[read_ofs], - len - ); - if(len > 2000) { - Log_Warning("PCnet3", "IRQ: Packet in buffer exceeds sanity (%i>2000)", len); - } - read_ofs += len + 4; - read_ofs = (read_ofs + 3) & ~3; // Align - } - read_ofs -= card->ReceiveBufferLength; - LOG("wrapped read_ofs"); - } - while( read_ofs < end_ofs ) - { - packet_count ++; - LOG("%i 0x%x Pkt Hdr: 0x%04x, len: 0x%04x", - packet_count, read_ofs, - *(Uint16*)&card->ReceiveBuffer[read_ofs], - *(Uint16*)&card->ReceiveBuffer[read_ofs+2] - ); - read_ofs += *(Uint16*)&card->ReceiveBuffer[read_ofs+2] + 4; - read_ofs = (read_ofs + 3) & ~3; // Align - } - if( read_ofs != end_ofs ) { - Log_Warning("PCnet3", "IRQ: read_ofs (%i) != end_ofs(%i)", read_ofs, end_ofs); - read_ofs = end_ofs; - } - card->SeenOfs = read_ofs; - - LOG("packet_count = %i, read_ofs = 0x%x", packet_count, read_ofs); - - if( packet_count ) - { - if( Semaphore_Signal( &card->ReadSemaphore, packet_count ) != packet_count ) { - // Oops? - } - VFS_MarkAvaliable( &card->Node, 1 ); - } - - outw(card->IOBase + ISR, FLAG_ISR_ROK); - } - } - #endif + desc->RSR = 0; + desc->Length = (1 << 15); // Reset OWN } +