Subject: Re: help with tulip port from netbsd to darwin
To: chuck remes <cremes@mac.com>
From: Sean Davis <dive@endersgame.net>
List: tech-net
Date: 04/16/2002 20:33:51
I have one of those cards:
tlp0 at pci0 dev 9 function 0: ADMtek AN985 Ethernet, pass 1.1
tlp0: interrupting at irq 12
tlp0: Ethernet address 00:04:5a:67:5e:a7
acphy0 at tlp0 phy 1: ACXXX 10/100 media interface, rev. 0
acphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto

When it first came into my posession, it didn't work in the netbsd-1-5
branch, and the handling for it in -current went in only a few days before I
tried current to see if I could get it to work. I've used other tulip cards
in FreeBSD and NetBSD before, with no problems, I think that the ADMtek
cards are slightly different than the standard everyday tulip. I don't know
the hardware details very well, but from brief reading through
sys/dev/pci/if_tlp_pci.c revision 1.64, the biggest oddity I see is:

                 * The ADMtek AN985 can be configured in Single-Chip
                 * mode or MAC-only mode.  Single-Chip uses the built-in
                 * PHY, MAC-only has an external PHY (usually HomePNA).
                 * The selection is based on an EEPROM setting, and both
                 * PHYs are accessed via MII attached to SIO.
                 *
                 * The AN985 "ghosts" the internal PHY onto all
                 * MII addresses, so we have to use a media init
                 * routine that limits the search.
                 * XXX How does this work with MAC-only mode?

(As far as I can tell, the reason it didn't work in netbsd-1-5 was because
acphy wasn't in the branch yet. But don't take my word for it :)

Disregard this of course if you have already taken that into consideration,
I just thought it might be worth noting, as it seems to be behavior unique
to the AN985 cards.

-Sean


