Browse Source

Plan 9 from Bell Labs 2003-11-08

David du Colombier 20 years ago
parent
commit
e580421da4

+ 9 - 8
dist/replica/plan9.db

@@ -4587,7 +4587,7 @@ sys/man/1/history - 664 sys sys 1044909169 1709
 sys/man/1/hoc - 664 sys sys 944959676 2357
 sys/man/1/hoc - 664 sys sys 944959676 2357
 sys/man/1/idiff - 664 sys sys 1018386774 927
 sys/man/1/idiff - 664 sys sys 1018386774 927
 sys/man/1/join - 664 sys sys 957920006 2562
 sys/man/1/join - 664 sys sys 957920006 2562
-sys/man/1/jpg - 664 sys sys 1032632642 3671
+sys/man/1/jpg - 664 sys sys 1068209494 4003
 sys/man/1/kill - 664 sys sys 1018369246 1193
 sys/man/1/kill - 664 sys sys 1018369246 1193
 sys/man/1/ktrace - 664 sys sys 957920006 1330
 sys/man/1/ktrace - 664 sys sys 957920006 1330
 sys/man/1/leak - 664 sys sys 1017423522 2871
 sys/man/1/leak - 664 sys sys 1017423522 2871
@@ -4741,7 +4741,7 @@ sys/man/2/genrandom - 664 sys sys 1017251164 876
 sys/man/2/getcallerpc - 664 sys sys 964455063 670
 sys/man/2/getcallerpc - 664 sys sys 964455063 670
 sys/man/2/getenv - 664 sys sys 944959695 685
 sys/man/2/getenv - 664 sys sys 944959695 685
 sys/man/2/getfcr - 664 sys sys 1015091521 2713
 sys/man/2/getfcr - 664 sys sys 1015091521 2713
-sys/man/2/getfields - 664 sys sys 1015091522 1472
+sys/man/2/getfields - 664 sys sys 1068209043 1605
 sys/man/2/getpid - 664 sys sys 944959694 657
 sys/man/2/getpid - 664 sys sys 944959694 657
 sys/man/2/getuser - 664 sys sys 1016466457 641
 sys/man/2/getuser - 664 sys sys 1016466457 641
 sys/man/2/getwd - 664 sys sys 971455511 701
 sys/man/2/getwd - 664 sys sys 971455511 701
@@ -5250,6 +5250,7 @@ sys/src/9/pc/etherif.h - 664 sys sys 1045063564 961
 sys/src/9/pc/etherigbe.c - 664 sys sys 1067792708 42430
 sys/src/9/pc/etherigbe.c - 664 sys sys 1067792708 42430
 sys/src/9/pc/ethermii.c - 664 sys sys 1039803177 4555
 sys/src/9/pc/ethermii.c - 664 sys sys 1039803177 4555
 sys/src/9/pc/ethermii.h - 664 sys sys 1039895684 3259
 sys/src/9/pc/ethermii.h - 664 sys sys 1039895684 3259
+sys/src/9/pc/etherrhine.c - 664 sys sys 1068244865 13437
 sys/src/9/pc/ethersink.c - 664 sys sys 1048644103 1076
 sys/src/9/pc/ethersink.c - 664 sys sys 1048644103 1076
 sys/src/9/pc/ethersmc.c - 664 sys sys 1015014518 15079
 sys/src/9/pc/ethersmc.c - 664 sys sys 1015014518 15079
 sys/src/9/pc/etherwavelan.c - 664 sys sys 1026847642 3722
 sys/src/9/pc/etherwavelan.c - 664 sys sys 1026847642 3722
@@ -5298,7 +5299,7 @@ sys/src/9/pc/sd53c8xx.n - 664 sys sys 1032059019 12455
 sys/src/9/pc/sdata.c - 664 sys sys 1067722685 50288
 sys/src/9/pc/sdata.c - 664 sys sys 1067722685 50288
 sys/src/9/pc/sdmylex.c - 664 sys sys 1015014523 27750
 sys/src/9/pc/sdmylex.c - 664 sys sys 1015014523 27750
 sys/src/9/pc/sdscsi.c - 664 sys sys 1055689892 7406
 sys/src/9/pc/sdscsi.c - 664 sys sys 1055689892 7406
-sys/src/9/pc/trap.c - 664 sys sys 1067722686 20552
+sys/src/9/pc/trap.c - 664 sys sys 1068237910 20045
 sys/src/9/pc/uarti8250.c - 664 sys sys 1067722686 13859
 sys/src/9/pc/uarti8250.c - 664 sys sys 1067722686 13859
 sys/src/9/pc/uartpci.c - 664 sys sys 1015014524 2709
 sys/src/9/pc/uartpci.c - 664 sys sys 1015014524 2709
 sys/src/9/pc/usb.h - 664 sys sys 1063857246 3566
 sys/src/9/pc/usb.h - 664 sys sys 1063857246 3566
@@ -5355,7 +5356,7 @@ sys/src/9/port/devmouse.c - 664 sys sys 1067722758 12203
 sys/src/9/port/devnmouse.c - 664 sys sys 1036812999 3738
 sys/src/9/port/devnmouse.c - 664 sys sys 1036812999 3738
 sys/src/9/port/devpipe.c - 664 sys sys 1032640439 5825
 sys/src/9/port/devpipe.c - 664 sys sys 1032640439 5825
 sys/src/9/port/devpnp.c - 664 sys sys 1055688361 13021
 sys/src/9/port/devpnp.c - 664 sys sys 1055688361 13021
-sys/src/9/port/devproc.c - 664 sys sys 1067880146 28269
+sys/src/9/port/devproc.c - 664 sys sys 1068237926 28403
 sys/src/9/port/devrealtime.c - 664 sys sys 1055688366 16209
 sys/src/9/port/devrealtime.c - 664 sys sys 1055688366 16209
 sys/src/9/port/devroot.c - 664 sys sys 1067722764 4254
 sys/src/9/port/devroot.c - 664 sys sys 1067722764 4254
 sys/src/9/port/devsd.c - 664 sys sys 1055688396 28669
 sys/src/9/port/devsd.c - 664 sys sys 1055688396 28669
@@ -5366,7 +5367,7 @@ sys/src/9/port/devssl.c - 664 sys sys 1045063590 26100
 sys/src/9/port/devtinyfs.c - 664 sys sys 1015278339 15347
 sys/src/9/port/devtinyfs.c - 664 sys sys 1015278339 15347
 sys/src/9/port/devtls.c - 664 sys sys 1066737478 45222
 sys/src/9/port/devtls.c - 664 sys sys 1066737478 45222
 sys/src/9/port/devuart.c - 664 sys sys 1067722718 11683
 sys/src/9/port/devuart.c - 664 sys sys 1067722718 11683
-sys/src/9/port/edf.c - 664 sys sys 1068135508 12286
+sys/src/9/port/edf.c - 664 sys sys 1068215525 12348
 sys/src/9/port/edf.h - 664 sys sys 1067722760 1124
 sys/src/9/port/edf.h - 664 sys sys 1067722760 1124
 sys/src/9/port/error.h - 664 sys sys 1055700517 2630
 sys/src/9/port/error.h - 664 sys sys 1055700517 2630
 sys/src/9/port/fault.c - 664 sys sys 1067722722 6628
 sys/src/9/port/fault.c - 664 sys sys 1067722722 6628
