9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* [9fans] Realtek RTL8139 driver
@ 2002-01-24 16:27 jmk
  2002-01-25 15:59 ` Jason Gurtz
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: jmk @ 2002-01-24 16:27 UTC (permalink / raw)
  To: 9fans

Andrey Mirtchovski <andrey@lanl.gov> and I have finished the
Realtek RTL8139 driver, both system and 9load. If you want the
driver, let us know.

--jim


^ permalink raw reply	[flat|nested] 6+ messages in thread

* RE: [9fans] Realtek RTL8139 driver
  2002-01-24 16:27 [9fans] Realtek RTL8139 driver jmk
@ 2002-01-25 15:59 ` Jason Gurtz
  2002-01-28 11:12 ` deicide
  2002-01-28 11:12 ` north_
  2 siblings, 0 replies; 6+ messages in thread
From: Jason Gurtz @ 2002-01-25 15:59 UTC (permalink / raw)
  To: 9fans



> Andrey Mirtchovski <andrey@lanl.gov> and I have finished the
> Realtek RTL8139 driver, both system and 9load. If you want the
> driver, let us know.

I have several of cheap cards with this chip, please post a link.

~Jason

--


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [9fans] Realtek RTL8139 driver
  2002-01-24 16:27 [9fans] Realtek RTL8139 driver jmk
  2002-01-25 15:59 ` Jason Gurtz
@ 2002-01-28 11:12 ` deicide
  2002-01-28 11:12 ` north_
  2 siblings, 0 replies; 6+ messages in thread
From: deicide @ 2002-01-28 11:12 UTC (permalink / raw)
  To: 9fans

<jmk@plan9.bell-labs.com> wrote in message
news:20020124162740.3F8DE19A88@mail.cse.psu.edu...
> Andrey Mirtchovski <andrey@lanl.gov> and I have finished the
> Realtek RTL8139 driver, both system and 9load. If you want the
> driver, let us know.
>
> --jim

My favourite chip. I use 8139s everywhere, and it's immensely popular with
manufacturers worldwide. May I commend you on a very good choice of chip to
support. :-)

~deicide.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [9fans] Realtek RTL8139 driver
  2002-01-24 16:27 [9fans] Realtek RTL8139 driver jmk
  2002-01-25 15:59 ` Jason Gurtz
  2002-01-28 11:12 ` deicide
@ 2002-01-28 11:12 ` north_
  2 siblings, 0 replies; 6+ messages in thread
From: north_ @ 2002-01-28 11:12 UTC (permalink / raw)
  To: 9fans

> Andrey Mirtchovski <andrey@lanl.gov> and I have finished the
> Realtek RTL8139 driver, both system and 9load. If you want the
> driver, let us know.
>
> --jim
Heck yea I want it ;)
I don't have the time to finish mine (or should I say the
driver development skill to finish it quickly?) Heheh, I'm
workin on that :P
Don
northern_snow78@yahoo.com
http://blessedchildren.virtualave.net/


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [9fans] Realtek RTL8139 driver
@ 2002-01-29  2:54 jmk
  0 siblings, 0 replies; 6+ messages in thread
From: jmk @ 2002-01-29  2:54 UTC (permalink / raw)
  To: 9fans

I wrote the instructions in the README file for adding to 9load
based on our current copy of the source. I hadn't realised that the
'ethercards[]' array had moved from load.c to ether.c since the
distribution. So, the instructions should say


To add to 9load:
	1) do the above copy;
	2) in /sys/src/boot/pc/load.c after
		{ "AMD79C970", amd79c970reset, },
	   add
		{ "RTL8139", rtl8139pnp, },
	   and after
		extern int amd79c970reset(Ether*);
	   add
		extern int rtl8139pnp(Ether*);
	3) in /sys/src/boot/pc/mkfile after
		ether8003.$O\
	   add
		ether8139.$O\
	4) mk


Sorry about the confusion.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [9fans] Realtek RTL8139 driver
@ 2002-01-28 14:47 andrey mirtchovski
  0 siblings, 0 replies; 6+ messages in thread
From: andrey mirtchovski @ 2002-01-28 14:47 UTC (permalink / raw)
  To: 9fans

[-- Attachment #1: Type: text/plain, Size: 88 bytes --]

here it is..  tell either me or jmk@plan9.bell-labs.com if you have
any problems :)


