Re[defense]: Netgear GA620 Gigabit Ethernet Card Available $249 (SC Fiber)

devdrvr devdrvr@davis.com
Thu Mar 23 22:37:24 2000


$235 wholesale would mean $249 ain't a bad price Donald.  I must be missing
your point.  If you are writing drivers for money you should know you get
tons of hardware sent to you -- not all of which you end up using.  Every so
often I try to off-load the hardware to others.  Being part of a free market
system I just made up the price; maybe I should have made it lower.

To prove that I actually did write the driver for the card on the Mac, OS
7-9 flavor (since you've called that into question); below is my receive a
single frame routine that goes inside the Apple Enet and Open Transport
framework for network drivers.  If you talk to Jes who did the Linux driver
for the Tigon 2 chip and Alteon firmware you'll discover that handling the
idea of two receive rings is a tricky part of the driver.  If the ifMTU
register is set above 1514 plus 4 bytes CRC the jumbo ring is used for fat
frames.  The driver if it supports jumbo packets has to do this on receive
by checking a flag.  You may not like the fact that I misused the list by
trying to sell a NIC here; but I fail to see why you would suggest that I
don't write drivers for a living?  Anyway I guess you have your reasons.  By
the way my driver does support jumbo frames but they get split by the NIC
and firmware into smaller chunks before they get passed to me.  I did this
because under OS 9 and prior Mac releases the DLPI streams layer can't
handle fatter frames so there is no point in passing them on up the stack.

I like your controller chip page and the associated URLs you have on your
home page.  I'll take my dings from you because you are a valued industry
resource; and I appreciate the the help you've given me and others in the
past.  Carry on Donald.  If you want to buy the (Netgear GA620 gigabit
Ethernet fiber) card anyway; there is no shame in that -- I won't tell
anybody.

[Advertising included.] Click on:

http://cgi.ebay.com/aw-cgi/eBayISAPI.dll?ViewItem&item=289756655

--Lu
Device Driver Programmer
Davis, CA
(530) 400-5692

----------

// MacRxPacket() receives a packet.
// Returns NULL if blocked.
static RxPacketPtr MacRxPacket(EnetMACPtr mac)
{
 RxRingPtr     r;
 RxBufferPtr     packet;
 UInt32      status;

 // Collect runtime statistics.
 RuntimeEnter(mac, MacRxPacket);

 // Assert that the receiver is not broken.
 assert(MacRxCheck(mac));

 // Blocked if the receiver is not active.
 if (mac->rx.probe == NULL) {
  mac->count.rx.blockedInactive++;
  goto blocked;
 }

 // Blocked if no packet is READY.
 if (!MacRxReady(mac))
  goto blocked;

 // Get the Receive Ring Element at the Tail.
 r = mac->rx.ring.tail;

#if SAMPLE // Receive a packet.
 // If there is only one segment...
 if (MacRxRingLast(r)) {
  packet = r->buffer;
  r->buffer = NULL;
  packet->bufferCount = 1;
  packet->packetNext = NULL;
  // Get the receive error status.
  status = r->rDes->rDesControlStatus;
  // Get the packet size, includes 4-byte CRC.
  packet->packetSize = packet->used =
   (status & kRDesStatusSizeMask) >> kRDesStatusSizeShift;
  // Advance the ring tail to the first buffer of the next packet.
  mac->rx.ring.tail = r->next;
  mac->rx.ring.used--;
 }
 // If there is more than one segment...
 else {
  UInt32 used;
  UInt32 size;
  RxBufferPtr b;
  r = mac->rx.ring.tail;
  packet = b = r->buffer;
  packet->bufferCount = 1;
  // Blocked if the last segment is not READY.
  do {
   r = r->next;
   if (MacRxRingBusy(r) || MacRxRingFirst(r)) {
    mac->count.rx.blockedPartial++;
    goto blocked;
   }
  } while (!MacRxRingLast(r));
  // Build the rest of the RxBuffer list.
  r = mac->rx.ring.tail;
  r->buffer = NULL;
  used = 0;
  do {
   r = r->next;
   used += b->used = b->allocated;
   b->packetNext = r->buffer;
   b = b->packetNext;
   packet->bufferCount++;
   r->buffer = NULL;
  } while (!MacRxRingLast(r));
  b->packetNext = NULL;
  // Get the receive error status.
  status = r->rDes->rDesControlStatus;
  // Get the packet size, includes 4-byte CRC.
  packet->packetSize = size =
   (status & kRDesStatusSizeMask) >> kRDesStatusSizeShift;
  b->used = size - used;
  // Advance the ring tail to the first buffer of the next packet.
  mac->rx.ring.tail = r->next;
  mac->rx.ring.used -= packet->bufferCount;
 }
 // One ring element is always left to stop the DMA.
 // The receiver is stopped if there are no more ring elements.
 if (mac->rx.ring.used <= 1) {
  mac->count.rx.stopped++;
  mac->rx.probe = NULL;
 }
 // The receiver is active if there are more ring elments.
 else {
  assert(mac->rx.ring.tail != NULL);
  mac->rx.probe = mac->rx.ring.tail;
 }
 // Error if the error status is non-zero.
 if ((status & kRDesStatusErrorMask) != kRDesStatusNoError)
  goto error;
#endif // SAMPLE // Receive a packet.

#if DEC21X4X // Receive a packet.
 // If there is only one segment...
 if (MacRxRingLast(r)) {
  r = mac->rx.ring.tail;
  packet = r->buffer;
  r->buffer = NULL;
  packet->bufferCount = 1;
  packet->packetNext = NULL;
  // Get the receive error status.
  status = r->rDes->status;
  // Get the packet size, includes 4-byte CRC.
  packet->packetSize = packet->used  =
   (status & kRDesStatusSizeMask) >> kRDesStatusSizeShift;
  // Advance the ring tail to the first buffer of the next packet.
  mac->rx.ring.tail = r->next;
  mac->rx.ring.used--;
 }
 // If there is more than one segment...
 else {
  UInt32 used;
  UInt32 size;
  RxBufferPtr b;
  r = mac->rx.ring.tail;
  packet = b = r->buffer;
  packet->bufferCount = 1;
  // Blocked if the last segment is not READY.
  do {
   r = r->next;
   if (MacRxRingBusy(r) || MacRxRingFirst(r)) {
    mac->count.rx.blockedPartial++;
    goto blocked;
   }
  } while (!MacRxRingLast(r));
  // Build the rest of the RxBuffer list.
  r = mac->rx.ring.tail;
  r->buffer = NULL;
  used = 0;
  do {
   r = r->next;
   used += b->used = b->allocated;
   b->packetNext = r->buffer;
   b = b->packetNext;
   packet->bufferCount++;
   r->buffer = NULL;
  } while (!MacRxRingLast(r));
  b->packetNext = NULL;
  // Get the receive error status.
  status = r->rDes->status;
  // Get the receive packet size, includes 4-byte CRC.
  size = (status & kRDesStatusSizeMask) >> kRDesStatusSizeShift;
  b->used = size - used;
  packet->packetSize = size;
  // Advance the ring tail to the first buffer of the next packet.
  mac->rx.ring.tail = r->next;
  mac->rx.ring.used -= packet->bufferCount;
 }
 // One ring element is always left to stop the DMA.
 // The receiver is stopped if there are no more ring elements.
 if (mac->rx.ring.used <= 1) {
  mac->count.rx.stopped++;
  mac->rx.probe = NULL;
 }
 // The receiver is active if there are more ring elments.
 else {
  assert(mac->rx.ring.tail != NULL);
  mac->rx.probe = mac->rx.ring.tail;
 }
 // Error if the kRDesStatusES or kRDesStatusZER bits are set.
 if ((status & (kRDesStatusES | kRDesStatusZER)) != 0)
  goto error;
 // Error if kRDesStatusDB is set and kRDesStatusCE is clear.
 if (((status & (kRDesStatusDB | kRDesStatusCE)) == kRDesStatusDB))
  goto error;
#endif // DEC21X4X // Receive a packet.

#if TIGON2 // Receive a packet.
 {
  ReceiveBufferDescriptorPtr returnBD;
  ReceiveBufferDescriptorPtr standardBD;
  // Get the current ReturnRing buffer descriptor.
  returnBD = &mac->returnRing.array[mac->returnRing.consumerIndex];
  // Get the current StandardRing buffer descriptor.
  standardBD = &mac->standardRing.array[mac->standardRing.consumerIndex];
#if TIGON2DEBUG
  TPrintf((mac->log, "RxRing     %3d 0x%08X     0x%08X 0x%08X\n",
           r->index,
           r->buffer->phyAddress,
           r->buffer,
           r->buffer->phyAddress));
  TPrintf((mac->log, "returnBD   %3d 0x%08X %3d 0x%08X 0x%08X %3d\n",
           mac->returnRing.consumerIndex,
           returnBD->buffer.phyAddress,
           returnBD->index,
           returnBD->opaque,
           ((RxBufferPtr)returnBD->opaque)->phyAddress,
           OpaqueToStandardRingIndex(mac, returnBD->opaque)));
  TPrintf((mac->log, "standardBD %3d 0x%08X %3d 0x%08X 0x%08X\n",
           mac->standardRing.consumerIndex,
           standardBD->buffer.phyAddress,
           standardBD->index,
           standardBD->opaque,
           ((RxBufferPtr)standardBD->opaque)->phyAddress));
  // Error if not StandardRing buffer descriptor.
  if (returnBD->type != TIGON_TYPE_RECV_BD) {
   EPrintf((mac->log,
            "MacRxPacket: returnBD[%d].type = 0x%04X\n",
            mac->returnRing.consumerIndex,
            returnBD->type & 0xFFFF));
  }
  // Error if not last segment.
  if ((returnBD->flags & BD_FLAG_END) == 0) {
   EPrintf((mac->log,
            "MacRxPacket: returnBD[%d].flags = 0x%04X\n",
            mac->returnRing.consumerIndex,
            returnBD->flags & 0xFFFF));
  }
  // Error if ReturnRing Index does not match StandardRing Index.
  if (returnBD->index != standardBD->index) {
   EPrintf((mac->log,
            "MacRxPacket: "
            "returnBD[%d].index %d != standardBD[%d]->index %d\n",
            mac->returnRing.consumerIndex,
            returnBD->index,
            mac->standardRing.consumerIndex,
            standardBD->index));
  }
  // Error if StandardRing Index does not match Receive Ring Index.
  if (standardBD->index != r->index) {
   EPrintf((mac->log,
            "MacRxPacket: "
            "standardBD[%d].index %d != RxRing[%d]->index %d\n",
            mac->standardRing.consumerIndex,
            standardBD->index,
            r->index,
            r->index));
  }
  // Error if StandardRing does not match RxRing.
  if (standardBD->opaque != (UInt32)r->buffer) {
   EPrintf((mac->log,
            "MacRxPacket: "
            "standardBD[%d].opaque 0x%08X != &RxRing[%d]->buffer 0x%08X\n",
            mac->standardRing.consumerIndex,
            standardBD->opaque,
            r->index,
            r->buffer));
  }
  // Error if StandardRing buffer address does not match RxRing.
  if (standardBD->buffer.phyAddress != r->buffer->phyAddress) {
   EPrintf((mac->log,
            "MacRxPacket: "
            "standardBD[%d].buffer.phyAddress 0x%08X != "
            "RxRing[%d].buffer->phyAddress 0x%08X\n",
            mac->standardRing.consumerIndex,
            standardBD->buffer.phyAddress,
            r->index,
            r->buffer->phyAddress));
  }
  // Error if ReturnRing does not match RxRing.
  if (returnBD->opaque != (UInt32)r->buffer) {
   EPrintf((mac->log,
            "MacRxPacket: "
            "returnBD[%d].opaque 0x%08X != &RxRing[%d]->buffer 0x%08X\n",
            mac->returnRing.consumerIndex,
            returnBD->opaque,
            r->index,
            r->buffer));
  }
  // Error if ReturnRing buffer address does not match RxRing.
  if (returnBD->buffer.phyAddress != r->buffer->phyAddress) {
   EPrintf((mac->log,
            "MacRxPacket: "
            "returnBD[%d].buffer.phyAddress 0x%08X != "
            "RxRing[%d].buffer->phyAddress 0x%08X\n",
            mac->returnRing.consumerIndex,
            returnBD->buffer.phyAddress,
            r->index,
            r->buffer->phyAddress));
  }
#endif // TIGON2DEBUG
  assert(returnBD->type == TIGON_TYPE_RECV_BD);
  assert((returnBD->flags & BD_FLAG_END) != 0);
  assert(returnBD->index == standardBD->index);
  assert(standardBD->index == r->index);
  assert(standardBD->opaque == (UInt32)r->buffer);
  assert(standardBD->buffer.phyAddress == r->buffer->phyAddress);
  assert(returnBD->opaque == (UInt32)r->buffer);
  assert(returnBD->buffer.phyAddress == r->buffer->phyAddress);
  // Consume the buffer descriptor from the ReturnRing.
  mac->returnRing.consumerIndex =
   (mac->returnRing.consumerIndex + 1) % kMaxReceiveReturnRing;
  MacSetReturnRingConsumerIndex(mac, mac->returnRing.consumerIndex);
  // Consume the buffer descriptor from the StandardRing.
  mac->standardRing.consumerIndex =
   (mac->standardRing.consumerIndex + 1) % kMaxReceiveStandardRing;
  // Build the RxBuffer list.
  packet = (RxBufferPtr)returnBD->opaque;
  packet->bufferCount = 1;
  packet->packetNext = NULL;
  // Remove the RxBuffer from the RxRing.
  r->buffer = NULL;
  // Get the receive packet status.
  status = returnBD->errorFlag;
  // Get the receive packet size, includes 4-byte CRC.
  packet->packetSize = packet->used = returnBD->len;
 }
 // Advance the ring tail to the first buffer of the next packet.
 mac->rx.ring.tail = r->next;
 mac->rx.ring.used--;
 // The receiver is stopped if there are no more ring elements.
 if (mac->rx.ring.used < 1) {
  mac->count.rx.stopped++;
  mac->rx.probe = NULL;
 }
 // The receiver is active if there are more ring elements.
 else {
  assert(mac->rx.ring.tail != NULL);
  mac->rx.probe = mac->rx.ring.tail;
 }
 // Error if the status is non-zero.
 if (status != 0)
  goto error;
#endif // TIGON2 // Receive a packet.

#if RTL8139 // Receive a packet.
 // *** NOT FINISHED YET ***
 goto blocked;
 r = mac->rx.ring.tail;
 packet = r->buffer;
 packet->bufferCount = 1;
 packet->packetNext = NULL;
 r->buffer = NULL;
#endif // RTL8139 // Receive a packet.

 // No error.
 assert(packet->flags == kRxNoError);

 // Count one normal packet.
 mac->rx.bufferBalance -= packet->bufferCount;
 mac->count.rx.normalPackets++;

 // Collect runtime statistics.
 RuntimeExit(mac, MacRxPacket);

 // All done, no error, return pointer to packet.
 return packet;

 // Process an error packet.
error:
 // Determine the RxErrorFlags.
 packet->flags = MacRxError(mac, status, packet->packetSize);
 // Count one error packet.
 mac->rx.bufferBalance -= packet->bufferCount;
 mac->count.rx.errorPackets++;
 // Collect runtime statistics.
 RuntimeExit(mac, MacRxPacket);
 // All done, no error, return pointer to packet.
 return packet;

 // Return NULL if blocked.
blocked:
 mac->count.rx.blocked++;
 // Enable receive interrupt generation if ASYNCHRONOUS.
 if (mac->mode == kEnetAsynchronous)
  MacRxInterruptEnable(mac);
 // Collect runtime statistics.
 RuntimeExit(mac, MacRxPacket);
 return NULL;

}
-------------------------------------------------------------------
To unsubscribe send a message body containing "unsubscribe"
to linux-vortex-request@beowulf.org