@@ -5395,10 +5396,10 @@ sys/src/9/port/parse.c - 664 sys sys 1014931177 2026
 sys/src/9/port/pgrp.c - 664 sys sys 1067722718 3944
 sys/src/9/port/pgrp.c - 664 sys sys 1067722718 3944
 sys/src/9/port/portclock.c - 664 sys sys 1068135508 4305
 sys/src/9/port/portclock.c - 664 sys sys 1068135508 4305
 sys/src/9/port/portdat.h - 664 sys sys 1067722763 22621
 sys/src/9/port/portdat.h - 664 sys sys 1067722763 22621
-sys/src/9/port/portfns.h - 664 sys sys 1067722759 11369
+sys/src/9/port/portfns.h - 664 sys sys 1068215525 11376
 sys/src/9/port/portmkfile - 664 sys sys 1067722766 2098
 sys/src/9/port/portmkfile - 664 sys sys 1067722766 2098
 sys/src/9/port/print.c - 664 sys sys 1014931178 227
 sys/src/9/port/print.c - 664 sys sys 1014931178 227
-sys/src/9/port/proc.c - 664 sys sys 1068135509 24818
+sys/src/9/port/proc.c - 664 sys sys 1068215525 24867
 sys/src/9/port/qio.c - 664 sys sys 1067953182 23406
 sys/src/9/port/qio.c - 664 sys sys 1067953182 23406
 sys/src/9/port/qlock.c - 664 sys sys 1067722765 3196
 sys/src/9/port/qlock.c - 664 sys sys 1067722765 3196
 sys/src/9/port/rdb.c - 664 sys sys 1018721202 1698
 sys/src/9/port/rdb.c - 664 sys sys 1018721202 1698
@@ -5410,7 +5411,7 @@ sys/src/9/port/swap.c - 664 sys sys 1055688551 6980
 sys/src/9/port/sysfile.c - 664 sys sys 1067722760 22127
 sys/src/9/port/sysfile.c - 664 sys sys 1067722760 22127
 sys/src/9/port/sysproc.c - 664 sys sys 1067722765 15396
 sys/src/9/port/sysproc.c - 664 sys sys 1067722765 15396
 sys/src/9/port/systab.h - 664 sys sys 1062721698 3044
 sys/src/9/port/systab.h - 664 sys sys 1062721698 3044
-sys/src/9/port/taslock.c - 664 sys sys 1067722721 3348
+sys/src/9/port/taslock.c - 664 sys sys 1068209643 3532
 sys/src/9/port/thwack.c - 664 sys sys 1057323394 7253
 sys/src/9/port/thwack.c - 664 sys sys 1057323394 7253
 sys/src/9/port/thwack.h - 664 sys sys 1015278340 1792
 sys/src/9/port/thwack.h - 664 sys sys 1015278340 1792
 sys/src/9/port/tod.c - 664 sys sys 1067722762 4856
 sys/src/9/port/tod.c - 664 sys sys 1067722762 4856

+ 10 - 0
dist/replica/plan9.log

@@ -14189,3 +14189,13 @@
 1068157925 0 c 386/9load - 775 sys sys 1068156766 181788
 1068157925 0 c 386/9load - 775 sys sys 1068156766 181788
 1068157925 1 c sys/src/boot/pc/sdata.c - 664 sys sys 1068156754 35084
 1068157925 1 c sys/src/boot/pc/sdata.c - 664 sys sys 1068156754 35084
 1068159726 0 c sys/src/boot/pc/console.c - 664 sys sys 1068158999 3487
 1068159726 0 c sys/src/boot/pc/console.c - 664 sys sys 1068158999 3487
+1068210121 0 c sys/man/1/jpg - 664 sys sys 1068209494 4003
+1068210121 1 c sys/man/2/getfields - 664 sys sys 1068209043 1605
+1068210121 2 c sys/src/9/port/taslock.c - 664 sys sys 1068209643 3532
+1068215523 0 c sys/src/9/port/devproc.c - 664 sys sys 1068215525 28324
+1068215523 1 c sys/src/9/port/edf.c - 664 sys sys 1068215525 12348
+1068215523 2 c sys/src/9/port/portfns.h - 664 sys sys 1068215525 11376
+1068215523 3 c sys/src/9/port/proc.c - 664 sys sys 1068215525 24867
+1068238928 0 c sys/src/9/pc/trap.c - 664 sys sys 1068237910 20045
+1068238928 1 c sys/src/9/port/devproc.c - 664 sys sys 1068237926 28403
+1068246130 0 a sys/src/9/pc/etherrhine.c - 664 sys sys 1068244865 13437

+ 14 - 1
sys/man/1/jpg

@@ -145,6 +145,19 @@ Like
 but force the image to RGB even if it is originally grey-scale.
 but force the image to RGB even if it is originally grey-scale.
 .PD
 .PD
 .PP
 .PP
+.I Jpg
+has two extra options used to process the output of the LML
+video card (see
+.IR lml (1)):
+.TP
+.B -f
+Merge two adjacent images, which represent the two fields of a video picture,
+into a single image.
+.TP
+.B -F
+The input is a motion JPEG file, with multiple images representing frames of the movie.  Sets
+.BR -f .
+.PD
 .PP
 .PP
 The
 The
 .IR togif
 .IR togif
@@ -175,7 +188,6 @@ By default, the images are displayed as fast as they can be rendered.
 This option specifies the time, in milliseconds, to pause while
 This option specifies the time, in milliseconds, to pause while
 displaying the next named
 displaying the next named
 .IR file .
 .IR file .
-.PD
 .PP
 .PP
 .I Gif
 .I Gif
 translates files that contain a `transparency' index by attaching
 translates files that contain a `transparency' index by attaching
@@ -183,6 +195,7 @@ an alpha channel to the converted image.
 .SH SOURCE
 .SH SOURCE
 .B /sys/src/cmd/jpg
 .B /sys/src/cmd/jpg
 .SH "SEE ALSO"
 .SH "SEE ALSO"
+.IR lml (1),
 .IR page (1),
 .IR page (1),
 .IR image (6).
 .IR image (6).
 .SH BUGS
 .SH BUGS

+ 34 - 27
sys/man/2/getfields

@@ -20,45 +20,52 @@ int	gettokens(char *str, char **args, int maxargs, char *delims)
 int	tokenize(char *str, char **args, int maxargs)
 int	tokenize(char *str, char **args, int maxargs)
 .SH DESCRIPTION
 .SH DESCRIPTION
 .I Getfields
 .I Getfields
-breaks the null-terminated
-.SM UTF
-string
-.I str
-into at most
-.I maxargs
-null-terminated fields and places pointers to the start of these fields in the array
-.IR args .
-Some of the bytes in
-.I str
-are overwritten.
-If there are more than
-.I maxargs
-fields,
-only the first
+places into the array
+.I args
+pointers to the first
 .I maxargs
 .I maxargs