[-- Attachment #2.1: Type: text/plain, Size: 316 bytes --]

The following attachment had content that we can't
prove to be harmless.  To avoid possible automatic
execution, we changed the content headers.
The original header was:

	Content-Disposition: attachment; filename=ether8139.bundle
	Content-Type: text/plain; charset="US-ASCII"
	Content-Transfer-Encoding: 7bit

[-- Attachment #2.2: ether8139.bundle.suspect --]
[-- Type: application/octet-stream, Size: 37004 bytes --]

# To unbundle, run this file
echo README
sed 's/.//' >README <<'//GO.SYSIN DD README'
-This bundle contains 3 files:
-	README			- this file
-	ether8139.c.kernel	- copy to /sys/src/9/pc
-	ether8139.c.9load	- copy to /sys/src/boot/pc
-
-To add to the kernel:
-	1) do the above copy;
-	2) edit whatever configuration file you use to add
-		ether8139	pci
-	   in the 'link' section;
-	3) mk
-
-To add to 9load:
-	1) do the above copy;
-	2) add this to /sys/src/boot/pc/ether.c:
-		20a21
-		> extern int rtl8139pnp(Ether*);
-		38a40
-		> 	{ "RTL8139", rtl8139pnp, },
-	3) add this to /sys/src/boot/pc/mkfile:
-		53a54
-		> 	ether8139.$O\
-	4) mk
-
-The 'type' of the interface for plan9.ini is 'rtl8139', e.g.
-	ether0=type=rtl8139
-
-The driver will handle RTL8139 chips which have had the PCI Vendor
-and Device ID changed, e.g. the SMC EZ-Card. There is a table in the
-driver containing (VendorID<<16)|DeviceID to match against. E.g. the
-generic Realtek value is (0x8139<<16)|0x10EC and the SMC EZ-Card is
-(0x1211<<16)|0x1113.
-It is possible to tell the driver to match against a new card not in
-the table by supplying the PCI ID in a plan9.ini option, e.g.
-	ether0=type=rtl8139 id=0x813910EC
-If you come across such a card, please let us know so it can be added
-to the internal driver table.
-
---jim
//GO.SYSIN DD README
echo ether8139.c.kernel
sed 's/.//' >ether8139.c.kernel <<'//GO.SYSIN DD ether8139.c.kernel'
-/*
- * Realtek 8139 (but not the 8129).
- * Error recovery for the various over/under -flow conditions
- * may need work.
- */
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "../port/error.h"
-#include "../port/netif.h"
-
-#include "etherif.h"
-
-enum {					/* registers */
-	Idr0		= 0x0000,	/* MAC address */
-	Mar0		= 0x0008,	/* Multicast address */
-	Tsd0		= 0x0010,	/* Transmit Status Descriptor0 */
-	Tsad0		= 0x0020,	/* Transmit Start Address Descriptor0 */
-	Rbstart		= 0x0030,	/* Receive Buffer Start Address */
-	Erbcr		= 0x0034,	/* Early Receive Byte Count */
-	Ersr		= 0x0036,	/* Early Receive Status */
-	Cr		= 0x0037,	/* Command Register */
-	Capr		= 0x0038,	/* Current Address of Packet Read */
-	Cbr		= 0x003A,	/* Current Buffer Address */
-	Imr		= 0x003C,	/* Interrupt Mask */
-	Isr		= 0x003E,	/* Interrupt Status */
-	Tcr		= 0x0040,	/* Transmit Configuration */
-	Rcr		= 0x0044,	/* Receive Configuration */
-	Tctr		= 0x0048,	/* Timer Count */
-	Mpc		= 0x004C,	/* Missed Packet Counter */
-	Cr9346		= 0x0050,	/* 9346 Command Register */
-	Config0		= 0x0051,	/* Configuration Register 0 */
-	Config1		= 0x0052,	/* Configuration Register 1 */
-	TimerInt	= 0x0054,	/* Timer Interrupt */
-	Msr		= 0x0058,	/* Media Status */
-	Config3		= 0x0059,	/* Configuration Register 3 */
-	Config4		= 0x005A,	/* Configuration Register 4 */
-	Mulint		= 0x005C,	/* Multiple Interrupt Select */
-	RerID		= 0x005E,	/* PCI Revision ID */
-	Tsad		= 0x0060,	/* Transmit Status of all Descriptors */
-
-	Bmcr		= 0x0062,	/* Basic Mode Control */
-	Bmsr		= 0x0064,	/* Basic Mode Status */
-	Anar		= 0x0066,	/* Auto-Negotiation Advertisment */
-	Anlpar		= 0x0068,	/* Auto-Negotiation Link Partner */
-	Aner		= 0x006A,	/* Auto-Negotiation Expansion */
-	Dis		= 0x006C,	/* Disconnect Counter */
-	Fcsc		= 0x006E,	/* False Carrier Sense Counter */
-	Nwaytr		= 0x0070,	/* N-way Test */
-	Rec		= 0x0072,	/* RX_ER Counter */
-	Cscr		= 0x0074,	/* CS Configuration */
-	Phy1parm	= 0x0078,	/* PHY Parameter 1 */
-	Twparm		= 0x007C,	/* Twister Parameter */
-	Phy2parm	= 0x0080,	/* PHY Parameter 2 */
-};
-
-enum {					/* Cr */
-	Bufe		= 0x01,		/* Rx Buffer Empty */
-	Te		= 0x04,		/* Transmitter Enable */
-	Re		= 0x08,		/* Receiver Enable */
-	Rst		= 0x10,		/* Software Reset */
-};
-
-enum {					/* Imr/Isr */
-	Rok		= 0x0001,	/* Receive OK */
-	Rer		= 0x0002,	/* Receive Error */
-	Tok		= 0x0004,	/* Transmit OK */
-	Ter		= 0x0008,	/* Transmit Error */
-	Rxovw		= 0x0010,	/* Receive Buffer Overflow */
-	PunLc		= 0x0020,	/* Packet Underrun or Link Change */
-	Fovw		= 0x0040,	/* Receive FIFO Overflow */
-	Clc		= 0x2000,	/* Cable Length Change */
-	Timer		= 0x4000,	/* Timer */
-	Serr		= 0x8000,	/* System Error */
-};
-
-enum {					/* Tcr */
-	Clrabt		= 0x00000001,	/* Clear Abort */
-	TxrrSHIFT	= 4,		/* Transmit Retry Count */
-	TxrrMASK	= 0x000000F0,
-	MtxdmaSHIFT	= 8,		/* Max. DMA Burst Size */
-	MtxdmaMASK	= 0x00000700,
-	Mtxdma2048	= 0x00000700,
-	Acrc		= 0x00010000,	/* Append CRC (not) */
-	LbkSHIFT	= 17,		/* Loopback Test */
-	LbkMASK		= 0x00060000,
-	Rtl8139ArevG	= 0x00800000,	/* RTL8139A Rev. G ID */
-	IfgSHIFT	= 24,		/* Interframe Gap */
-	IfgMASK		= 0x03000000,
-	HwveridSHIFT	= 26,		/* Hardware Version ID */
-	HwveridMASK	= 0x7C000000,
-};
-
-enum {					/* Rcr */
-	Aap		= 0x00000001,	/* Accept All Packets */
-	Apm		= 0x00000002,	/* Accept Physical Match */
-	Am		= 0x00000004,	/* Accept Multicast */
-	Ab		= 0x00000008,	/* Accept Broadcast */
-	Ar		= 0x00000010,	/* Accept Runt */
-	Aer		= 0x00000020,	/* Accept Error */
-	Sel9356		= 0x00000040,	/* 9356 EEPROM used */
-	Wrap		= 0x00000080,	/* Rx Buffer Wrap Control */
-	MrxdmaSHIFT	= 8,		/* Max. DMA Burst Size */
-	MrxdmaMASK	= 0x00000700,
-	Mrxdmaunlimited	= 0x00000700,
-	RblenSHIFT	= 11,		/* Receive Buffer Length */
-	RblenMASK	= 0x00001800,
-	Rblen8K		= 0x00000000,	/* 8KB+16 */
-	Rblen16K	= 0x00000800,	/* 16KB+16 */
-	Rblen32K	= 0x00001000,	/* 32KB+16 */
-	Rblen64K	= 0x00001800,	/* 64KB+16 */
-	RxfthSHIFT	= 13,		/* Receive Buffer Length */
-	RxfthMASK	= 0x0000E000,
-	Rxfth256	= 0x00008000,
-	Rxfthnone	= 0x0000E000,
-	Rer8		= 0x00010000,	/* Accept Error Packets > 8 bytes */
-	MulERINT	= 0x00020000,	/* Multiple Early Interrupt Select */
-	ErxthSHIFT	= 24,		/* Early Rx Threshold */
-	ErxthMASK	= 0x0F000000,
-	Erxthnone	= 0x00000000,
-};
-
-enum {					/* Received Packet Status */
-	Rcok		= 0x0001,	/* Receive Completed OK */
-	Fae		= 0x0002,	/* Frame Alignment Error */
-	Crc		= 0x0004,	/* CRC Error */
-	Long		= 0x0008,	/* Long Packet */
-	Runt		= 0x0010,	/* Runt Packet Received */
-	Ise		= 0x0020,	/* Invalid Symbol Error */
-	Bar		= 0x2000,	/* Broadcast Address Received */
-	Pam		= 0x4000,	/* Physical Address Matched */
-	Mar		= 0x8000,	/* Multicast Address Received */
-};
-
-enum {					/* Media Status Register */
-	Rxpf		= 0x01,		/* Pause Flag */
-	Txpf		= 0x02,		/* Pause Flag */
-	Linkb		= 0x04,		/* Inverse of Link Status */
-	Speed10		= 0x08,		/* 10Mbps */
-	Auxstatus	= 0x10,		/* Aux. Power Present Status */
-	Rxfce		= 0x40,		/* Receive Flow Control Enable */
-	Txfce		= 0x80,		/* Transmit Flow Control Enable */
-};
-
-typedef struct {			/* Soft Transmit Descriptor */
-	int	tsd;
-	int	tsad;
-	uchar*	data;
-	Block*	bp;
-} Td;
-
-enum {					/* Tsd0 */
-	SizeSHIFT	= 0,		/* Descriptor Size */
-	SizeMASK	= 0x00001FFF,
-	Own		= 0x00002000,
-	Tun		= 0x00004000,	/* Transmit FIFO Underrun */
-	Tcok		= 0x00008000,	/* Transmit COmpleted OK */
-	EtxthSHIFT	= 16,		/* Early Tx Threshold */
-	EtxthMASK	= 0x001F0000,
-	NccSHIFT	= 24,		/* Number of Collisions Count */
-	NccMASK		= 0x0F000000,
-	Cdh		= 0x10000000,	/* CD Heartbeat */
-	Owc		= 0x20000000,	/* Out of Window Collision */
-	Tabt		= 0x40000000,	/* Transmit Abort */
-	Crs		= 0x80000000,	/* Carrier Sense Lost */
-};
-
-enum {
-	Rblen		= Rblen64K,	/* Receive Buffer Length */
-	Ntd		= 4,		/* Number of Transmit Descriptors */
-	Tdbsz		= ROUNDUP(sizeof(Etherpkt), 4),
-};
-
-typedef struct Ctlr Ctlr;
-typedef struct Ctlr {
-	int	port;
-	Pcidev*	pcidev;
-	Ctlr*	next;
-	int	active;
-	int	id;
-
-	QLock	alock;			/* attach */
-	Lock	ilock;			/* init */
-	void*	alloc;			/* base of per-Ctlr allocated data */
-
-	int	rcr;			/* receive configuration register */
-	uchar*	rbstart;		/* receive buffer */
-	int	rblen;			/* receive buffer length */
-	int	ierrs;			/* receive errors */
-
-	Lock	tlock;			/* transmit */
-	Td	td[Ntd];
-	int	ntd;			/* descriptors active */
-	int	tdh;			/* host index into td */
-	int	tdi;			/* interface index into td */
-	int	etxth;			/* early transmit threshold */
-	int	taligned;		/* packet required no alignment */
-	int	tunaligned;		/* packet required alignment */
-
-	int	dis;			/* disconnect counter */
-	int	fcsc;			/* false carrier sense counter */
-	int	rec;			/* RX_ER counter */
-} Ctlr;
-
-static Ctlr* ctlrhead;
-static Ctlr* ctlrtail;
-
-#define csr8r(c, r)	(inb((c)->port+(r)))
-#define csr16r(c, r)	(ins((c)->port+(r)))
-#define csr32r(c, r)	(inl((c)->port+(r)))
-#define csr8w(c, r, b)	(outb((c)->port+(r), (int)(b)))
-#define csr16w(c, r, w)	(outs((c)->port+(r), (ushort)(w)))
-#define csr32w(c, r, l)	(outl((c)->port+(r), (ulong)(l)))
-
-static void
-rtl8139promiscuous(void* arg, int on)
-{
-	Ether *edev;
-	Ctlr * ctlr;
-
-	edev = arg;
-	ctlr = edev->ctlr;
-	ilock(&ctlr->ilock);
-
-	if(on)
-		ctlr->rcr |= Aap;
-	else
-		ctlr->rcr &= ~Aap;
-	csr32w(ctlr, Rcr, ctlr->rcr);
-	iunlock(&ctlr->ilock);
-}
-
-static long
-rtl8139ifstat(Ether* edev, void* a, long n, ulong offset)
-{
-	int l;
-	char *p;
-	Ctlr *ctlr;
-
-	ctlr = edev->ctlr;
-	p = malloc(READSTR);
-	l = snprint(p, READSTR, "rcr %8.8uX\n", ctlr->rcr);
-	l += snprint(p+l, READSTR-l, "ierrs %d\n", ctlr->ierrs);
-	l += snprint(p+l, READSTR-l, "etxth %d\n", ctlr->etxth);
-	l += snprint(p+l, READSTR-l, "taligned %d\n", ctlr->taligned);
-	l += snprint(p+l, READSTR-l, "tunaligned %d\n", ctlr->tunaligned);
-	ctlr->dis += csr16r(ctlr, Dis);
-	l += snprint(p+l, READSTR-l, "dis %d\n", ctlr->dis);
-	ctlr->fcsc += csr16r(ctlr, Fcsc);
-	l += snprint(p+l, READSTR-l, "fcscnt %d\n", ctlr->fcsc);
-	ctlr->rec += csr16r(ctlr, Rec);
-	l += snprint(p+l, READSTR-l, "rec %d\n", ctlr->rec);
-
-	l += snprint(p+l, READSTR-l, "Tcr %8.8luX\n", csr32r(ctlr, Tcr));
-	l += snprint(p+l, READSTR-l, "Config0 %2.2uX\n", csr8r(ctlr, Config0));
-	l += snprint(p+l, READSTR-l, "Config1 %2.2uX\n", csr8r(ctlr, Config1));
-	l += snprint(p+l, READSTR-l, "Msr %2.2uX\n", csr8r(ctlr, Msr));
-	l += snprint(p+l, READSTR-l, "Config3 %2.2uX\n", csr8r(ctlr, Config3));
-	l += snprint(p+l, READSTR-l, "Config4 %2.2uX\n", csr8r(ctlr, Config4));
-
-	l += snprint(p+l, READSTR-l, "Bmcr %4.4uX\n", csr16r(ctlr, Bmcr));
-	l += snprint(p+l, READSTR-l, "Bmsr %4.4uX\n", csr16r(ctlr, Bmsr));
-	l += snprint(p+l, READSTR-l, "Anar %4.4uX\n", csr16r(ctlr, Anar));
-	l += snprint(p+l, READSTR-l, "Anlpar %4.4uX\n", csr16r(ctlr, Anlpar));
-	l += snprint(p+l, READSTR-l, "Aner %4.4uX\n", csr16r(ctlr, Aner));
-	l += snprint(p+l, READSTR-l, "Nwaytr %4.4uX\n", csr16r(ctlr, Nwaytr));
-	snprint(p+l, READSTR-l, "Cscr %4.4uX\n", csr16r(ctlr, Cscr));
-	n = readstr(offset, a, n, p);
-	free(p);
-
-	return n;
-}
-
-static int
-rtl8139reset(Ctlr* ctlr)
-{
-	/*
-	 * Soft reset the controller.
-	 */
-	csr8w(ctlr, Cr, Rst);
-	while(csr8r(ctlr, Cr) & Rst)
-		;
-
-	return 0;
-}
-
-static void
-rtl8139halt(Ctlr* ctlr)
-{
-	int i;
-
-	csr8w(ctlr, Cr, 0);
-	csr16w(ctlr, Imr, 0);
-	csr16w(ctlr, Isr, ~0);
-
-	for(i = 0; i < Ntd; i++){
-		if(ctlr->td[i].bp == nil)
-			continue;
-		freeb(ctlr->td[i].bp);
-		ctlr->td[i].bp = nil;
-	}
-}
-
-static void
-rtl8139init(Ether* edev)
-{
-	int i;
-	ulong r;
-	Ctlr *ctlr;
-	uchar *alloc;
-
-	ctlr = edev->ctlr;
-	ilock(&ctlr->ilock);
-
-	rtl8139halt(ctlr);
-
-	/*
-	 * MAC Address.
-	 */
-	r = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0];
-	csr32w(ctlr, Idr0, r);
-	r = (edev->ea[5]<<8)|edev->ea[4];
-	csr32w(ctlr, Idr0+4, r);
-
-	/*
-	 * Receiver
-	 */
-	alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 32);
-	ctlr->rbstart = alloc;
-	alloc += ctlr->rblen+16;
-	memset(ctlr->rbstart, 0, ctlr->rblen+16);
-	csr32w(ctlr, Rbstart, PCIWADDR(ctlr->rbstart));
-	ctlr->rcr = Rxfth256|Rblen|Mrxdmaunlimited|Ab|Apm;
-
-	/*
-	 * Transmitter.
-	 */
-	for(i = 0; i < Ntd; i++){
-		ctlr->td[i].tsd = Tsd0+i*4;
-		ctlr->td[i].tsad = Tsad0+i*4;
-		ctlr->td[i].data = alloc;
-		alloc += Tdbsz;
-		ctlr->td[i].bp = nil;
-	}
-	ctlr->ntd = ctlr->tdh = ctlr->tdi = 0;
-	ctlr->etxth = 128/32;
-
-	/*
-	 * Interrupts.
-	 */
-	csr32w(ctlr, TimerInt, 0);
-	csr16w(ctlr, Imr, Serr|Timer|Fovw|PunLc|Rxovw|Ter|Tok|Rer|Rok);
-	csr32w(ctlr, Mpc, 0);
-
-	/*
-	 * Enable receiver/transmitter.
-	 * Need to enable before writing the Rcr or it won't take.
-	 */
-	csr8w(ctlr, Cr, Te|Re);
-	csr32w(ctlr, Tcr, Mtxdma2048);
-	csr32w(ctlr, Rcr, ctlr->rcr);
-
-	iunlock(&ctlr->ilock);
-}
-
-static void
-rtl8139attach(Ether* edev)
-{
-	Ctlr *ctlr;
-
-	ctlr = edev->ctlr;
-	qlock(&ctlr->alock);
-	if(ctlr->alloc == nil){
-		ctlr->rblen = 1<<((Rblen>>RblenSHIFT)+13);
-		ctlr->alloc = mallocz(ctlr->rblen+16 + Ntd*Tdbsz + 32, 0);
-		rtl8139init(edev);
-	}
-	qunlock(&ctlr->alock);
-}
-
-static void
-rtl8139txstart(Ether* edev)
-{
-	Td *td;
-	int size;
-	Block *bp;
-	Ctlr *ctlr;
-
-	ctlr = edev->ctlr;
-	while(ctlr->ntd < Ntd){
-		bp = qget(edev->oq);
-		if(bp == nil)
-			break;
-		size = BLEN(bp);
-
-		td = &ctlr->td[ctlr->tdh];
-		if(((int)bp->rp) & 0x03){
-			memmove(td->data, bp->rp, size);
-			freeb(bp);
-			csr32w(ctlr, td->tsad, PCIWADDR(td->data));
-			ctlr->tunaligned++;
-		}
-		else{
-			td->bp = bp;
-			csr32w(ctlr, td->tsad, PCIWADDR(bp->rp));
-			ctlr->taligned++;
-		}
-		csr32w(ctlr, td->tsd, (ctlr->etxth<<EtxthSHIFT)|size);
-
-		ctlr->ntd++;
-		ctlr->tdh = NEXT(ctlr->tdh, Ntd);
-	}
-}
-
-static void
-rtl8139transmit(Ether* edev)
-{
-	Ctlr *ctlr;
-
-	ctlr = edev->ctlr;
-	ilock(&ctlr->tlock);
-	rtl8139txstart(edev);
-	iunlock(&ctlr->tlock);
-}
-
-static void
-rtl8139receive(Ether* edev)
-{
-	Block *bp;
-	Ctlr *ctlr;
-	ushort capr;
-	uchar cr, *p;
-	int l, length, status;
-
-	ctlr = edev->ctlr;
-
-	/*
-	 * Capr is where the host is reading from,
-	 * Cbr is where the NIC is currently writing.
-	 */
-	capr = (csr16r(ctlr, Capr)+16) % ctlr->rblen;
-	while(!(csr8r(ctlr, Cr) & Bufe)){
-		p = ctlr->rbstart+capr;
-
-		/*
-		 * Apparently the packet length may be 0xFFF0 if
-		 * the NIC is still copying the packet into memory.
-		 */
-		length = (*(p+3)<<8)|*(p+2);
-		if(length == 0xFFF0)
-			break;
-		status = (*(p+1)<<8)|*p;
-
-		if(!(status & Rcok)){
-			if(status & (Ise|Fae))
-				edev->frames++;
-			if(status & Crc)
-				edev->crcs++;
-			if(status & (Runt|Long))
-				edev->buffs++;
-
-			/*
-			 * Reset the receiver.
-			 * Also may have to restore the multicast list
-			 * here too if it ever gets used.
-			 */
-			cr = csr8r(ctlr, Cr);
-			csr8w(ctlr, Cr, cr & ~Re);
-			csr32w(ctlr, Rbstart, PCIWADDR(ctlr->rbstart));
-			csr8w(ctlr, Cr, cr);
-			csr32w(ctlr, Rcr, ctlr->rcr);
-
-			continue;
-		}
-
-		/*
-		 * Receive Completed OK.
-		 * Very simplistic; there are ways this could be done
-		 * without copying, but the juice probably isn't worth
-		 * the squeeze.
-		 * The packet length includes a 4 byte CRC on the end.
-		 */
-		capr = (capr+4) % ctlr->rblen;
-		p = ctlr->rbstart+capr;
-		capr = (capr+length) % ctlr->rblen;
-
-		bp = iallocb(length);
-		if(p+length >= ctlr->rbstart+ctlr->rblen){
-			l = ctlr->rbstart+ctlr->rblen - p;
-			if(bp != nil){
-				memmove(bp->rp, p, l);
-				bp->wp += l;
-				if(l == length)
-					bp->wp -= 4;
-			}
-			length -= l;
-			p = ctlr->rbstart;
-		}
-		if(length > 0 && bp != nil){
-			length -= 4;
-			memmove(bp->wp, p, length);
-			bp->wp += length;
-		}
-
-		capr = ROUNDUP(capr, 4);
-		csr16w(ctlr, Capr, capr-16);
-
-		if(bp != nil)
-			etheriq(edev, bp, 1);
-	}
-}
-
-static void
-rtl8139interrupt(Ureg*, void* arg)
-{
-	Td *td;
-	Ctlr *ctlr;
-	Ether *edev;
-	int isr, msr, tsd;
-
-	edev = arg;
-	ctlr = edev->ctlr;
-
-	while((isr = csr16r(ctlr, Isr)) != 0){
-		csr16w(ctlr, Isr, isr);
-		if(isr & (Fovw|PunLc|Rxovw|Rer|Rok)){
-			rtl8139receive(edev);
-			if(!(isr & Rok))
-				ctlr->ierrs++;
-			isr &= ~(Fovw|Rxovw|Rer|Rok);
-		}
-
-		if(isr & (Ter|Tok)){
-			ilock(&ctlr->tlock);
-			while(ctlr->ntd){
-				td = &ctlr->td[ctlr->tdi];
-				tsd = csr32r(ctlr, td->tsd);
-				if(!(tsd & (Tabt|Tun|Tcok)))
-					break;
-
-				if(!(tsd & Tcok)){
-					if(tsd & Tun){
-						if(ctlr->etxth < ETHERMAXTU/32)
-							ctlr->etxth++;
-					}
-					edev->oerrs++;
-				}
-
-				if(td->bp != nil){
-					freeb(td->bp);
-					td->bp = nil;
-				}
-
-				ctlr->ntd--;
-				ctlr->tdi = NEXT(ctlr->tdi, Ntd);
-			}
-			rtl8139txstart(edev);
-			iunlock(&ctlr->tlock);
-			isr &= ~(Ter|Tok);
-		}
-
-		if(isr & PunLc){
-			/*
-			 * Maybe the link changed - do we care very much?
-			 */
-			msr = csr8r(ctlr, Msr);
-			if(!(msr & Linkb)){
-				if(!(msr & Speed10) && edev->mbps != 100){
-					edev->mbps = 100;
-					qsetlimit(edev->oq, 256*1024);
-				}
-				else if((msr & Speed10) && edev->mbps != 10){
-					edev->mbps = 10;
-					qsetlimit(edev->oq, 65*1024);
-				}
-			}
-			isr &= ~(Clc|PunLc);
-		}
-
-		/*
-		 * Only Serr|Timer should be left by now.
-		 * Should anything be done to tidy up? TimerInt isn't
-		 * used so that can be cleared. A PCI bus error is indicated
-		 * by Serr, that's pretty serious; is there anyhing to do
-		 * other than try to reinitialise the chip?
-		 */
-		if(isr != 0){
-			iprint("rtl8139interrupt: imr %4.4uX isr %4.4uX\n",
-				csr16r(ctlr, Imr), isr);
-			if(isr & Timer)
-				csr32w(ctlr, TimerInt, 0);
-			if(isr & Serr)
-				rtl8139init(edev);
-		}
-	}
-}
-
-static Ctlr*
-rtl8139match(Ether* edev, int id)
-{
-	int port;
-	Pcidev *p;
-	Ctlr *ctlr;
-
-	/*
-	 * Any adapter matches if no edev->port is supplied,
-	 * otherwise the ports must match.
-	 */
-	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
-		if(ctlr->active)
-			continue;
-		p = ctlr->pcidev;
-		if(((p->did<<16)|p->vid) != id)
-			continue;
-		port = p->mem[0].bar & ~0x01;
-		if(edev->port != 0 && edev->port != port)
-			continue;
-
-		if(ioalloc(port, p->mem[0].size, 0, "rtl8139") < 0){
-			print("rtl8139: port 0x%uX in use\n", port);
-			continue;
-		}
-
-		ctlr->port = port;
-		if(rtl8139reset(ctlr))
-			continue;
-		pcisetbme(p);
-
-		ctlr->active = 1;
-		return ctlr;
-	}
-	return nil;
-}
-
-static struct {
-	char*	name;
-	int	id;
-} rtl8139pci[] = {
-	{ "rtl8139",	(0x8139<<16)|0x10EC, },	/* generic */
-	{ "smc1211",	(0x1211<<16)|0x1113, },	/* SMC EZ-Card */
-	{ nil },
-};
-
-static int
-rtl8139pnp(Ether* edev)
-{
-	int i, id;
-	Pcidev *p;
-	Ctlr *ctlr;
-	uchar ea[Eaddrlen];
-
-	/*
-	 * Make a list of all ethernet controllers
-	 * if not already done.
-	 */
-	if(ctlrhead == nil){
-		p = nil;
-		while(p = pcimatch(p, 0, 0)){
-			if(p->ccrb != 0x02 || p->ccru != 0)
-				continue;
-			ctlr = malloc(sizeof(Ctlr));
-			ctlr->pcidev = p;
-			ctlr->id = (p->did<<16)|p->vid;
-
-			if(ctlrhead != nil)
-				ctlrtail->next = ctlr;
-			else
-				ctlrhead = ctlr;
-			ctlrtail = ctlr;
-		}
-	}
-
-	/*
-	 * Is it an RTL8139 under a different name?
-	 * Normally a search is made through all the found controllers
-	 * for one which matches any of the known vid+did pairs.
-	 * If a vid+did pair is specified a search is made for that
-	 * specific controller only.
-	 */
-	id = 0;
-	for(i = 0; i < edev->nopt; i++){
-		if(cistrncmp(edev->opt[i], "id=", 3) == 0)
-			id = strtol(&edev->opt[i][3], nil, 0);
-	}
-
-	ctlr = nil;
-	if(id != 0)
-		ctlr = rtl8139match(edev, id);
-	else for(i = 0; rtl8139pci[i].name; i++){
-		if((ctlr = rtl8139match(edev, rtl8139pci[i].id)) != nil)
-			break;
-	}
-	if(ctlr == nil)
-		return -1;
-
-	edev->ctlr = ctlr;
-	edev->port = ctlr->port;
-	edev->irq = ctlr->pcidev->intl;
-	edev->tbdf = ctlr->pcidev->tbdf;
-
-	/*
-	 * Check if the adapter's station address is to be overridden.
-	 * If not, read it from the device and set in edev->ea.
-	 */
-	memset(ea, 0, Eaddrlen);
-	if(memcmp(ea, edev->ea, Eaddrlen) == 0){
-		i = csr32r(ctlr, Idr0);
-		edev->ea[0] = i;
-		edev->ea[1] = i>>8;
-		edev->ea[2] = i>>16;
-		edev->ea[3] = i>>24;
-		i = csr32r(ctlr, Idr0+4);
-		edev->ea[4] = i;
-		edev->ea[5] = i>>8;
-	}
-
-	edev->attach = rtl8139attach;
-	edev->transmit = rtl8139transmit;
-	edev->interrupt = rtl8139interrupt;
-	edev->ifstat = rtl8139ifstat;
-
-	edev->arg = edev;
-	edev->promiscuous = rtl8139promiscuous;
-
-	/*
-	 * This should be much more dynamic but will do for now.
-	 */
-	if((csr8r(ctlr, Msr) & (Speed10|Linkb)) == 0)
-		edev->mbps = 100;
-
-	return 0;
-}
-
-void
-ether8139link(void)
-{
-	addethercard("rtl8139", rtl8139pnp);
-}
//GO.SYSIN DD ether8139.c.kernel
echo ether8139.c.9load
sed 's/.//' >ether8139.c.9load <<'//GO.SYSIN DD ether8139.c.9load'
-/*
- * Realtek 8139 (but not the 8129).
- * Error recovery for the various over/under -flow conditions
- * may need work.
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-enum {					/* registers */
-	Idr0		= 0x0000,	/* MAC address */
-	Mar0		= 0x0008,	/* Multicast address */
-	Tsd0		= 0x0010,	/* Transmit Status Descriptor0 */
-	Tsad0		= 0x0020,	/* Transmit Start Address Descriptor0 */
-	Rbstart		= 0x0030,	/* Receive Buffer Start Address */
-	Erbcr		= 0x0034,	/* Early Receive Byte Count */
-	Ersr		= 0x0036,	/* Early Receive Status */
-	Cr		= 0x0037,	/* Command Register */
-	Capr		= 0x0038,	/* Current Address of Packet Read */
-	Cbr		= 0x003A,	/* Current Buffer Address */
-	Imr		= 0x003C,	/* Interrupt Mask */
-	Isr		= 0x003E,	/* Interrupt Status */
-	Tcr		= 0x0040,	/* Transmit Configuration */
-	Rcr		= 0x0044,	/* Receive Configuration */
-	Tctr		= 0x0048,	/* Timer Count */
-	Mpc		= 0x004C,	/* Missed Packet Counter */
-	Cr9346		= 0x0050,	/* 9346 Command Register */
-	Config0		= 0x0051,	/* Configuration Register 0 */
-	Config1		= 0x0052,	/* Configuration Register 1 */
-	TimerInt	= 0x0054,	/* Timer Interrupt */
-	Msr		= 0x0058,	/* Media Status */
-	Config3		= 0x0059,	/* Configuration Register 3 */
-	Config4		= 0x005A,	/* Configuration Register 4 */
-	Mulint		= 0x005C,	/* Multiple Interrupt Select */
-	RerID		= 0x005E,	/* PCI Revision ID */
-	Tsad		= 0x0060,	/* Transmit Status of all Descriptors */
-
-	Bmcr		= 0x0062,	/* Basic Mode Control */
-	Bmsr		= 0x0064,	/* Basic Mode Status */
-	Anar		= 0x0066,	/* Auto-Negotiation Advertisment */
-	Anlpar		= 0x0068,	/* Auto-Negotiation Link Partner */
-	Aner		= 0x006A,	/* Auto-Negotiation Expansion */
-	Dis		= 0x006C,	/* Disconnect Counter */
-	Fcsc		= 0x006E,	/* False Carrier Sense Counter */
-	Nwaytr		= 0x0070,	/* N-way Test */
-	Rec		= 0x0072,	/* RX_ER Counter */
-	Cscr		= 0x0074,	/* CS Configuration */
-	Phy1parm	= 0x0078,	/* PHY Parameter 1 */
-	Twparm		= 0x007C,	/* Twister Parameter */
-	Phy2parm	= 0x0080,	/* PHY Parameter 2 */
-};
-
-enum {					/* Cr */
-	Bufe		= 0x01,		/* Rx Buffer Empty */
-	Te		= 0x04,		/* Transmitter Enable */
-	Re		= 0x08,		/* Receiver Enable */
-	Rst		= 0x10,		/* Software Reset */
-};
-
-enum {					/* Imr/Isr */
-	Rok		= 0x0001,	/* Receive OK */
-	Rer		= 0x0002,	/* Receive Error */
-	Tok		= 0x0004,	/* Transmit OK */
-	Ter		= 0x0008,	/* Transmit Error */
-	Rxovw		= 0x0010,	/* Receive Buffer Overflow */
-	PunLc		= 0x0020,	/* Packet Underrun or Link Change */
-	Fovw		= 0x0040,	/* Receive FIFO Overflow */
-	Clc		= 0x2000,	/* Cable Length Change */
-	Timer		= 0x4000,	/* Timer */
-	Serr		= 0x8000,	/* System Error */
-};
-
-enum {					/* Tcr */
-	Clrabt		= 0x00000001,	/* Clear Abort */
-	TxrrSHIFT	= 4,		/* Transmit Retry Count */
-	TxrrMASK	= 0x000000F0,
-	MtxdmaSHIFT	= 8,		/* Max. DMA Burst Size */
-	MtxdmaMASK	= 0x00000700,
-	Mtxdma2048	= 0x00000700,
-	Acrc		= 0x00010000,	/* Append CRC (not) */
-	LbkSHIFT	= 17,		/* Loopback Test */
-	LbkMASK		= 0x00060000,
-	Rtl8139ArevG	= 0x00800000,	/* RTL8139A Rev. G ID */
-	IfgSHIFT	= 24,		/* Interframe Gap */
-	IfgMASK		= 0x03000000,
-	HwveridSHIFT	= 26,		/* Hardware Version ID */
-	HwveridMASK	= 0x7C000000,
-};
-
-enum {					/* Rcr */
-	Aap		= 0x00000001,	/* Accept All Packets */
-	Apm		= 0x00000002,	/* Accept Physical Match */
-	Am		= 0x00000004,	/* Accept Multicast */
-	Ab		= 0x00000008,	/* Accept Broadcast */
-	Ar		= 0x00000010,	/* Accept Runt */
-	Aer		= 0x00000020,	/* Accept Error */
-	Sel9356		= 0x00000040,	/* 9356 EEPROM used */
-	Wrap		= 0x00000080,	/* Rx Buffer Wrap Control */
-	MrxdmaSHIFT	= 8,		/* Max. DMA Burst Size */
-	MrxdmaMASK	= 0x00000700,
-	Mrxdmaunlimited	= 0x00000700,
-	RblenSHIFT	= 11,		/* Receive Buffer Length */
-	RblenMASK	= 0x00001800,
-	Rblen8K		= 0x00000000,	/* 8KB+16 */
-	Rblen16K	= 0x00000800,	/* 16KB+16 */
-	Rblen32K	= 0x00001000,	/* 32KB+16 */
-	Rblen64K	= 0x00001800,	/* 64KB+16 */
-	RxfthSHIFT	= 13,		/* Receive Buffer Length */
-	RxfthMASK	= 0x0000E000,
-	Rxfth256	= 0x00008000,
-	Rxfthnone	= 0x0000E000,
-	Rer8		= 0x00010000,	/* Accept Error Packets > 8 bytes */
-	MulERINT	= 0x00020000,	/* Multiple Early Interrupt Select */
-	ErxthSHIFT	= 24,		/* Early Rx Threshold */
-	ErxthMASK	= 0x0F000000,
-	Erxthnone	= 0x00000000,
-};
-
-enum {					/* Received Packet Status */
-	Rcok		= 0x0001,	/* Receive Completed OK */
-	Fae		= 0x0002,	/* Frame Alignment Error */
-	Crc		= 0x0004,	/* CRC Error */
-	Long		= 0x0008,	/* Long Packet */
-	Runt		= 0x0010,	/* Runt Packet Received */
-	Ise		= 0x0020,	/* Invalid Symbol Error */
-	Bar		= 0x2000,	/* Broadcast Address Received */
-	Pam		= 0x4000,	/* Physical Address Matched */
-	Mar		= 0x8000,	/* Multicast Address Received */
-};
-
-enum {					/* Media Status Register */
-	Rxpf		= 0x01,		/* Pause Flag */
-	Txpf		= 0x02,		/* Pause Flag */
-	Linkb		= 0x04,		/* Inverse of Link Status */
-	Speed10		= 0x08,		/* 10Mbps */
-	Auxstatus	= 0x10,		/* Aux. Power Present Status */
-	Rxfce		= 0x40,		/* Receive Flow Control Enable */
-	Txfce		= 0x80,		/* Transmit Flow Control Enable */
-};
-
-typedef struct {			/* Soft Transmit Descriptor */
-	int	tsd;
-	int	tsad;
-	uchar*	data;
-} Td;
-
-enum {					/* Tsd0 */
-	SizeSHIFT	= 0,		/* Descriptor Size */
-	SizeMASK	= 0x00001FFF,
-	Own		= 0x00002000,
-	Tun		= 0x00004000,	/* Transmit FIFO Underrun */
-	Tcok		= 0x00008000,	/* Transmit COmpleted OK */
-	EtxthSHIFT	= 16,		/* Early Tx Threshold */
-	EtxthMASK	= 0x001F0000,
-	NccSHIFT	= 24,		/* Number of Collisions Count */
-	NccMASK		= 0x0F000000,
-	Cdh		= 0x10000000,	/* CD Heartbeat */
-	Owc		= 0x20000000,	/* Out of Window Collision */
-	Tabt		= 0x40000000,	/* Transmit Abort */
-	Crs		= 0x80000000,	/* Carrier Sense Lost */
-};
-
-enum {
-	Rblen		= Rblen64K,	/* Receive Buffer Length */
-	Ntd		= 4,		/* Number of Transmit Descriptors */
-	Tdbsz		= ROUNDUP(sizeof(Etherpkt), 4),
-};
-
-typedef struct Ctlr Ctlr;
-typedef struct Ctlr {
-	int	port;
-	Pcidev*	pcidev;
-	Ctlr*	next;
-	int	active;
-	int	id;
-
-	Lock	ilock;			/* init */
-	void*	alloc;			/* base of per-Ctlr allocated data */
-
-	int	rcr;			/* receive configuration register */
-	uchar*	rbstart;		/* receive buffer */
-	int	rblen;			/* receive buffer length */
-	int	ierrs;			/* receive errors */
-
-	Lock	tlock;			/* transmit */
-	Td	td[Ntd];
-	int	ntd;			/* descriptors active */
-	int	tdh;			/* host index into td */
-	int	tdi;			/* interface index into td */
-	int	etxth;			/* early transmit threshold */
-	int	taligned;		/* packet required no alignment */
-	int	tunaligned;		/* packet required alignment */
-
-	int	dis;			/* disconnect counter */
-	int	fcsc;			/* false carrier sense counter */
-	int	rec;			/* RX_ER counter */
-} Ctlr;
-
-static Ctlr* ctlrhead;
-static Ctlr* ctlrtail;
-
-#define csr8r(c, r)	(inb((c)->port+(r)))
-#define csr16r(c, r)	(ins((c)->port+(r)))
-#define csr32r(c, r)	(inl((c)->port+(r)))
-#define csr8w(c, r, b)	(outb((c)->port+(r), (int)(b)))
-#define csr16w(c, r, w)	(outs((c)->port+(r), (ushort)(w)))
-#define csr32w(c, r, l)	(outl((c)->port+(r), (ulong)(l)))
-
-static int
-rtl8139reset(Ctlr* ctlr)
-{
-	/*
-	 * Soft reset the controller.
-	 */
-	csr8w(ctlr, Cr, Rst);
-	while(csr8r(ctlr, Cr) & Rst)
-		;
-
-	return 0;
-}
-
-static void
-rtl8139detach(Ether* edev)
-{
-	rtl8139reset(edev->ctlr);
-}
-
-static void
-rtl8139halt(Ctlr* ctlr)
-{
-	csr8w(ctlr, Cr, 0);
-	csr16w(ctlr, Imr, 0);
-	csr16w(ctlr, Isr, ~0);
-}
-
-static void
-rtl8139init(Ether* edev)
-{
-	int i;
-	ulong r;
-	Ctlr *ctlr;
-	uchar *alloc;
-
-	ctlr = edev->ctlr;
-	ilock(&ctlr->ilock);
-
-	rtl8139halt(ctlr);
-
-	/*
-	 * MAC Address.
-	 */
-	r = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0];
-	csr32w(ctlr, Idr0, r);
-	r = (edev->ea[5]<<8)|edev->ea[4];
-	csr32w(ctlr, Idr0+4, r);
-
-	/*
-	 * Receiver
-	 */
-	alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 32);
-	ctlr->rbstart = alloc;
-	alloc += ctlr->rblen+16;
-	memset(ctlr->rbstart, 0, ctlr->rblen+16);
-	csr32w(ctlr, Rbstart, PADDR(ctlr->rbstart));
-	ctlr->rcr = Rxfth256|Rblen|Mrxdmaunlimited|Ab|Apm;
-
-	/*
-	 * Transmitter.
-	 */
-	for(i = 0; i < Ntd; i++){
-		ctlr->td[i].tsd = Tsd0+i*4;
-		ctlr->td[i].tsad = Tsad0+i*4;
-		ctlr->td[i].data = alloc;
-		alloc += Tdbsz;
-	}
-	ctlr->ntd = ctlr->tdh = ctlr->tdi = 0;
-	ctlr->etxth = 128/32;
-
-	/*
-	 * Interrupts.
-	 */
-	csr32w(ctlr, TimerInt, 0);
-	csr16w(ctlr, Imr, Serr|Timer|Fovw|PunLc|Rxovw|Ter|Tok|Rer|Rok);
-	csr32w(ctlr, Mpc, 0);
-
-	/*
-	 * Enable receiver/transmitter.
-	 * Need to enable before writing the Rcr or it won't take.
-	 */
-	csr8w(ctlr, Cr, Te|Re);
-	csr32w(ctlr, Tcr, Mtxdma2048);
-	csr32w(ctlr, Rcr, ctlr->rcr);
-
-	iunlock(&ctlr->ilock);
-}
-
-static void
-rtl8139attach(Ether* edev)
-{
-	Ctlr *ctlr;
-
-	ctlr = edev->ctlr;
-	if(ctlr->alloc == nil){
-		ctlr->rblen = 1<<((Rblen>>RblenSHIFT)+13);
-		ctlr->alloc = mallocz(ctlr->rblen+16 + Ntd*Tdbsz + 32, 0);
-		rtl8139init(edev);
-	}
-}
-
-static void
-rtl8139txstart(Ether* edev)
-{
-	Td *td;
-	Ctlr *ctlr;
-	RingBuf *tb;
-
-	ctlr = edev->ctlr;
-	while(ctlr->ntd < Ntd){
-		tb = &edev->tb[edev->ti];
-		if(tb->owner != Interface)
-			break;
-
-		td = &ctlr->td[ctlr->tdh];
-		memmove(td->data, tb->pkt, tb->len);
-		csr32w(ctlr, td->tsad, PADDR(tb->pkt));
-		csr32w(ctlr, td->tsd, (ctlr->etxth<<EtxthSHIFT)|tb->len);
-
-		ctlr->ntd++;
-		ctlr->tdh = NEXT(ctlr->tdh, Ntd);
-		tb->owner = Host;
-		edev->ti = NEXT(edev->ti, edev->ntb);
-	}
-}
-
-static void
-rtl8139transmit(Ether* edev)
-{
-	Ctlr *ctlr;
-
-	ctlr = edev->ctlr;
-	ilock(&ctlr->tlock);
-	rtl8139txstart(edev);
-	iunlock(&ctlr->tlock);
-}
-
-static void
-rtl8139receive(Ether* edev)
-{
-	Ctlr *ctlr;
-	RingBuf *rb;
-	ushort capr;
-	uchar cr, *p;
-	int l, length, status;
-
-	ctlr = edev->ctlr;
-
-	/*
-	 * Capr is where the host is reading from,
-	 * Cbr is where the NIC is currently writing.
-	 */
-	capr = (csr16r(ctlr, Capr)+16) % ctlr->rblen;
-	while(!(csr8r(ctlr, Cr) & Bufe)){
-		p = ctlr->rbstart+capr;
-
-		/*
-		 * Apparently the packet length may be 0xFFF0 if
-		 * the NIC is still copying the packet into memory.
-		 */
-		length = (*(p+3)<<8)|*(p+2);
-		if(length == 0xFFF0)
-			break;
-		status = (*(p+1)<<8)|*p;
-
-		if(!(status & Rcok)){
-			/*
-			 * Reset the receiver.
-			 * Also may have to restore the multicast list
-			 * here too if it ever gets used.
-			 */
-			cr = csr8r(ctlr, Cr);
-			csr8w(ctlr, Cr, cr & ~Re);
-			csr32w(ctlr, Rbstart, PADDR(ctlr->rbstart));
-			csr8w(ctlr, Cr, cr);
-			csr32w(ctlr, Rcr, ctlr->rcr);
-
-			continue;
-		}
-
-		/*
-		 * Receive Completed OK.
-		 * Very simplistic; there are ways this could be done
-		 * without copying, but the juice probably isn't worth
-		 * the squeeze.
-		 * The packet length includes a 4 byte CRC on the end.
-		 */
-		capr = (capr+4) % ctlr->rblen;
-		p = ctlr->rbstart+capr;
-		capr = (capr+length) % ctlr->rblen;
-
-		rb = &edev->rb[edev->ri];
-		l = 0;
-		if(p+length >= ctlr->rbstart+ctlr->rblen){
-			l = ctlr->rbstart+ctlr->rblen - p;
-			if(rb->owner == Interface)
-				memmove(rb->pkt, p, l);
-			length -= l;
-			p = ctlr->rbstart;
-		}
-		if(length > 0 && rb->owner == Interface){
-			memmove(rb->pkt+l, p, length);
-			l += length;
-		}
-		if(rb->owner == Interface){
-			rb->owner = Host;
-			rb->len = l-4;
-			edev->ri = NEXT(edev->ri, edev->nrb);
-		}
-
-		capr = ROUNDUP(capr, 4);
-		csr16w(ctlr, Capr, capr-16);
-	}
-}
-
-static void
-rtl8139interrupt(Ureg*, void* arg)
-{
-	Td *td;
-	Ctlr *ctlr;
-	Ether *edev;
-	int isr, tsd;
-
-	edev = arg;
-	ctlr = edev->ctlr;
-
-	while((isr = csr16r(ctlr, Isr)) != 0){
-		csr16w(ctlr, Isr, isr);
-		if(isr & (Fovw|PunLc|Rxovw|Rer|Rok)){
-			rtl8139receive(edev);
-			if(!(isr & Rok))
-				ctlr->ierrs++;
-			isr &= ~(Fovw|Rxovw|Rer|Rok);
-		}
-
-		if(isr & (Ter|Tok)){
-			ilock(&ctlr->tlock);
-			while(ctlr->ntd){
-				td = &ctlr->td[ctlr->tdi];
-				tsd = csr32r(ctlr, td->tsd);
-				if(!(tsd & (Tabt|Tun|Tcok)))
-					break;
-
-				if(!(tsd & Tcok)){
-					if(tsd & Tun){
-						if(ctlr->etxth < ETHERMAXTU/32)
-							ctlr->etxth++;
-					}
-				}
-
-				ctlr->ntd--;
-				ctlr->tdi = NEXT(ctlr->tdi, Ntd);
-			}
-			rtl8139txstart(edev);
-			iunlock(&ctlr->tlock);
-			isr &= ~(Ter|Tok);
-		}
-
-		if(isr & PunLc)
-			isr &= ~(Clc|PunLc);
-
-		/*
-		 * Only Serr|Timer should be left by now.
-		 * Should anything be done to tidy up? TimerInt isn't
-		 * used so that can be cleared. A PCI bus error is indicated
-		 * by Serr, that's pretty serious; is there anyhing to do
-		 * other than try to reinitialise the chip?
-		 */
-		if(isr != 0){
-			print("rtl8139interrupt: imr %4.4uX isr %4.4uX\n",
-				csr16r(ctlr, Imr), isr);
-			if(isr & Timer)
-				csr32w(ctlr, TimerInt, 0);
-			if(isr & Serr)
-				rtl8139init(edev);
-		}
-	}
-}
-
-static Ctlr*
-rtl8139match(Ether* edev, int id)
-{
-	int port;
-	Pcidev *p;
-	Ctlr *ctlr;
-
-	/*
-	 * Any adapter matches if no edev->port is supplied,
-	 * otherwise the ports must match.
-	 */
-	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
-		if(ctlr->active)
-			continue;
-		p = ctlr->pcidev;
-		if(((p->did<<16)|p->vid) != id)
-			continue;
-		port = p->mem[0].bar & ~0x01;
-		if(edev->port != 0 && edev->port != port)
-			continue;
-
-		ctlr->port = port;
-		if(rtl8139reset(ctlr))
-			continue;
-		pcisetbme(p);
-
-		ctlr->active = 1;
-		return ctlr;
-	}
-	return nil;
-}
-
-static struct {
-	char*	name;
-	int	id;
-} rtl8139pci[] = {
-	{ "rtl8139",	(0x8139<<16)|0x10EC, },	/* generic */
-	{ "smc1211",	(0x1211<<16)|0x1113, },	/* SMC EZ-Card */
-	{ nil },
-};
-
-int
-rtl8139pnp(Ether* edev)
-{
-	int i, id;
-	Pcidev *p;
-	Ctlr *ctlr;
-	uchar ea[Eaddrlen];
-
-	/*
-	 * Make a list of all ethernet controllers
-	 * if not already done.
-	 */
-	if(ctlrhead == nil){
-		p = nil;
-		while(p = pcimatch(p, 0, 0)){
-			if(p->ccrb != 0x02 || p->ccru != 0)
-				continue;
-			ctlr = malloc(sizeof(Ctlr));
-			ctlr->pcidev = p;
-			ctlr->id = (p->did<<16)|p->vid;
-
-			if(ctlrhead != nil)
-				ctlrtail->next = ctlr;
-			else
-				ctlrhead = ctlr;
-			ctlrtail = ctlr;
-		}
-	}
-
-	/*
-	 * Is it an RTL8139 under a different name?
-	 * Normally a search is made through all the found controllers
-	 * for one which matches any of the known vid+did pairs.
-	 * If a vid+did pair is specified a search is made for that
-	 * specific controller only.
-	 */
-	id = 0;
-	for(i = 0; i < edev->nopt; i++){
-		if(cistrncmp(edev->opt[i], "id=", 3) == 0)
-			id = strtol(&edev->opt[i][3], nil, 0);
-	}
-
-	ctlr = nil;
-	if(id != 0)
-		ctlr = rtl8139match(edev, id);
-	else for(i = 0; rtl8139pci[i].name; i++){
-		if((ctlr = rtl8139match(edev, rtl8139pci[i].id)) != nil)
-			break;
-	}
-	if(ctlr == nil)
-		return -1;
-
-	edev->ctlr = ctlr;
-	edev->port = ctlr->port;
-	edev->irq = ctlr->pcidev->intl;
-	edev->tbdf = ctlr->pcidev->tbdf;
-
-	/*
-	 * Check if the adapter's station address is to be overridden.
-	 * If not, read it from the device and set in edev->ea.
-	 */
-	memset(ea, 0, Eaddrlen);
-	if(memcmp(ea, edev->ea, Eaddrlen) == 0){
-		i = csr32r(ctlr, Idr0);
-		edev->ea[0] = i;
-		edev->ea[1] = i>>8;
-		edev->ea[2] = i>>16;
-		edev->ea[3] = i>>24;
-		i = csr32r(ctlr, Idr0+4);
-		edev->ea[4] = i;
-		edev->ea[5] = i>>8;
-	}
-
-	edev->attach = rtl8139attach;
-	edev->transmit = rtl8139transmit;
-	edev->interrupt = rtl8139interrupt;
-	edev->detach = rtl8139detach;
-
-	return 0;
-}
//GO.SYSIN DD ether8139.c.9load

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2002-01-29  2:54 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-01-24 16:27 [9fans] Realtek RTL8139 driver jmk
2002-01-25 15:59 ` Jason Gurtz
2002-01-28 11:12 ` deicide
2002-01-28 11:12 ` north_
2002-01-28 14:47 andrey mirtchovski
2002-01-29  2:54 jmk

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).