On Tue, Apr 16, 2002 at 06:44:04PM -0500, chuck remes wrote:
> If this is an inappropriate question for the list, my apologies!
> 
> I've undertaken the task of porting the tulip driver from freebsd/netbsd 
> to darwin. I don't know if you are in the business of helping people port 
> this driver to other OSes, but I'm hoping for some help with a few 
> questions.  I searched all the archives of tech-net, but virtually none of 
> the discussion covers coding of the driver. As an aside, I don't know if 
> any of you are familiar with darwin or not, but its driver model is based 
> on IOKit which is substantially different from any other bsd unix.  On the 
> off chance you'll answer, I'll include as much info as I can.  :-)
> 
> Anyway, I'm almost done.  I have receiving working, but transmitting won't 
> work no matter what incantations I attempt.  My target chipset is the 
> ADMtek 985 (out of a Linksys EtherFast release 5.1, a 21143 clone).  My 
> descriptors (chained) are aligned along a quadword boundary (3 lowest bits 
> are 0) and I coalesce my outgoing mbuf into a single physical segment.  
> Also, to verify bus timing issues aren't throwing me off I have set the 
> transmitter for store-and-forward mode.
> 
> After tx'ing the first packet, my registers look like:
> control   = 0xfef98082 tx_demand = 0xffffffff
> rx_demand = 0xffffffff rx_desc   = 0x0ce54808
> tx_desc   = 0x0ce54888 status    = 0xfc67c814
> netconfig = 0xffb72153 intrrupts = 0xfffe5410
> lpc       = 0xfffe0000 MIIeeprom = 0xfff0b7f8
> rom       = 0x00000000 timer     = 0xfffe0000
> 10btstat  = 0x00000000 siareset  = 0x00000200
> 
> Here's my empty tx descriptor chain (8 desc).
> s = 0x00000000 c = 0x00000000 b1 = 0x00000000 b2 = 0x0ce54898
> s = 0x00000000 c = 0x00000000 b1 = 0x00000000 b2 = 0x0ce548a8
> s = 0x00000000 c = 0x00000000 b1 = 0x00000000 b2 = 0x0ce548b8
> s = 0x00000000 c = 0x00000000 b1 = 0x00000000 b2 = 0x0ce548c8
> s = 0x00000000 c = 0x00000000 b1 = 0x00000000 b2 = 0x0ce548d8
> s = 0x00000000 c = 0x00000000 b1 = 0x00000000 b2 = 0x0ce548e8
> s = 0x00000000 c = 0x00000000 b1 = 0x00000000 b2 = 0x0ce548f8
> s = 0x00000000 c = 0x00000000 b1 = 0x00000000 b2 = 0x0ce54888 <- points 
> back to first
> 
> Here are the values in my descriptor before kicking the transmitter (csr1)
> outputPacket, output pkt length = 42
> outputPacket, tx mbuf 0x02d5e8d6 in desc 0
> outputPacket, B4 s = 0x80000000 c = 0xe100002a b1 = 0x02d5e8d6 b2 = 
> 0x0ce54898
> outputPacket, kick tx-er
> outputPacket, AF s = 0x1a078c80 c = 0xe100002a b1 = 0x02d5e8d6 b2 = 
> 0x0ce54898
> 
> The status word gets set to a very bizarre value.  Most of those bits aren'
> t even defined (in either the 21143 datasheet or the ADMtek datasheet).  
> Those that are say (bit 7) hearbeat failure, (bit 10) no carrier, and (bit 
> 11) loss of carrier.
> 
> After sending a second packet, the status register is 0xfc67c815. The 
> lowest bit got set after the second packet!
> 
> This is telling me that (bit 2) tx buf unavailable and (bits 22,21) tx 
> suspended due to underflow or unavail descriptor.  Strangely, bit 0 is set 
> which tells me the tx finished, so at least I know it is reading the 
> tx_interrupt bit out of the control word (bit 0 does not set if I don't 
> set that bit in the control word of the descriptor).
> 
> Darwin runs on PPC, so there are endian differences.  I take care of all 
> that by reordering the bytes in the tulip descriptor structure and writing 
> the addresses in little-endian to the card (in a method _descOrder()) much 
> like the netbsd driver uses the DESC_BO macro.
> 
> Here is a segment of code that shows my output packet routine.
> 
> UInt32 com_chuck_iokit_tulip::outputPacket(struct mbuf * m, void * param)
> {
>     if ( !enabledNetif)
>     {
>         IOLog("%s, interface not enabled\n", __FUNCTION__);
>         // drop the packet
>         freePacket( m);
>         return kIOReturnOutputDropped;
>     }
> 
>     if ( txActiveCount >= TULIP_TX_RING_LENGTH) {
>         IOLog("%s, kIOReturnOutputStall", __FUNCTION__);
>         return kIOReturnOutputStall;
>     }
> 
>     struct IOPhysicalSegment 	vector;
>     int				segments;
> 
>     // coalesce to one mbuf segment
>     segments = txMbufCursor->getPhysicalSegmentsWithCoalesce( m, &vector);
> 
>     if ( ! segments)
>     {
>         // record error stats
>         IOLog("%s, getPhysicalSegmentswithCoalesce returned zero\n", 
> __FUNCTION__);
>         freePacket( m);
>         return kIOReturnOutputDropped;
>     }
> 
>     txActiveCount++; // update counter
> 
>     int				i = txHead;
>     tulip_descriptor_t *	d = &tx_desc_ring[ txHead];
> 
>     IOLog("%s, output pkt length = %d\n", __FUNCTION__, m->m_len);
> 	// tells chip to use chain-mode, plus length of mbuf seg
>     d->control = _descOrder( ADMTEK_TX_CTL_TLINK | m->m_len);
>     d->status  = 0;
> 	// assign physical address to buffer1
>     d->buffer1 = _descOrder( vector.location);
> 	// save the virtual address so we can safely call freePacket()
>     tx_mbuf_ring[ i] = m;
>     IOLog("%s, tx mbuf 0x%08x in desc %d\n", __FUNCTION__, (UInt32) vector.
> location, i);
> 
>     d->control |= _descOrder( ADMTEK_TX_CTL_FIRSTFRAG);
>     d->control |= _descOrder( ADMTEK_TX_CTL_LASTFRAG);
> 	// force interrupt every 4 packets to allow for housekeeping tasks
>     d->control |= _descOrder( ADMTEK_TX_CTL_FINT);
> 	// set OWN bit so chip knows it can take control of descriptor
>     d->status = _descOrder( ADMTEK_TX_STAT_OWN);
> 
>     RING_INCREMENT( txHead, TULIP_TX_RING_LENGTH);
> 	IOLog("%s, B4 s = 0x%08x c = 0x%08x b1 = 0x%08x b2 = 0x%08x\n", 
> __FUNCTION__,
>         _descOrder(tx_desc_ring[i].status), 
> _descOrder(tx_desc_ring[i].control),
>         _descOrder(tx_desc_ring[i].buffer1), 
> _descOrder(tx_desc_ring[i].buffer2));
> 
> 	// kick transmitter
>     _writeRegister( ADMTEK_TXSTART, 0xbaadf00d);
> 
>     IOLog("%s, kick tx-er\n", __FUNCTION__);IOSleep(20);
> 	IOLog("%s, AF s = 0x%08x c = 0x%08x b1 = 0x%08x b2 = 0x%08x\n", 
> __FUNCTION__,
>         _descOrder(tx_desc_ring[i].status), 
> _descOrder(tx_desc_ring[i].control),
>         _descOrder(tx_desc_ring[i].buffer1), 
> _descOrder(tx_desc_ring[i].buffer2));
> 
>     return kIOReturnOutputSuccess;
> }
> 
> Any ideas?
> 
> cr
> 

-- 
/~\ The ASCII                         Sean Davis
\ / Ribbon Campaign                    aka dive
 X  Against HTML
/ \ Email!               http://eros.endersgame.net:8000/~dive