-fields will be set.
-.I Delims
-is a
+fields of the null terminated
 .SM UTF
 .SM UTF
-string defining a set of delimiters.
+string
+.IR str .
+Delimiters between these fields are set to null.
 .PP
 .PP
+Fields are substrings of
+.I str
+whose definition depends on the value of
+.IR multiflag.
 If
 If
 .I multiflag
 .I multiflag
 is zero,
 is zero,
 adjacent fields are separated by exactly one delimiter.
 adjacent fields are separated by exactly one delimiter.
-A string containing
-.I n
-delimiter characters
-contains
-.IR n +1
-fields.
+For example
+.EX
+
+	getfields("#alice#bob##charles###", arg, 3, 0, "#");
+
+.EE
+yields three substrings:
+null-string ,
+.BR "alice" ,
+and
+.BR "bob##charles###" .
 If the
 If the
 .I multiflag
 .I multiflag
 argument is not zero,
 argument is not zero,
 a field is a non-empty string of non-delimiters.
 a field is a non-empty string of non-delimiters.
+For example
+.EX
+
+	getfields("#alice#bob##charles###", arg, 3, 1, "#");
+
+.EE
+yields the three substrings:
+.BR "alice" ,
+.BR "bob" ,
+and
+.BR "charles###" .
 .PP
 .PP
-Getfields
-returns the number of tokens processed.
+Getfields returns the number of fields pointed to.
 .PP
 .PP
 .I Gettokens
 .I Gettokens
 is the same as
 is the same as

+ 716 - 0
sys/src/9/pc/etherrhine.c

@@ -0,0 +1,716 @@
+ /*
+	Via Rhine driver, written for VT6102.
+	Uses the ethermii to control PHY.
+
+	Currently always copies on both, tx and rx.
+	rx side could be copy-free, and tx-side might be made
+	(almost) copy-free by using (possibly) two descriptors (if it allows
+	arbitrary tx lengths, which it should..): first for alignment and
+	second for rest of the frame. Rx-part should be worth doing.
+*/
+
+#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"
+
+#include "ethermii.h"
+
+typedef struct Desc Desc;
+typedef struct Ctlr Ctlr;
+
+enum {
+	Ntxd = 4,
+	Nrxd = 4,
+	Nwait = 50,
+	Ntxstats = 9,
+	Nrxstats = 8,
+	BIGSTR = 8192,
+};
+
+struct Desc {
+	ulong stat;
+	ulong size;
+	ulong addr;
+	ulong next;
+	char *buf;
+	ulong pad[3];
+};
+
+struct Ctlr {
+	Pcidev *pci;
+	int attached;
+	int txused;
+	int txhead;
+	int txtail;
+	int rxtail;
+	ulong port;
+
+	Mii mii;
+
+	ulong txstats[Ntxstats];
+	ulong rxstats[Nrxstats];
+
+	Desc *txd;	/* wants to be aligned on 16-byte boundary */
+	Desc *rxd;
+
+	QLock attachlck;
+	Lock lock;
+};
+
+#define ior8(c, r)	(inb((c)->port+(r)))
+#define ior16(c, r)	(ins((c)->port+(r)))
+#define ior32(c, r)	(inl((c)->port+(r)))
+#define iow8(c, r, b)	(outb((c)->port+(r), (int)(b)))
+#define iow16(c, r, w)	(outs((c)->port+(r), (ushort)(w)))
+#define iow32(c, r, l)	(outl((c)->port+(r), (ulong)(l)))
+
+enum Regs {
+	Eaddr = 0x0,
+	Rcr = 0x6,
+	Tcr = 0x7,
+	Cr = 0x8,
+	Isr = 0xc,
+	Imr = 0xe,
+	McastAddr = 0x10,
+	RxdAddr = 0x18,
+	TxdAddr = 0x1C,
+	Bcr = 0x6e,
+	RhineMiiPhy = 0x6C,
+	RhineMiiSr = 0x6D,
+	RhineMiiCr = 0x70,
+	RhineMiiAddr = 0x71,
+	RhineMiiData = 0x72,
+	Eecsr = 0x74,
+	ConfigB = 0x79,
+	ConfigD = 0x7B,
+	MiscCr = 0x80,
+	HwSticky = 0x83,
+	MiscIsr = 0x84,
+	MiscImr = 0x86,
+	WolCrSet = 0xA0,
+	WolCfgSet = 0xA1,
+	WolCgSet = 0xA3,
+	WolCrClr = 0xA4,
+	PwrCfgClr = 0xA5,
+	WolCgClr = 0xA7,
+};
+
+enum Rcrbits {
+	RxErrX = 1<<0,
+	RxSmall = 1<<1,
+	RxMcast = 1<<2,
+	RxBcast = 1<<3,
+	RxProm = 1<<4,
+	RxFifo64 = 0<<5, RxFifo32 = 1<<5, RxFifo128 = 2<<5, RxFifo256 = 3<<5,
+	RxFifo512 = 4<<5, RxFifo768 = 5<<5, RxFifo1024 = 6<<5,
+	RxFifoStoreForward = 7<<5,
+};
+
+enum Tcrbits {
+	TxLoopback0 = 1<<1,
+	TxLoopback1 = 1<<2,
+	TxBackoff = 1<<3,
+	TxFifo128 = 0<<5, TxFifo256 = 1<<5, TxFifo512 = 2<<5, TxFifo1024 = 3<<5,
+	TxFifoStoreForward = 7<<5,
+};
+
+enum Crbits {
+	Init = 1<<0,
+	Start = 1<<1,
+	Stop = 1<<2,
+	RxOn = 1<<3,
+	TxOn = 1<<4,
+	Tdmd = 1<<5,
+	Rdmd = 1<<6,
+	EarlyRx = 1<<8,
+	Reserved0 = 1<<9,
+	FullDuplex = 1<<10,
+	NoAutoPoll = 1<<11,
+	Reserved1 = 1<<12,
+	Tdmd1 = 1<<13,
+	Rdmd1 = 1<<14,
+	Reset = 1<<15,
+};
+
+enum Isrbits {
+	RxOk = 1<<0,
+	TxOk = 1<<1,
+	RxErr = 1<<2,
+	TxErr = 1<<3,
+	TxBufUdf = 1<<4,
+	RxBufLinkErr = 1<<5,
+	BusErr = 1<<6,
+	CrcOvf = 1<<7,
+	EarlyRxInt = 1<<8,
+	TxFifoUdf = 1<<9,
+	RxFifoOvf = 1<<10,
+	TxPktRace = 1<<11,
+	NoRxbuf = 1<<12,
+	TxCollision = 1<<13,
+	PortCh = 1<<14,
+	GPInt = 1<<15
+};
+
+enum Bcrbits {
+	Dma32 = 0<<0, Dma64 = 1<<0, Dma128 = 2<<0,
+	Dma256 = 3<<0, Dma512 = 4<<0, Dma1024 = 5<<0,
+	DmaStoreForward = 7<<0,
+	DupRxFifo0 = 1<<3, DupRxFifo1 = 1<<4, DupRxFifo2 = 1<<5,
+	ExtraLed = 1<<6,
+	MediumSelect = 1<<7,
+	PollTimer0 = 1<<8, PollTimer1 = 1<<9, PollTimer2 = 1<<10,
+	DupTxFifo0 = 1<<11, DupTxFifo1 = 1<<12, DupTxFifo2 = 1<<13,
+};
+
+enum Eecsrbits {
+	EeAutoLoad = 1<<5,
+};
+
+enum MiscCrbits {
+	Timer0Enable= 1<<0,
+	Timer0Suspend = 1<<1,
+	HalfDuplexFlowControl = 1<<2,
+	FullDuplexFlowControl = 1<<3,
+	Timer1Enable = 1<<8,
+	ForceSoftReset = 1<<14,
+};
+
+enum HwStickybits {
+	StickyDS0 = 1<<0,
+	StickyDS1 = 1<<1,
+	WOLEna = 1<<2,
+	WOLStat = 1<<3,
+};
+
+enum WolCgbits {
+	PmeOvr = 1<<7,
+};
+
+enum Descbits {
+	OwnNic = 1<<31,		/* stat */
+	TxAbort = 1<<8,		/* stat */
+	TxError = 1<<15,		/* stat */
+	RxChainbuf = 1<<10,	/* stat */
+	RxChainStart = 1<<9,	/* stat */
+	RxChainEnd = 1<<8,		/* stat */
+	Chainbuf = 1<<15,		/* size rx & tx*/
+	TxDisableCrc = 1<<16,	/* size */
+	TxChainStart = 1<<21,	/* size */
+	TxChainEnd = 1<<22,	/* size */
+	TxInt = 1<<23,			/* size */
+};
+
+enum ConfigDbits {
+	BackoffOptional = 1<<0,
+	BackoffAMD = 1<<1,
+	BackoffDEC = 1<<2,
+	BackoffRandom = 1<<3,
+	PmccTestMode = 1<<4,
+	PciReadlineCap = 1<<5,
+	DiagMode = 1<<6,
+	MmioEnable = 1<<7,
+};
+
+enum ConfigBbits {
+	LatencyTimer = 1<<0,
+	WriteWaitState = 1<<1,
+	ReadWaitState = 1<<2,
+	RxArbit = 1<<3,
+	TxArbit = 1<<4,
+	NoMemReadline = 1<<5,
+	NoParity = 1<<6,
+	NoTxQueuing = 1<<7,
+};
+
+enum RhineMiiCrbits {
+	Mdc = 1<<0,
+	Mdi = 1<<1,
+	Mdo = 1<<2,
+	Mdout = 1<<3,
+	Mdpm = 1<<4,
+	Wcmd = 1<<5,
+	Rcmd = 1<<6,
+	Mauto = 1<<7,
+};
+
+enum RhineMiiSrbits {
+	Speed10M = 1<<0,
+	LinkFail = 1<<1,
+	PhyError = 1<<3,
+	DefaultPhy = 1<<4,
+	ResetPhy = 1<<7,
+};
+
+enum RhineMiiAddrbits {
+	Mdone = 1<<5,
+	Msrcen = 1<<6,
+	Midle = 1<<7,
+};
+
+static char *
+txstatnames[Ntxstats] = {
+	"aborts (excess collisions)",
+	"out of window collisions",
+	"carrier sense losses",
+	"fifo underflows",
+	"invalid descriptor format or underflows",
+	"system errors",
+	"reserved",
+	"transmit errors",
+	"collisions",
+};
+
+static char *
+rxstatnames[Nrxstats] = {
+	"receiver errors",
+	"crc errors",
+	"frame alignment errors",
+	"fifo overflows",
+	"long packets",
+	"run packets",
+	"system errors",
+	"buffer underflows",
+};
+
+static void
+attach(Ether *edev)
+{
+	Ctlr *ctlr;
+	Desc *txd, *rxd, *td, *rd;
+	Mii *mi;
+	MiiPhy *phy;
+	int i, s;
+	
+	ctlr = edev->ctlr;
+	qlock(&ctlr->attachlck);
+	if (ctlr->attached == 0) {
+		txd = ctlr->txd;
+		rxd = ctlr->rxd;
+		for (i = 0; i < Ntxd; ++i) {
+			td = &txd[i];
+			td->next = PCIWADDR(&txd[(i+1) % Ntxd]);
+			td->buf = xspanalloc(sizeof(Etherpkt)+4, 4, 0);
+			td->addr = PCIWADDR(td->buf);
+			td->size = 0;
+			coherence();
+			td->stat = 0;
+		}
+		for (i = 0; i < Nrxd; ++i) {
+			rd = &rxd[i];
+			rd->next = PCIWADDR(&rxd[(i+1) % Nrxd]);
+			rd->buf = xspanalloc(sizeof(Etherpkt)+4, 4, 0);
+			rd->addr = PCIWADDR(rd->buf);
+			rd->size = sizeof(Etherpkt)+4;
+			coherence();
+			rd->stat = OwnNic;
+		}
+
+		ctlr->txhead = ctlr->txtail = ctlr->rxtail = 0;
+		mi = &ctlr->mii;
+		miistatus(mi);
+		phy = mi->curphy;
+		s = splhi();
+		iow32(ctlr, TxdAddr, PCIWADDR(&txd[0]));
+		iow32(ctlr, RxdAddr, PCIWADDR(&rxd[0]));
+		iow16(ctlr, Cr, (phy->fd ? FullDuplex : 0) | NoAutoPoll | TxOn | RxOn | Start | Rdmd);
+		iow16(ctlr, Isr, 0xFFFF);
+		iow16(ctlr, Imr, 0xFFFF);
+		iow8(ctlr, MiscIsr, 0xFF);
+		iow8(ctlr, MiscImr, ~(3<<5));
+		splx(s);
+	}
+	ctlr->attached++;
+	qunlock(&ctlr->attachlck);
+}
+
+static void
+txstart(Ether *edev)
+{
+	Ctlr *ctlr;
+	Desc *txd, *td;
+	Block *b;
+	int i, txused, n;
+	ulong size;
+
+	ctlr = edev->ctlr;
+
+	txd = ctlr->txd;
+	i = ctlr->txhead;
+	txused = ctlr->txused;
+	n = 0;
+	while (txused < Ntxd) {
+		if ((b = qget(edev->oq)) == nil)
+			break;
+
+		td = &txd[i];
+
+		size = BLEN(b);
+		memmove(td->buf, b->rp, size);
+		freeb(b);
+		td->size = size | TxChainStart | TxChainEnd | TxInt; /* could reduce number of ints here */
+		coherence();
+		td->stat = OwnNic;
+		i = (i + 1) % Ntxd;
+		txused++;
+		n++;
+	}
+	if (n)
+		iow16(ctlr, Cr, ior16(ctlr, Cr) | Tdmd);
+
+	ctlr->txhead = i;
+	ctlr->txused = txused;
+}
+
+static void
+transmit(Ether *edev)
+{
+	Ctlr *ctlr;
+	ctlr = edev->ctlr;
+	ilock(&ctlr->lock);
+	txstart(edev);
+	iunlock(&ctlr->lock);
+}
+
+static void
+txcomplete(Ether *edev)
+{
+	Ctlr *ctlr;
+	Desc *txd, *td;
+	int i, txused, j;
+	ulong stat;
+
+	ctlr = edev->ctlr;
+ 	txd = ctlr->txd;
+	txused = ctlr->txused;
+	i = ctlr->txtail;
+	while (txused > 0) {
+		td = &txd[i];
+		stat = td->stat;
+
+		if (stat & OwnNic)
+			break;
+
+		ctlr->txstats[Ntxstats-1] += stat & 0xF;
+		for (j = 0; j < Ntxstats-1; ++j)
+			if (stat & (1<<(j+8)))
+				ctlr->txstats[j]++;
+
+		i = (i + 1) % Ntxd;
+		txused--;
+	}
+	ctlr->txused = txused;
+	ctlr->txtail = i;
+
+	if (txused <= Ntxd/2)
+		txstart(edev);
+}
+
+static void
+interrupt(Ureg *, void *arg)
+{
+	Ether *edev;
+	Ctlr *ctlr;
+	ushort  isr, misr;
+	ulong stat;
+	Desc *rxd, *rd;
+	int i, n, j;
+
+	edev = (Ether*)arg;
+	ctlr = edev->ctlr;
+	iow16(ctlr, Imr, 0);
+	isr = ior16(ctlr, Isr);
+	iow16(ctlr, Isr, 0xFFFF);
+	misr = ior16(ctlr, MiscIsr) & ~(3<<5); /* don't care about used defined ints */
+
+	if (isr & RxOk) {
+		Block *b;
+		int size;
+		rxd = ctlr->rxd;
+		i = ctlr->rxtail;
+
+		n = 0;
+		while ((rxd[i].stat & OwnNic) == 0) {
+			rd = &rxd[i];
+			stat = rd->stat;
+			for (j = 0; j < Nrxstats; ++j)
+				if (stat & (1<<j))
+					ctlr->rxstats[j]++;
+
+			if (stat & 0xFF)
+				iprint("rx: %lux\n", stat & 0xFF);
+
+			size = ((rd->stat>>16) & 2047) - 4;
+			b = iallocb(sizeof(Etherpkt));
+			memmove(b->wp, rd->buf, size);
+			b->wp += size;
+			etheriq(edev, b, 1);
+			rd->size = sizeof(Etherpkt)+4;
+			coherence();
+			rd->stat = OwnNic;
+			i = (i + 1) % Nrxd;
+			n++;
+		}
+		if (n)
+			iow16(ctlr, Cr, ior16(ctlr, Cr) | Rdmd);
+		ctlr->rxtail = i;
+		isr &= ~RxOk;
+	}
+	if (isr & TxOk) {
+		txcomplete(edev);
+		isr &= ~TxOk;
+	}
+	if (isr | misr)
+		iprint("etherrhine: unhandled irq(s). isr:%x misr:%x\n", isr, misr);
+
+	iow16(ctlr, Imr, 0xFFFF);
+}
+
+static void
+promiscuous(void *arg, int enable)
+{
+	Ether *edev;
+	Ctlr *ctlr;
+
+	edev = arg;
+	ctlr = edev->ctlr;
+	ilock(&ctlr->lock);
+	iow8(ctlr, Rcr, ior8(ctlr, Rcr) | (enable ? RxProm : RxBcast));
+	iunlock(&ctlr->lock);
+}
+
+static int
+miiread(Mii *mii, int phy, int reg)
+{
+	Ctlr *ctlr;
+	int n;
+
+	ctlr = mii->ctlr;
+	
+	n = Nwait;
+	while (n-- && ior8(ctlr, RhineMiiCr) & (Rcmd | Wcmd))
+		microdelay(1);
+	if (n == Nwait)
+		iprint("etherrhine: miiread: timeout\n");
+
+	iow8(ctlr, RhineMiiCr, 0);
+	iow8(ctlr, RhineMiiPhy, phy);
+	iow8(ctlr, RhineMiiAddr, reg);
+	iow8(ctlr, RhineMiiCr, Rcmd);
+
+	n = Nwait;
+	while (n-- && ior8(ctlr, RhineMiiCr) & Rcmd)
+		microdelay(1);
+	if (n == Nwait)
+		iprint("etherrhine: miiread: timeout\n");
+
+	n = ior16(ctlr, RhineMiiData);
+
+	return n;
+}
+
+static int
+miiwrite(Mii *mii, int phy, int reg, int data)
+{
+	int n;
+	Ctlr *ctlr;
+
+	ctlr = mii->ctlr;
+
+	n = Nwait;
+	while (n-- && ior8(ctlr, RhineMiiCr) & (Rcmd | Wcmd))
+		microdelay(1);
+	if (n == Nwait)
+		iprint("etherrhine: miiwrite: timeout\n");
+
+	iow8(ctlr, RhineMiiCr, 0);
+	iow8(ctlr, RhineMiiPhy, phy);
+	iow8(ctlr, RhineMiiAddr, reg);
+	iow16(ctlr, RhineMiiData, data);
+	iow8(ctlr, RhineMiiCr, Wcmd);
+
+	n = Nwait;
+	while (n-- && ior8(ctlr, RhineMiiCr) & Wcmd)
+		microdelay(1);
+	if (n == Nwait)
+		iprint("etherrhine: miiwrite: timeout\n");
+
+	return 0;
+}
+
+static void
+init(Ether *edev)
+{
+	Ctlr *ctlr;
+	MiiPhy *phy;
+	int i;
+
+	ctlr = edev->ctlr;
+
+	ilock(&ctlr->lock);
+
+	pcisetbme(ctlr->pci);
+
+	iow16(ctlr, Cr, ior16(ctlr, Cr) | Stop);
+	iow16(ctlr, Cr, ior16(ctlr, Cr) | Reset);
+
+	for (i = 0; i < Nwait; ++i) {
+		if ((ior16(ctlr, Cr) & Reset) == 0)
+			break;
+		delay(5);
+	}
+	if (i == Nwait)
+		iprint("etherrhine: reset timeout\n");
+
+	iow8(ctlr, Eecsr, ior8(ctlr, Eecsr) | EeAutoLoad);
+	for (i = 0; i < Nwait; ++i) {
+		if ((ior8(ctlr, Eecsr) & EeAutoLoad) == 0)
+			break;
+		delay(5);
+	}
+	if (i == Nwait)
+		iprint("etherrhine: eeprom autoload timeout\n");
+
+	for (i = 0; i < Eaddrlen; ++i)
+		edev->ea[i] = ior8(ctlr, Eaddr + i);
+
+	ctlr->mii.mir = miiread;
+	ctlr->mii.miw = miiwrite;
+	ctlr->mii.ctlr = ctlr;
+
+	if(mii(&ctlr->mii, ~0) == 0 || ctlr->mii.curphy == nil){
+		iprint("etherrhine: init mii failure\n");
+		return;
+	}
+	for (i = 0; i < NMiiPhy; ++i)
+		if (ctlr->mii.phy[i])
+			if (ctlr->mii.phy[i]->oui != 0xFFFFF)
+				ctlr->mii.curphy = ctlr->mii.phy[i];
+
+	miistatus(&ctlr->mii);
+	phy = ctlr->mii.curphy;
+	edev->mbps = phy->speed;
+
+	iow16(ctlr, Imr, 0);
+	iow16(ctlr, Cr, ior16(ctlr, Cr) | Stop);
+
+	iunlock(&ctlr->lock);
+}
+
+static Pcidev *
+rhinematch(ulong)
+{
+	static int nrhines = 0;
+	int nfound = 0;
+	Pcidev *p = nil;
+
+	while (p = pcimatch(p, 0x1106, 0))
+		if (p->did == 0x3065)
+			if (++nfound > nrhines) {
+				nrhines++;
+				break;
+			}
+	return p;
+}
+static long
+ifstat(Ether* edev, void* a, long n, ulong offset)
+{
+	int l = 0, i;
+	char *p;
+	Ctlr *ctlr;
+	ctlr = edev->ctlr;
+	p = malloc(BIGSTR);
+
+	for (i = 0; i < Ntxstats; ++i)
+		if (txstatnames[i])
+			l += snprint(p+l, BIGSTR - l, "tx: %s: %lud\n", txstatnames[i], ctlr->txstats[i]);
+
+	for (i = 0; i < Nrxstats; ++i)
+		if (rxstatnames[i])
+			l += snprint(p+l, BIGSTR - l, "rx: %s: %lud\n", rxstatnames[i], ctlr->rxstats[i]);
+
+/*
+	for (i = 0; i < NMiiPhyr; ++i) {
+		if ((i % 8) == 0)
+			l += snprint(p + l, BIGSTR - l, "\nmii 0x%02x:", i);
+		reg=miimir(&ctlr->mii, i);
+		reg=miimir(&ctlr->mii, i);
+		l += snprint(p + l, BIGSTR - l, " %4ux", reg);
+	}
+
+	for (i = 0; i < 0x100; i+=1) {
+		if ((i % 16) == 0)
+			l += snprint(p + l, BIGSTR - l, "\nreg 0x%02x:", i);
+		else if ((i % 2) == 0)
+			l += snprint(p + l, BIGSTR - l, " ");
+		reg=ior8(ctlr, i);
+		l += snprint(p + l, BIGSTR - l, "%02x", reg);
+	}
+	l += snprint(p + l, BIGSTR - l, " \n");
+*/
+
+
+	n = readstr(offset, a, n, p);
+	free(p);
+
+	return n;
+}
+
+static int
+pnp(Ether *edev)
+{
+	Pcidev *p;
+	Ctlr *ctlr;
+	ulong port;
+	ulong size;
+
+	p = rhinematch(edev->port);
+	if (p == nil)
+		return -1;
+
+	port = p->mem[0].bar & ~1;
+	size = p->mem[0].size;
+	if (ioalloc(port, size, 0, "rhine") < 0) {
+		print("etherrhine: couldn't allocate port %lud\n", port);
+		return -1;
+	}
+
+	if ((ctlr = malloc(sizeof(Ctlr))) == nil) {
+		print("etherrhine: couldn't allocate memory for ctlr\n");
+		return -1;
+	}
+	memset(ctlr, 0, sizeof(Ctlr));
+	ctlr->txd = xspanalloc(sizeof(Desc) * Ntxd, 16, 0);
+	ctlr->rxd = xspanalloc(sizeof(Desc) * Nrxd, 16, 0);
+		
+	ctlr->pci = p;
+	ctlr->port = port;
+
+	edev->ctlr = ctlr;
+	edev->port = ctlr->port;
+	edev->irq = p->intl;
+	edev->tbdf = p->tbdf;
+
+	init(edev);
+
+	edev->interrupt = interrupt;
+	edev->arg = edev;
+
+	edev->attach = attach;
+	edev->transmit = transmit;
+	edev->ifstat = ifstat;
+	edev->promiscuous = promiscuous;
+
+	return 0;
+}
+
+void
+etherrhinelink(void)
+{
+	addethercard("rhine", pnp);
+}

+ 5 - 23
sys/src/9/pc/trap.c

@@ -19,7 +19,7 @@ static Vctl *vctl[256];
 
 
 enum
 enum
 {
 {
-	Ntimevec = 10		/* number of time buckets for each intr */
+	Ntimevec = 20		/* number of time buckets for each intr */
 };
 };
 ulong intrtimes[256][Ntimevec];
 ulong intrtimes[256][Ntimevec];
 
 
@@ -267,7 +267,7 @@ intrtime(Mach*, int vno)
 	if(up == nil && m->perf.inidle > diff)
 	if(up == nil && m->perf.inidle > diff)
 		m->perf.inidle -= diff;
 		m->perf.inidle -= diff;
 
 
-	diff /= m->cpumhz*10;	// quantum = 10µsec
+	diff /= m->cpumhz*100;	// quantum = 100µsec
 	if(diff >= Ntimevec)
 	if(diff >= Ntimevec)
 		diff = Ntimevec-1;
 		diff = Ntimevec-1;
 	intrtimes[vno][diff]++;
 	intrtimes[vno][diff]++;
@@ -304,17 +304,12 @@ trap(Ureg* ureg)
 	char buf[ERRMAX];
 	char buf[ERRMAX];
 	Vctl *ctl, *v;
 	Vctl *ctl, *v;
 	Mach *mach;
 	Mach *mach;
-	Ureg urcopy;
-	ulong *u;
-
-	urcopy = *ureg;
-	memset(buf, 0, sizeof(buf));
 
 
 	m->perf.intrts = perfticks();
 	m->perf.intrts = perfticks();
 	user = (ureg->cs & 0xFFFF) == UESEL;
 	user = (ureg->cs & 0xFFFF) == UESEL;
 	if(user){
 	if(user){
 		up->dbgreg = ureg;
 		up->dbgreg = ureg;
-		if (m->havetsc)
+		if(m->havetsc)
 			cycles(&up->kentry);
 			cycles(&up->kentry);
 	}
 	}
 
 
@@ -329,20 +324,8 @@ trap(Ureg* ureg)
 		if(ctl->isr)
 		if(ctl->isr)
 			ctl->isr(vno);
 			ctl->isr(vno);
 		for(v = ctl; v != nil; v = v->next){
 		for(v = ctl; v != nil; v = v->next){
-			if(v->f){
+			if(v->f)
 				v->f(ureg, v->a);
 				v->f(ureg, v->a);
-				if (vno & ~0xff){
-					u = (ulong*)&u;
-					for(i = 0; i < 40; ++i && (u+=4))
-						iprint("0x%lux:	0x%lux	0x%lux	0x%lux	0x%lux\n", u, u[0], u[1], u[2], u[3]);
-					iprint("vno 0x%ux after calling %s\n", vno, v->name);
-					iprint("ureg di si bp nsp bx dx cx ax gs fs es ds trap ecode pc cs flags sp ss\n");
-					u = (ulong*)ureg;
-					for(i = 0; i < 19; i++)
-						iprint("0x%lux ", u[i]);
-					panic("vno");
-				}
-			}
 		}
 		}
 		if(ctl->eoi)
 		if(ctl->eoi)
 			ctl->eoi(vno);
 			ctl->eoi(vno);
@@ -505,7 +488,6 @@ _dumpstack(Ureg *ureg)
 	ulong l, v, i, estack;
 	ulong l, v, i, estack;
 	extern ulong etext;
 	extern ulong etext;
 
 
-return;
 	print("ktrace /kernel/path %.8lux %.8lux\n", ureg->pc, ureg->sp);
 	print("ktrace /kernel/path %.8lux %.8lux\n", ureg->pc, ureg->sp);
 	i = 0;
 	i = 0;
 	if(up
 	if(up
@@ -740,7 +722,7 @@ notify(Ureg* ureg)
 		pexit(n->msg, n->flag!=NDebug);
 		pexit(n->msg, n->flag!=NDebug);
 	}
 	}
 
 
-	if(up->notified) {
+	if(up->notified){
 		qunlock(&up->debug);
 		qunlock(&up->debug);
 		splhi();
 		splhi();
 		return 0;
 		return 0;

+ 10 - 5
sys/src/9/port/devproc.c

@@ -155,7 +155,7 @@ static Lock tlock;
 static int topens;
 static int topens;
 static int tproduced, tconsumed;
 static int tproduced, tconsumed;
 static Rendez teventr;
 static Rendez teventr;
-void	(*proctrace)(Proc*, int); 
+void	(*proctrace)(Proc*, int, vlong); 
 
 
 extern int unfair;
 extern int unfair;
 
 
@@ -265,18 +265,23 @@ procgen(Chan *c, char *name, Dirtab *tab, int, int s, Dir *dp)
 }
 }
 
 
 static void
 static void
-_proctrace(Proc*p, Tevent etype)
+_proctrace(Proc*p, Tevent etype, vlong ts)
 {
 {
 	Traceevent *te;
 	Traceevent *te;
 
 
-	if (p->trace == 0 || topens == 0 || 
-			(tproduced - tconsumed >= Nevents))
+	if (p->trace == 0 || topens == 0)
 		return;
 		return;
 
 
+	if(tproduced - tconsumed >= Nevents)
+		tconsumed = tproduced - Nevents + 1;
+		/* discard oldest, never mind the race */
 	te = &tevents[tproduced&Emask];
 	te = &tevents[tproduced&Emask];
 	te->pid = p->pid;
 	te->pid = p->pid;
 	te->etype = etype;
 	te->etype = etype;
-	te->time = todget(nil);
+	if (ts == 0)
+		te->time = todget(nil);
+	else
+		te->time = ts;
 	tproduced++;
 	tproduced++;
 
 
 	/* To avoid circular wakeup when used in combination with 
 	/* To avoid circular wakeup when used in combination with 

+ 16 - 15
sys/src/9/port/edf.c

@@ -123,6 +123,7 @@ deadlineintr(Ureg*, Timer *t)
 		return;
 		return;
 
 
 	p = t->ta;
 	p = t->ta;
+
 	DPRINT("%t deadlineintr %lud[%s]\n", todget(nil), p->pid, statename[p->state]);
 	DPRINT("%t deadlineintr %lud[%s]\n", todget(nil), p->pid, statename[p->state]);
 	/* If we're interrupting something other than the proc pointed to by t->a,
 	/* If we're interrupting something other than the proc pointed to by t->a,
 	 * we've already achieved recheduling, so we need not do anything
 	 * we've already achieved recheduling, so we need not do anything
@@ -142,7 +143,7 @@ release(Proc *p)
 {
 {
 	/* Called with edflock held */
 	/* Called with edflock held */
 	Edf *e;
 	Edf *e;
-	void (*pt)(Proc*, int);
+	void (*pt)(Proc*, int, vlong);
 
 
 	e = p->edf;
 	e = p->edf;
 	e->flags &= ~Yield;
 	e->flags &= ~Yield;
@@ -165,8 +166,10 @@ release(Proc *p)
 		e->S = e->C;
 		e->S = e->C;
 		DPRINT("%t release %lud[%s], r=%t, d=%t, t=%t, S=%t\n",
 		DPRINT("%t release %lud[%s], r=%t, d=%t, t=%t, S=%t\n",
 			now, p->pid, statename[p->state], e->r, e->d, e->t, e->S);
 			now, p->pid, statename[p->state], e->r, e->d, e->t, e->S);
-		if (pt = proctrace)
-			pt(p, SRelease);
+		if (pt = proctrace){
+			pt(p, SRelease, e->r);
+			pt(p, SDeadline, e->d);
+		}
 	}else{
 	}else{
 		DPRINT("%t release %lud[%s], too late t=%t, called from 0x%lux\n",
 		DPRINT("%t release %lud[%s], too late t=%t, called from 0x%lux\n",
 			now, p->pid, statename[p->state], e->t, getcallerpc(&p));
 			now, p->pid, statename[p->state], e->t, getcallerpc(&p));
@@ -238,7 +241,7 @@ edfrecord(Proc *p)
 {
 {
 	vlong used;
 	vlong used;
 	Edf *e;
 	Edf *e;
-	void (*pt)(Proc*, int);
+	void (*pt)(Proc*, int, vlong);
 
 
 	e = p->edf;
 	e = p->edf;
 	edflock();
 	edflock();
@@ -250,7 +253,7 @@ edfrecord(Proc *p)
 	if (e->S > 0){
 	if (e->S > 0){
 		if (e->S <= used){
 		if (e->S <= used){
 			if(pt = proctrace)
 			if(pt = proctrace)
-				pt(p, SDeadline);
+				pt(p, SSlice, now);
 			DPRINT("%t edfrecord slice used up\n", now);
 			DPRINT("%t edfrecord slice used up\n", now);
 			e->d = now;
 			e->d = now;
 			e->S = 0;
 			e->S = 0;
@@ -303,7 +306,7 @@ edfadmit(Proc *p)
 	Edf *e;
 	Edf *e;
 	int i;
 	int i;
 	Proc *r;
 	Proc *r;
-	void	(*pt)(Proc*, int);
+	void (*pt)(Proc*, int, vlong);
 
 
 	e = p->edf;
 	e = p->edf;
 	if (e->flags & Admitted)
 	if (e->flags & Admitted)
@@ -331,7 +334,7 @@ edfadmit(Proc *p)
 	e->flags |= Admitted;
 	e->flags |= Admitted;
 
 
 	if(pt = proctrace)
 	if(pt = proctrace)
-		pt(p, SAdmit);
+		pt(p, SAdmit, now);
 
 
 	/* Look for another proc with the same period to synchronize to */
 	/* Look for another proc with the same period to synchronize to */
 	SET(r);
 	SET(r);
@@ -392,13 +395,13 @@ void
 edfstop(Proc *p)
 edfstop(Proc *p)
 {
 {
 	Edf *e;
 	Edf *e;
-	void	(*pt)(Proc*, int);
+	void (*pt)(Proc*, int, vlong);
 
 
 	if ((e = p->edf) && (e->flags & Admitted)){
 	if ((e = p->edf) && (e->flags & Admitted)){
 		edflock();
 		edflock();
 		DPRINT("%t edfstop %lud[%s]\n", now, p->pid, statename[p->state]);
 		DPRINT("%t edfstop %lud[%s]\n", now, p->pid, statename[p->state]);
 		if(pt = proctrace)
 		if(pt = proctrace)
-			pt(p, SExpel);
+			pt(p, SExpel, now);
 		e->flags &= ~Admitted;
 		e->flags &= ~Admitted;
 		if (p->tt)
 		if (p->tt)
 			timerdel(p);
 			timerdel(p);
@@ -417,12 +420,12 @@ edfyield(void)
 {
 {
 	/* sleep until next release */
 	/* sleep until next release */
 	Edf *e;
 	Edf *e;
-	void	(*pt)(Proc*, int);
+	void (*pt)(Proc*, int, vlong);
 
 
 	edflock();
 	edflock();
 	e = up->edf;
 	e = up->edf;
 	if(pt = proctrace)
 	if(pt = proctrace)
-		pt(up, SYield);
+		pt(up, SYield, now);
 	while(e->t < now)
 	while(e->t < now)
 		e->t += e->T;
 		e->t += e->T;
 	e->r = e->t;
 	e->r = e->t;
@@ -444,7 +447,7 @@ edfready(Proc *p)
 	Edf *e;
 	Edf *e;
 	Schedq *rq;
 	Schedq *rq;
 	Proc *l, *pp;
 	Proc *l, *pp;
-	void (*pt)(Proc*, int);
+	void (*pt)(Proc*, int, vlong);
 
 
 	if ((e = p->edf) == nil || (e->flags & Admitted) == 0)
 	if ((e = p->edf) == nil || (e->flags & Admitted) == 0)
 		return 0;	/* Not an edf process */
 		return 0;	/* Not an edf process */
@@ -489,8 +492,6 @@ edfready(Proc *p)
 		DPRINT("%t edfready %lud %s release now\n", now, p->pid, statename[p->state]);
 		DPRINT("%t edfready %lud %s release now\n", now, p->pid, statename[p->state]);
 		/* release now */
 		/* release now */
 		release(p);
 		release(p);
-		if(pt = proctrace)
-			pt(p, SRelease);
 	}
 	}
 	DPRINT("^");
 	DPRINT("^");
 	rq = &runq[PriEdf];
 	rq = &runq[PriEdf];
@@ -517,7 +518,7 @@ edfready(Proc *p)
 	p->readytime = m->ticks;
 	p->readytime = m->ticks;
 	p->state = Ready;
 	p->state = Ready;
 	if(pt = proctrace)
 	if(pt = proctrace)
-		pt(p, SReady);
+		pt(p, SReady, now);
 	edfunlock();
 	edfunlock();
 	return 1;
 	return 1;
 }
 }

+ 1 - 1
sys/src/9/port/portfns.h

@@ -243,7 +243,7 @@ void		procinit0(void);
 void		procflushseg(Segment*);
 void		procflushseg(Segment*);
 void		procpriority(Proc*, int, int);
 void		procpriority(Proc*, int, int);
 Proc*		proctab(int);
 Proc*		proctab(int);
-extern void	(*proctrace)(Proc*, int); 
+extern void	(*proctrace)(Proc*, int, vlong); 
 void		procwired(Proc*, int);
 void		procwired(Proc*, int);
 Pte*		ptealloc(void);
 Pte*		ptealloc(void);
 Pte*		ptecpy(Pte*);
 Pte*		ptecpy(Pte*);

+ 12 - 8
sys/src/9/port/proc.c

@@ -213,7 +213,7 @@ ready(Proc *p)
 {
 {
 	int s, pri;
 	int s, pri;
 	Schedq *rq;
 	Schedq *rq;
-	void (*pt)(Proc*, int);
+	void (*pt)(Proc*, int, vlong);
 
 
 	s = splhi();
 	s = splhi();
 
 
@@ -258,7 +258,8 @@ ready(Proc *p)
 	p->readytime = m->ticks;
 	p->readytime = m->ticks;
 	p->state = Ready;
 	p->state = Ready;
 	pt = proctrace;
 	pt = proctrace;
-	if(pt) pt(p, SReady);
+	if(pt)
+		pt(p, SReady, 0);
 	unlock(runq);
 	unlock(runq);
 	splx(s);
 	splx(s);
 }
 }
@@ -363,7 +364,7 @@ runproc(void)
 	Proc *p;
 	Proc *p;
 	ulong start, now;
 	ulong start, now;
 	int i;
 	int i;
-	void (*pt)(Proc*, int);
+	void (*pt)(Proc*, int, vlong);
 
 
 	start = perfticks();
 	start = perfticks();
 
 
@@ -419,7 +420,8 @@ found:
 		edfunlock();
 		edfunlock();
 	}
 	}
 	pt = proctrace;
 	pt = proctrace;
-	if(pt) pt(p, SRun);
+	if(pt)
+		pt(p, SRun, 0);
 	return p;
 	return p;
 }
 }
 
 
@@ -589,7 +591,7 @@ void
 sleep(Rendez *r, int (*f)(void*), void *arg)
 sleep(Rendez *r, int (*f)(void*), void *arg)
 {
 {
 	int s;
 	int s;
-	void (*pt)(Proc*, int);
+	void (*pt)(Proc*, int, vlong);
 
 
 	s = splhi();
 	s = splhi();
 
 
@@ -625,7 +627,8 @@ sleep(Rendez *r, int (*f)(void*), void *arg)
 		 *  change state and call scheduler
 		 *  change state and call scheduler
 		 */
 		 */
 		pt = proctrace;
 		pt = proctrace;
-		if(pt) pt(up, SSleep);
+		if(pt)
+			pt(up, SSleep, 0);
 		up->state = Wakeme;
 		up->state = Wakeme;
 		up->r = r;
 		up->r = r;
 
 
@@ -912,13 +915,14 @@ pexit(char *exitstr, int freemem)
 	Rgrp *rgrp;
 	Rgrp *rgrp;
 	Pgrp *pgrp;
 	Pgrp *pgrp;
 	Chan *dot;
 	Chan *dot;
-	void (*pt)(Proc*, int);
+	void (*pt)(Proc*, int, vlong);
 
 
 	up->alarm = 0;
 	up->alarm = 0;
 	if (up->tt)
 	if (up->tt)
 		timerdel(up);
 		timerdel(up);
 	pt = proctrace;
 	pt = proctrace;
-	if(pt) pt(up, SDead);
+	if(pt)
+		pt(up, SDead, 0);
 
 
 	/* nil out all the resources under lock (free later) */
 	/* nil out all the resources under lock (free later) */
 	qlock(&up->debug);
 	qlock(&up->debug);

+ 7 - 2
sys/src/9/port/taslock.c

@@ -187,8 +187,13 @@ unlock(Lock *l)
 	l->key = 0;
 	l->key = 0;
 	coherence();
 	coherence();
 
 
-	if(up)
-		deccnt(&up->nlocks);
+	if(up && deccnt(&up->nlocks) == 0 && up->delaysched && islo()){
+		/*
+		 * Call sched if the need arose while locks were held
+		 * But, don't do it from interrupt routines, hence the islo() test
+		 */
+		sched();
+	}
 }
 }
 
 
 void
 void