Browse Source

Plan 9 from Bell Labs 2006-03-02

David du Colombier 18 years ago
parent
commit
d743cf4669

+ 23 - 22
dist/replica/_plan9.db

@@ -3,19 +3,19 @@
 386/9loaddebug - 775 sys sys 1140808449 312052
 386/9loadlite - 775 sys sys 1131317306 135668
 386/9loadlitedebug - 775 sys sys 1140726314 200137
-386/9pc - 775 sys sys 1136441425 1894552
-386/9pc.gz - 664 sys sys 1136441426 663936
-386/9pccpu - 775 sys sys 1136441429 1568136
-386/9pccpu.gz - 664 sys sys 1136441430 557125
-386/9pcdisk - 775 sys sys 1136441434 2085574
-386/9pcdisk.gz - 664 sys sys 1136441436 750976
-386/9pcf - 775 sys sys 1136441440 2428828
-386/9pcf.gz - 664 sys sys 1136441442 905190
+386/9pc - 775 sys sys 1141258200 1909853
+386/9pc.gz - 664 sys sys 1141258202 668936
+386/9pccpu - 775 sys sys 1141258205 1583315
+386/9pccpu.gz - 664 sys sys 1141258206 561499
+386/9pcdisk - 775 sys sys 1141258210 2100897
+386/9pcdisk.gz - 664 sys sys 1141258211 755785
+386/9pcf - 775 sys sys 1141258216 2446791
+386/9pcf.gz - 664 sys sys 1141258217 910970
 386/9pxeload - 775 sys sys 1131317321 216948
 386/_9pcdisk.gz - 664 sys sys 1039764191 695837
 386/bin - 20000000775 sys sys 1018897690 0
 386/bin/8a - 775 sys sys 1135570766 116009
-386/bin/8c - 775 sys sys 1138464441 361964
+386/bin/8c - 775 sys sys 1141271048 362551
 386/bin/8l - 775 sys sys 1140553397 115719
 386/bin/9660srv - 775 sys sys 1135570766 104023
 386/bin/aan - 775 sys sys 1138500151 131061
@@ -530,9 +530,9 @@
 386/lib - 20000000775 sys sys 1016826328 0
 386/lib/ape - 20000000775 sys sys 944969312 0
 386/lib/ape/lib9.a - 664 sys sys 1135531447 6906
-386/lib/ape/libap.a - 664 sys sys 1138500806 815698
+386/lib/ape/libap.a - 664 sys sys 1141271050 815700
 386/lib/ape/libbsd.a - 664 sys sys 1138500827 183176
-386/lib/ape/libdraw.a - 664 sys sys 1138500836 580882
+386/lib/ape/libdraw.a - 664 sys sys 1141271052 580882
 386/lib/ape/libfmt.a - 664 sys sys 1138500850 150976
 386/lib/ape/libl.a - 664 sys sys 1122001337 9420
 386/lib/ape/libnet.a - 664 sys sys 1138500858 16950
@@ -545,19 +545,19 @@
 386/lib/libauthsrv.a - 664 sys sys 1138500905 34210
 386/lib/libbin.a - 664 sys sys 1115950150 2534
 386/lib/libbio.a - 664 sys sys 1138500914 26064
-386/lib/libc.a - 664 sys sys 1138500920 502724
+386/lib/libc.a - 664 sys sys 1141271053 502726
 386/lib/libcomplete.a - 664 sys sys 1138500945 6372
 386/lib/libcontrol.a - 664 sys sys 1138500950 274924
 386/lib/libdisk.a - 664 sys sys 1138982896 42414
-386/lib/libdraw.a - 664 sys sys 1138500978 374124
+386/lib/libdraw.a - 664 sys sys 1141271054 374124
 386/lib/libflate.a - 664 sys sys 1138500991 76832
-386/lib/libframe.a - 664 sys sys 1138500996 66116
+386/lib/libframe.a - 664 sys sys 1141271054 66118
 386/lib/libgeometry.a - 664 sys sys 1115950153 50470
-386/lib/libhtml.a - 664 sys sys 1128740945 220134
+386/lib/libhtml.a - 664 sys sys 1141271055 220134
 386/lib/libhttpd.a - 664 sys sys 1138501008 99586
 386/lib/libip.a - 664 sys sys 1116126324 35602
 386/lib/libl.a - 664 sys sys 1115950154 5384
-386/lib/libmach.a - 664 sys sys 1138501015 782466
+386/lib/libmach.a - 664 sys sys 1141271057 782466
 386/lib/libmemdraw.a - 664 sys sys 1138501040 284158
 386/lib/libmemlayer.a - 664 sys sys 1115950157 47360
 386/lib/libmp.a - 664 sys sys 1138501044 79942
@@ -566,7 +566,7 @@
 386/lib/libregexp.a - 664 sys sys 1115950157 37464
 386/lib/libscribble.a - 664 sys sys 1138501058 107278
 386/lib/libsec.a - 664 sys sys 1140717392 646938
-386/lib/libstdio.a - 664 sys sys 1138501067 126186
+386/lib/libstdio.a - 664 sys sys 1141271057 126186
 386/lib/libsunrpc.a - 664 sys sys 1138501070 355994
 386/lib/libthread.a - 664 sys sys 1138501077 71986
 386/lib/libventi.a - 664 sys sys 1138501085 98038
@@ -9818,16 +9818,17 @@ sys/src/cmd/cb/mkfile - 664 sys sys 1062860425 172
 sys/src/cmd/cc - 20000000775 sys sys 1018556175 0
 sys/src/cmd/cc/acid.c - 664 sys sys 944960808 5314
 sys/src/cmd/cc/bits.c - 664 sys sys 944960873 850
+sys/src/cmd/cc/c99 - 664 sys sys 1141256556 1302
 sys/src/cmd/cc/cc.h - 664 sys sys 1134321729 12122
-sys/src/cmd/cc/cc.y - 664 sys sys 1134321719 16058
+sys/src/cmd/cc/cc.y - 664 sys sys 1141254919 16159
 sys/src/cmd/cc/com.c - 664 sys sys 1134321739 22202
 sys/src/cmd/cc/com64.c - 664 sys sys 1089299182 9975
 sys/src/cmd/cc/compat - 664 sys sys 1014925177 684
 sys/src/cmd/cc/compat.c - 664 sys sys 1132451523 454
-sys/src/cmd/cc/dcl.c - 664 sys sys 1134390084 26837
+sys/src/cmd/cc/dcl.c - 664 sys sys 1141256563 26858
 sys/src/cmd/cc/dpchk.c - 664 sys sys 1107365037 7152
 sys/src/cmd/cc/funct.c - 664 sys sys 984718510 6167
-sys/src/cmd/cc/lex.c - 664 sys sys 1134321742 23923
+sys/src/cmd/cc/lex.c - 664 sys sys 1141250058 23973
 sys/src/cmd/cc/lexbody - 664 sys sys 1131293457 9188
 sys/src/cmd/cc/mac.c - 664 sys sys 944960808 36
 sys/src/cmd/cc/macbody - 664 sys sys 1108281581 11703
@@ -14353,7 +14354,7 @@ sys/src/fs/pc/dosfs.c - 664 sys sys 1097712365 16637
 sys/src/fs/pc/dosfs.h - 664 sys sys 1140167937 2696
 sys/src/fs/pc/ether2114x.c - 664 sys sys 1015110044 31874
 sys/src/fs/pc/ether8139.c - 664 sys sys 1086569718 18552
-sys/src/fs/pc/ether82557.c - 664 sys sys 1037805116 24037
+sys/src/fs/pc/ether82557.c - 664 sys sys 1141035189 30669
 sys/src/fs/pc/ether83815.c - 664 sys sys 1140335463 26764
 sys/src/fs/pc/ether83815.mii.c - 664 sys sys 1049156663 31622
 sys/src/fs/pc/etherdp83820.c - 664 sys sys 1092268058 30976
@@ -14362,7 +14363,7 @@ sys/src/fs/pc/etherga620.c - 664 sys sys 1140166315 24732
 sys/src/fs/pc/etherga620fw.h - 664 sys sys 1032126775 222295
 sys/src/fs/pc/etherif.c - 664 sys sys 1140162742 6375
 sys/src/fs/pc/etherif.h - 664 sys sys 1015110057 730
-sys/src/fs/pc/etherigbe.c - 664 sys sys 1131948319 46571
+sys/src/fs/pc/etherigbe.c - 664 sys sys 1141208695 46676
 sys/src/fs/pc/ethermii.c - 664 sys sys 1140167954 4689
 sys/src/fs/pc/ethermii.h - 664 sys sys 1140167955 3259
 sys/src/fs/pc/floppy.c - 664 sys sys 1097579636 14022

+ 23 - 22
dist/replica/plan9.db

@@ -3,19 +3,19 @@
 386/9loaddebug - 775 sys sys 1140808449 312052
 386/9loadlite - 775 sys sys 1131317306 135668
 386/9loadlitedebug - 775 sys sys 1140726314 200137
-386/9pc - 775 sys sys 1136441425 1894552
-386/9pc.gz - 664 sys sys 1136441426 663936
-386/9pccpu - 775 sys sys 1136441429 1568136
-386/9pccpu.gz - 664 sys sys 1136441430 557125
-386/9pcdisk - 775 sys sys 1136441434 2085574
-386/9pcdisk.gz - 664 sys sys 1136441436 750976
-386/9pcf - 775 sys sys 1136441440 2428828
-386/9pcf.gz - 664 sys sys 1136441442 905190
+386/9pc - 775 sys sys 1141258200 1909853
+386/9pc.gz - 664 sys sys 1141258202 668936
+386/9pccpu - 775 sys sys 1141258205 1583315
+386/9pccpu.gz - 664 sys sys 1141258206 561499
+386/9pcdisk - 775 sys sys 1141258210 2100897
+386/9pcdisk.gz - 664 sys sys 1141258211 755785
+386/9pcf - 775 sys sys 1141258216 2446791
+386/9pcf.gz - 664 sys sys 1141258217 910970
 386/9pxeload - 775 sys sys 1131317321 216948
 386/_9pcdisk.gz - 664 sys sys 1039764191 695837
 386/bin - 20000000775 sys sys 1018897690 0
 386/bin/8a - 775 sys sys 1135570766 116009
-386/bin/8c - 775 sys sys 1138464441 361964
+386/bin/8c - 775 sys sys 1141271048 362551
 386/bin/8l - 775 sys sys 1140553397 115719
 386/bin/9660srv - 775 sys sys 1135570766 104023
 386/bin/aan - 775 sys sys 1138500151 131061
@@ -530,9 +530,9 @@
 386/lib - 20000000775 sys sys 1016826328 0
 386/lib/ape - 20000000775 sys sys 944969312 0
 386/lib/ape/lib9.a - 664 sys sys 1135531447 6906
-386/lib/ape/libap.a - 664 sys sys 1138500806 815698
+386/lib/ape/libap.a - 664 sys sys 1141271050 815700
 386/lib/ape/libbsd.a - 664 sys sys 1138500827 183176
-386/lib/ape/libdraw.a - 664 sys sys 1138500836 580882
+386/lib/ape/libdraw.a - 664 sys sys 1141271052 580882
 386/lib/ape/libfmt.a - 664 sys sys 1138500850 150976
 386/lib/ape/libl.a - 664 sys sys 1122001337 9420
 386/lib/ape/libnet.a - 664 sys sys 1138500858 16950
@@ -545,19 +545,19 @@
 386/lib/libauthsrv.a - 664 sys sys 1138500905 34210
 386/lib/libbin.a - 664 sys sys 1115950150 2534
 386/lib/libbio.a - 664 sys sys 1138500914 26064
-386/lib/libc.a - 664 sys sys 1138500920 502724
+386/lib/libc.a - 664 sys sys 1141271053 502726
 386/lib/libcomplete.a - 664 sys sys 1138500945 6372
 386/lib/libcontrol.a - 664 sys sys 1138500950 274924
 386/lib/libdisk.a - 664 sys sys 1138982896 42414
-386/lib/libdraw.a - 664 sys sys 1138500978 374124
+386/lib/libdraw.a - 664 sys sys 1141271054 374124
 386/lib/libflate.a - 664 sys sys 1138500991 76832
-386/lib/libframe.a - 664 sys sys 1138500996 66116
+386/lib/libframe.a - 664 sys sys 1141271054 66118
 386/lib/libgeometry.a - 664 sys sys 1115950153 50470
-386/lib/libhtml.a - 664 sys sys 1128740945 220134
+386/lib/libhtml.a - 664 sys sys 1141271055 220134
 386/lib/libhttpd.a - 664 sys sys 1138501008 99586
 386/lib/libip.a - 664 sys sys 1116126324 35602
 386/lib/libl.a - 664 sys sys 1115950154 5384
-386/lib/libmach.a - 664 sys sys 1138501015 782466
+386/lib/libmach.a - 664 sys sys 1141271057 782466
 386/lib/libmemdraw.a - 664 sys sys 1138501040 284158
 386/lib/libmemlayer.a - 664 sys sys 1115950157 47360
 386/lib/libmp.a - 664 sys sys 1138501044 79942
@@ -566,7 +566,7 @@
 386/lib/libregexp.a - 664 sys sys 1115950157 37464
 386/lib/libscribble.a - 664 sys sys 1138501058 107278
 386/lib/libsec.a - 664 sys sys 1140717392 646938
-386/lib/libstdio.a - 664 sys sys 1138501067 126186
+386/lib/libstdio.a - 664 sys sys 1141271057 126186
 386/lib/libsunrpc.a - 664 sys sys 1138501070 355994
 386/lib/libthread.a - 664 sys sys 1138501077 71986
 386/lib/libventi.a - 664 sys sys 1138501085 98038
@@ -9818,16 +9818,17 @@ sys/src/cmd/cb/mkfile - 664 sys sys 1062860425 172
 sys/src/cmd/cc - 20000000775 sys sys 1018556175 0
 sys/src/cmd/cc/acid.c - 664 sys sys 944960808 5314
 sys/src/cmd/cc/bits.c - 664 sys sys 944960873 850
+sys/src/cmd/cc/c99 - 664 sys sys 1141256556 1302
 sys/src/cmd/cc/cc.h - 664 sys sys 1134321729 12122
-sys/src/cmd/cc/cc.y - 664 sys sys 1134321719 16058
+sys/src/cmd/cc/cc.y - 664 sys sys 1141254919 16159
 sys/src/cmd/cc/com.c - 664 sys sys 1134321739 22202
 sys/src/cmd/cc/com64.c - 664 sys sys 1089299182 9975
 sys/src/cmd/cc/compat - 664 sys sys 1014925177 684
 sys/src/cmd/cc/compat.c - 664 sys sys 1132451523 454
-sys/src/cmd/cc/dcl.c - 664 sys sys 1134390084 26837
+sys/src/cmd/cc/dcl.c - 664 sys sys 1141256563 26858
 sys/src/cmd/cc/dpchk.c - 664 sys sys 1107365037 7152
 sys/src/cmd/cc/funct.c - 664 sys sys 984718510 6167
-sys/src/cmd/cc/lex.c - 664 sys sys 1134321742 23923
+sys/src/cmd/cc/lex.c - 664 sys sys 1141250058 23973
 sys/src/cmd/cc/lexbody - 664 sys sys 1131293457 9188
 sys/src/cmd/cc/mac.c - 664 sys sys 944960808 36
 sys/src/cmd/cc/macbody - 664 sys sys 1108281581 11703
@@ -14353,7 +14354,7 @@ sys/src/fs/pc/dosfs.c - 664 sys sys 1097712365 16637
 sys/src/fs/pc/dosfs.h - 664 sys sys 1140167937 2696
 sys/src/fs/pc/ether2114x.c - 664 sys sys 1015110044 31874
 sys/src/fs/pc/ether8139.c - 664 sys sys 1086569718 18552
-sys/src/fs/pc/ether82557.c - 664 sys sys 1037805116 24037
+sys/src/fs/pc/ether82557.c - 664 sys sys 1141035189 30669
 sys/src/fs/pc/ether83815.c - 664 sys sys 1140335463 26764
 sys/src/fs/pc/ether83815.mii.c - 664 sys sys 1049156663 31622
 sys/src/fs/pc/etherdp83820.c - 664 sys sys 1092268058 30976
@@ -14362,7 +14363,7 @@ sys/src/fs/pc/etherga620.c - 664 sys sys 1140166315 24732
 sys/src/fs/pc/etherga620fw.h - 664 sys sys 1032126775 222295
 sys/src/fs/pc/etherif.c - 664 sys sys 1140162742 6375
 sys/src/fs/pc/etherif.h - 664 sys sys 1015110057 730
-sys/src/fs/pc/etherigbe.c - 664 sys sys 1131948319 46571
+sys/src/fs/pc/etherigbe.c - 664 sys sys 1141208695 46676
 sys/src/fs/pc/ethermii.c - 664 sys sys 1140167954 4689
 sys/src/fs/pc/ethermii.h - 664 sys sys 1140167955 3259
 sys/src/fs/pc/floppy.c - 664 sys sys 1097579636 14022

+ 24 - 0
dist/replica/plan9.log

@@ -27891,3 +27891,27 @@
 1141146019 2 c sys/src/cmd/ql/obj.c - 664 sys sys 1141144914 25389
 1141146019 3 c sys/src/cmd/tapefs/32vfs.c - 664 sys sys 1141144939 3899
 1141147820 0 c sys/man/1/trace - 664 sys sys 1141147048 1497
+1141201833 0 c sys/src/fs/pc/ether82557.c - 664 sys sys 1141035189 30669
+1141209036 0 c sys/src/fs/pc/etherigbe.c - 664 sys sys 1141208695 46676
+1141250447 0 c sys/src/cmd/cc/cc.y - 664 sys sys 1141250058 16298
+1141250447 1 c sys/src/cmd/cc/lex.c - 664 sys sys 1141250058 23973
+1141255847 0 c sys/src/cmd/cc/cc.y - 664 sys sys 1141254919 16159
+1141257648 0 a sys/src/cmd/cc/c99 - 664 sys sys 1141256556 1302
+1141257648 1 c sys/src/cmd/cc/dcl.c - 664 sys sys 1141256563 26858
+1141259450 0 c 386/9pc - 775 sys sys 1141258200 1909853
+1141259450 1 c 386/9pc.gz - 664 sys sys 1141258202 668936
+1141259450 2 c 386/9pccpu - 775 sys sys 1141258205 1583315
+1141259450 3 c 386/9pccpu.gz - 664 sys sys 1141258206 561499
+1141259450 4 c 386/9pcdisk - 775 sys sys 1141258210 2100897
+1141259450 5 c 386/9pcdisk.gz - 664 sys sys 1141258211 755785
+1141259450 6 c 386/9pcf - 775 sys sys 1141258216 2446791
+1141259450 7 c 386/9pcf.gz - 664 sys sys 1141258217 910970
+1141272052 0 c 386/bin/8c - 775 sys sys 1141271048 362551
+1141272052 1 c 386/lib/ape/libap.a - 664 sys sys 1141271050 815700
+1141272052 2 c 386/lib/ape/libdraw.a - 664 sys sys 1141271052 580882
+1141272052 3 c 386/lib/libc.a - 664 sys sys 1141271053 502726
+1141272052 4 c 386/lib/libdraw.a - 664 sys sys 1141271054 374124
+1141272052 5 c 386/lib/libframe.a - 664 sys sys 1141271054 66118
+1141272052 6 c 386/lib/libhtml.a - 664 sys sys 1141271055 220134
+1141272052 7 c 386/lib/libmach.a - 664 sys sys 1141271057 782466
+1141272052 8 c 386/lib/libstdio.a - 664 sys sys 1141271057 126186

+ 46 - 0
sys/src/cmd/cc/c99

@@ -0,0 +1,46 @@
+C99 changes vs C89
+http://home.tiscalinet.ch/t_wolf/tw/c/c9x_changes.html
+
+(Numbers are from the web page list.)
+
+Not done (yet?):
+9, 19. Hexdecimal floating point constants.
+11. _Complex, _Imaginary, _Bool
+14. Variable arrays in parameter lists.
+33. Variable-length arrows
+34. goto restrictions for variable-length arrows
+18. Notation for universal characters \uXXXX
+25. Division and mod truncate toward zero.
+26. _Bool, float _Complex, double _Complex, long double _Complex
+
+Done:
+11, 30, 31, 32. restrict, inline
+12. Allow declarations anywhere.
+15. for loop declarations
+28. structs ending in incomplete type.
+
+Unneeded (already had):
+1. Translation limits
+6. Empty macro arguments allowed.
+8. #line limit
+10 // comments
+16. (Type){initializer list} compound literals
+17. Named initializers
+20. LL suffix for long long constants
+21. IEEE 754 floating-point arithmetic
+22. Long long type, 64 bits wide.
+24. Initializers for auto aggregates can be non-constants.
+26. long long int, unsigned long long int, signed long long int
+27. require at least one type specifier in a declaration
+29. Idempotent type qualifiers.
+
+Unwanted:
+2. #pragma stdc
+3. _Pragma
+4. __STDC_VERSION__
+5. __STDC_IEC_559__, __STDC_IEC_559_COMPLEX__,
+	__STDC_ISO_10646__
+7. __VA_ARGS__
+13. Digraph tokens
+23. __func__ identifier
+

+ 31 - 23
sys/src/cmd/cc/cc.y

@@ -35,7 +35,7 @@
 %type	<node>	xdecor xdecor2 labels label ulstmnt
 %type	<node>	adlist edecor tag qual qlist
 %type	<node>	abdecor abdecor1 abdecor2 abdecor3
-%type	<node>	zexpr lexpr init ilist
+%type	<node>	zexpr lexpr init ilist forexpr
 
 %left	';'
 %left	','
@@ -62,6 +62,7 @@
 %token	LIF LINT LLONG LREGISTER LRETURN LSHORT LSIZEOF LUSED
 %token	LSTATIC LSTRUCT LSWITCH LTYPEDEF LTYPESTR LUNION LUNSIGNED
 %token	LWHILE LVOID LENUM LSIGNED LCONSTNT LVOLATILE LSET LSIGNOF
+%token	LRESTRICT LINLINE
 %%
 prog:
 |	prog xdecl
@@ -146,26 +147,13 @@ xdecor2:
  * automatic declarator
  */
 adecl:
-	{
-		$$ = Z;
-	}
-|	adecl ctlist ';'
+	ctlist ';'
 	{
 		$$ = dodecl(adecl, lastclass, lasttype, Z);
-		if($1 != Z)
-			if($$ != Z)
-				$$ = new(OLIST, $1, $$);
-			else
-				$$ = $1;
 	}
-|	adecl ctlist adlist ';'
+|	ctlist adlist ';'
 	{
-		$$ = $1;
-		if($3 != Z) {
-			$$ = $3;
-			if($1 != Z)
-				$$ = new(OLIST, $1, $3);
-		}
+		$$ = $2;
 	}
 
 adlist:
@@ -371,11 +359,11 @@ arglist:
 	}
 
 block:
-	'{' adecl slist '}'
+	'{' slist '}'
 	{
-		$$ = invert($3);
-		if($2 != Z)
-			$$ = new(OLIST, $2, $$);
+		$$ = invert($2);
+	//	if($2 != Z)
+	//		$$ = new(OLIST, $2, $$);
 		if($$ == Z)
 			$$ = new(OLIST, Z, Z);
 	}
@@ -384,6 +372,10 @@ slist:
 	{
 		$$ = Z;
 	}
+|	slist adecl
+	{
+		$$ = new(OLIST, $1, $2);
+	}
 |	slist stmnt
 	{
 		$$ = new(OLIST, $1, $2);
@@ -421,6 +413,13 @@ stmnt:
 		$$ = new(OLIST, $1, $2);
 	}
 
+forexpr:
+	zcexpr
+|	ctlist adlist
+	{
+		$$ = Z;
+	}
+
 ulstmnt:
 	zcexpr ';'
 |	{
@@ -448,9 +447,16 @@ ulstmnt:
 		if($7 == Z)
 			warn($3, "empty else body");
 	}
-|	LFOR '(' zcexpr ';' zcexpr ';' zcexpr ')' stmnt
+|	{ markdcl(); } LFOR '(' forexpr ';' zcexpr ';' zcexpr ')' stmnt
 	{
-		$$ = new(OFOR, new(OLIST, $5, new(OLIST, $3, $7)), $9);
+		$$ = revertdcl();
+		if($$){
+			if($4)
+				$4 = new(OLIST, $$, $4);
+			else
+				$4 = $$;
+		}
+		$$ = new(OFOR, new(OLIST, $6, new(OLIST, $4, $8)), $10);
 	}
 |	LWHILE '(' cexpr ')' stmnt
 	{
@@ -1129,10 +1135,12 @@ cname:	/* class words */
 |	LTYPEDEF { $$ = BTYPEDEF; }
 |	LTYPESTR { $$ = BTYPESTR; }
 |	LREGISTER { $$ = BREGISTER; }
+|	LINLINE { $$ = 0; }
 
 gname:	/* garbage words */
 	LCONSTNT { $$ = BCONSTNT; }
 |	LVOLATILE { $$ = BVOLATILE; }
+|	LRESTRICT { $$ = 0; }
 
 name:
 	LNAME

+ 1 - 0
sys/src/cmd/cc/dcl.c

@@ -537,6 +537,7 @@ suallign(Type *t)
 				l->offset = o;
 			} else {
 				if(l->width <= 0)
+				if(l->down != T)
 					if(l->sym)
 						diag(Z, "incomplete structure element: %s",
 							l->sym->name);

+ 2 - 0
sys/src/cmd/cc/lex.c

@@ -1124,9 +1124,11 @@ struct
 	"for",		LFOR,		0,
 	"goto",		LGOTO,		0,
 	"if",		LIF,		0,
+	"inline",	LINLINE,	0,
 	"int",		LINT,		TINT,
 	"long",		LLONG,		TLONG,
 	"register",	LREGISTER,	0,
+	"restrict",	LRESTRICT,	0,
 	"return",	LRETURN,	0,
 	"SET",		LSET,		0,
 	"short",	LSHORT,		TSHORT,

+ 401 - 138
sys/src/fs/pc/ether82557.c

@@ -8,12 +8,27 @@
  *	optionally use memory-mapped registers;
  *	detach for PCI reset problems (also towards loadable drivers).
  */
+#ifdef FS
 #include "all.h"
 #include "io.h"
 #include "mem.h"
-
 #include "../ip/ip.h"
+
+#else
+
+#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"
+#endif			/* FS */
+
 #include "etherif.h"
+#include "ethermii.h"
+#include "compat.h"
 
 enum {
 	Nrfd		= 64,		/* receive frame area */
@@ -32,6 +47,7 @@ enum {					/* CSR */
 	Fcr		= 0x0C,		/* Flash control register */
 	Ecr		= 0x0E,		/* EEPROM control register */
 	Mcr		= 0x10,		/* MDI control register */
+	Gstatus		= 0x1D,		/* General status register */
 };
 
 enum {					/* Status */
@@ -86,8 +102,6 @@ enum {					/* Ecr */
 
 	EEstart		= 0x04,		/* start bit */
 	EEread		= 0x02,		/* read opcode */
-
-	EEaddrsz	= 6,		/* bits of address */
 };
 
 enum {					/* Mcr */
@@ -152,7 +166,7 @@ typedef struct Cb {
 		};
 	};
 
-	Msgbuf*	mb;
+	Block*	bp;
 	Cb*	next;
 } Cb;
 
@@ -181,28 +195,33 @@ enum {					/* CbTransmit count */
 	CbEOF		= 0x8000,
 };
 
+typedef struct Ctlr Ctlr;
 typedef struct Ctlr {
 	Lock	slock;			/* attach */
 	int	state;
 
 	int	port;
-	ushort	eeprom[0x40];
+	Pcidev*	pcidev;
+	Ctlr*	next;
+	int	active;
+
+	int	eepromsz;		/* address size in bits */
+	ushort*	eeprom;
 
 	Lock	miilock;
 
-	Rendez	timer;			/* watchdog timer for receive lockup errata */
 	int	tick;
-	char	wname[NAMELEN];
 
 	Lock	rlock;			/* registers */
 	int	command;		/* last command issued */
 
-	Msgbuf*	rfdhead;		/* receive side */
-	Msgbuf*	rfdtail;
+	Block*	rfdhead;		/* receive side */
+	Block*	rfdtail;
 	int	nrfd;
 
 	Lock	cblock;			/* transmit side */
 	int	action;
+	int	nop;
 	uchar	configdata[24];
 	int	threshold;
 	int	ncb;
@@ -213,10 +232,15 @@ typedef struct Ctlr {
 	int	cbqmax;
 	int	cbqmaxhw;
 
+	Rendez	timer;			/* for watchdog */
+
 	Lock	dlock;			/* dump statistical counters */
 	ulong	dump[17];
 } Ctlr;
 
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
 static uchar configdata[24] = {
 	0x16,				/* byte count */
 	0x08,				/* Rx/Tx FIFO limit */
@@ -254,6 +278,8 @@ static uchar configdata[24] = {
 static void
 command(Ctlr* ctlr, int c, int v)
 {
+	int timeo;
+
 	ilock(&ctlr->rlock);
 
 	/*
@@ -269,8 +295,17 @@ command(Ctlr* ctlr, int c, int v)
 	}
 	 */
 
-	while(csr8r(ctlr, CommandR))
-		;
+	for(timeo = 0; timeo < 100; timeo++){
+		if(!csr8r(ctlr, CommandR))
+			break;
+		microdelay(1);
+	}
+	if(timeo >= 100){
+		ctlr->command = -1;
+		iunlock(&ctlr->rlock);
+		iprint("i82557: command %#ux %#ux timeout\n", c, v);
+		return;
+	}
 
 	switch(c){
 
@@ -300,41 +335,43 @@ command(Ctlr* ctlr, int c, int v)
 	iunlock(&ctlr->rlock);
 }
 
-static Msgbuf*
+static Block*
 rfdalloc(ulong link)
 {
-	Msgbuf *mb;
+	Block *bp;
 	Rfd *rfd;
 
-	if(mb = mballoc(sizeof(Rfd), 0, Maeth2)){
-		rfd = (Rfd*)mb->data;
+	if(bp = iallocb(sizeof(Rfd))){
+		rfd = (Rfd*)bp->rp;
 		rfd->field = 0;
 		rfd->link = link;
 		rfd->rbd = NullPointer;
 		rfd->count = 0;
-		rfd->size = sizeof(Enpkt);
+		rfd->size = sizeof(Etherpkt);
 	}
 
-	return mb;
+	return bp;
 }
 
+#ifdef FS
 static int
 return0(void*)
 {
 	return 0;
 }
+#endif
 
 static void
-watchdog(void)
+watchdog(PROCARG(void* arg))
 {
 	Ether *ether;
 	Ctlr *ctlr;
 	static void txstart(Ether*);
+	static Rendez timer;		/* for FS */
 
-	ether = getarg();
+	ether = GETARG(arg);
 	for(;;){
-		ctlr = ether->ctlr;
-		tsleep(&ctlr->timer, return0, 0, 4000);
+		tsleep(&timer, return0, 0, 4000);
 
 		/*
 		 * Hmmm. This doesn't seem right. Currently
@@ -342,8 +379,16 @@ watchdog(void)
 		 * the future.
 		 */
 		ctlr = ether->ctlr;
-		if(ctlr == nil || ctlr->state == 0)
-			continue;
+		if(ctlr == nil || ctlr->state == 0){
+#ifdef FS
+			print("i82557: watchdog: exiting\n");
+			for (;;)
+				tsleep(&timer, return0, 0, 10000);
+#else
+			print("%s: exiting\n", up->text);
+			pexit("disabled", 0);
+#endif
+		}
 
 		ilock(&ctlr->cblock);
 		if(ctlr->tick++){
@@ -358,6 +403,7 @@ static void
 attach(Ether* ether)
 {
 	Ctlr *ctlr;
+	char name[KNAMELEN];
 
 	ctlr = ether->ctlr;
 	lock(&ctlr->slock);
@@ -365,7 +411,7 @@ attach(Ether* ether)
 		ilock(&ctlr->rlock);
 		csr8w(ctlr, Interrupt, 0);
 		iunlock(&ctlr->rlock);
-		command(ctlr, RUstart, PADDR(ctlr->rfdhead->data));
+		command(ctlr, RUstart, PADDR(ctlr->rfdhead->rp));
 		ctlr->state = 1;
 
 		/*
@@ -374,26 +420,112 @@ attach(Ether* ether)
 		 * omitted.
 		 */
 		if((ctlr->eeprom[0x03] & 0x0003) != 0x0003){
-			sprint(ctlr->wname, "ether%dwatchdog", ether->ctlrno);
-			userinit(watchdog, ether, ctlr->wname);
+			snprint(name, KNAMELEN, "#l%dwatchdog", ether->ctlrno);
+			kproc(name, watchdog, ether);
 		}
 	}
 	unlock(&ctlr->slock);
 }
 
+#ifndef FS
+static long
+ifstat(Ether* ether, void* a, long n, ulong offset)
+{
+	char *p;
+	int i, len, phyaddr;
+	Ctlr *ctlr;
+	ulong dump[17];
+
+	ctlr = ether->ctlr;
+	lock(&ctlr->dlock);
+
+	/*
+	 * Start the command then
+	 * wait for completion status,
+	 * should be 0xA005.
+	 */
+	ctlr->dump[16] = 0;
+	command(ctlr, DumpSC, 0);
+	while(ctlr->dump[16] == 0)
+		;
+
+	ether->oerrs = ctlr->dump[1]+ctlr->dump[2]+ctlr->dump[3];
+	ether->crcs = ctlr->dump[10];
+	ether->frames = ctlr->dump[11];
+	ether->buffs = ctlr->dump[12]+ctlr->dump[15];
+	ether->overflows = ctlr->dump[13];
+
+	if(n == 0){
+		unlock(&ctlr->dlock);
+		return 0;
+	}
+
+	memmove(dump, ctlr->dump, sizeof(dump));
+	unlock(&ctlr->dlock);
+
+	p = malloc(READSTR);
+	len = snprint(p, READSTR, "transmit good frames: %lud\n", dump[0]);
+	len += snprint(p+len, READSTR-len, "transmit maximum collisions errors: %lud\n", dump[1]);
+	len += snprint(p+len, READSTR-len, "transmit late collisions errors: %lud\n", dump[2]);
+	len += snprint(p+len, READSTR-len, "transmit underrun errors: %lud\n", dump[3]);
+	len += snprint(p+len, READSTR-len, "transmit lost carrier sense: %lud\n", dump[4]);
+	len += snprint(p+len, READSTR-len, "transmit deferred: %lud\n", dump[5]);
+	len += snprint(p+len, READSTR-len, "transmit single collisions: %lud\n", dump[6]);
+	len += snprint(p+len, READSTR-len, "transmit multiple collisions: %lud\n", dump[7]);
+	len += snprint(p+len, READSTR-len, "transmit total collisions: %lud\n", dump[8]);
+	len += snprint(p+len, READSTR-len, "receive good frames: %lud\n", dump[9]);
+	len += snprint(p+len, READSTR-len, "receive CRC errors: %lud\n", dump[10]);
+	len += snprint(p+len, READSTR-len, "receive alignment errors: %lud\n", dump[11]);
+	len += snprint(p+len, READSTR-len, "receive resource errors: %lud\n", dump[12]);
+	len += snprint(p+len, READSTR-len, "receive overrun errors: %lud\n", dump[13]);
+	len += snprint(p+len, READSTR-len, "receive collision detect errors: %lud\n", dump[14]);
+	len += snprint(p+len, READSTR-len, "receive short frame errors: %lud\n", dump[15]);
+	len += snprint(p+len, READSTR-len, "nop: %d\n", ctlr->nop);
+	if(ctlr->cbqmax > ctlr->cbqmaxhw)
+		ctlr->cbqmaxhw = ctlr->cbqmax;
+	len += snprint(p+len, READSTR-len, "cbqmax: %d\n", ctlr->cbqmax);
+	ctlr->cbqmax = 0;
+	len += snprint(p+len, READSTR-len, "threshold: %d\n", ctlr->threshold);
+
+	len += snprint(p+len, READSTR-len, "eeprom:");
+	for(i = 0; i < (1<<ctlr->eepromsz); i++){
+		if(i && ((i & 0x07) == 0))
+			len += snprint(p+len, READSTR-len, "\n       ");
+		len += snprint(p+len, READSTR-len, " %4.4ux", ctlr->eeprom[i]);
+	}
+
+	if((ctlr->eeprom[6] & 0x1F00) && !(ctlr->eeprom[6] & 0x8000)){
+		phyaddr = ctlr->eeprom[6] & 0x00FF;
+		len += snprint(p+len, READSTR-len, "\nphy %2d:", phyaddr);
+		for(i = 0; i < 6; i++){
+			static int miir(Ctlr*, int, int);
+
+			len += snprint(p+len, READSTR-len, " %4.4ux",
+				miir(ctlr, phyaddr, i));
+		}
+	}
+
+	snprint(p+len, READSTR-len, "\n");
+	n = readstr(offset, a, n, p);
+	free(p);
+
+	return n;
+}
+#endif
+
 static void
 txstart(Ether* ether)
 {
 	Ctlr *ctlr;
-	Msgbuf *mb;
+	Block *bp;
 	Cb *cb;
 
 	ctlr = ether->ctlr;
 	while(ctlr->cbq < (ctlr->ncb-1)){
 		cb = ctlr->cbhead->next;
 		if(ctlr->action == 0){
-			mb = etheroq(ether);
-			if(mb == nil)
+			bp = etheroq(ether);
+			if(bp == nil)
 				break;
 
 			cb->command = CbS|CbSF|CbTransmit;
@@ -401,9 +533,9 @@ txstart(Ether* ether)
 			cb->count = 0;
 			cb->threshold = ctlr->threshold;
 			cb->number = 1;
-			cb->tba = PADDR(mb->data);
-			cb->mb = mb;
-			cb->tbasz = mb->count;
+			cb->tba = PADDR(bp->rp);
+			cb->bp = bp;
+			cb->tbasz = BLEN(bp);
 		}
 		else if(ctlr->action == CbConfigure){
 			cb->command = CbS|CbConfigure;
@@ -412,7 +544,7 @@ txstart(Ether* ether)
 		}
 		else if(ctlr->action == CbIAS){
 			cb->command = CbS|CbIAS;
-			memmove(cb->data, ether->ea, Easize);
+			memmove(cb->data, ether->ea, Eaddrlen);
 			ctlr->action = 0;
 		}
 		else if(ctlr->action == CbMAS){
@@ -421,17 +553,26 @@ txstart(Ether* ether)
 			ctlr->action = 0;
 		}
 		else{
-			print("#l%d: action 0x%ux\n", ether->ctlrno, ctlr->action);
+			print("#l%d: action %#ux\n", ether->ctlrno, ctlr->action);
 			ctlr->action = 0;
 			break;
 		}
 		cb->status = 0;
 
-		//coherence();
+		coherence();
 		ctlr->cbhead->command &= ~CbS;
 		ctlr->cbhead = cb;
 		ctlr->cbq++;
 	}
+
+	/*
+	 * Workaround for some broken HUB chips
+	 * when connected at 10Mb/s half-duplex.
+	 */
+	if(ctlr->nop){
+		command(ctlr, CUnop, 0);
+		microdelay(1);
+	}
 	command(ctlr, CUresume, 0);
 
 	if(ctlr->cbq > ctlr->cbqmax)
@@ -466,6 +607,19 @@ configure(Ether* ether, int promiscuous)
 	iunlock(&ctlr->cblock);
 }
 
+static void
+promiscuous(void* arg, int on)
+{
+	configure(arg, on);
+}
+
+static void
+multicast(void* arg, uchar *addr, int on)
+{
+	USED(addr, on);
+	configure(arg, 1);
+}
+
 static void
 transmit(Ether* ether)
 {
@@ -483,11 +637,11 @@ receive(Ether* ether)
 	Rfd *rfd;
 	Ctlr *ctlr;
 	int count;
-	Msgbuf *mb, *pmb, *xmb;
+	Block *bp, *pbp, *xbp;
 
 	ctlr = ether->ctlr;
-	mb = ctlr->rfdhead;
-	for(rfd = (Rfd*)mb->data; rfd->field & RfdC; rfd = (Rfd*)mb->data){
+	bp = ctlr->rfdhead;
+	for(rfd = (Rfd*)bp->rp; rfd->field & RfdC; rfd = (Rfd*)bp->rp){
 		/*
 		 * If it's an OK receive frame
 		 * 1) save the count 
@@ -499,31 +653,31 @@ receive(Ether* ether)
 		 *	  actual data received;
 		 *	initialise the replacement buffer to point to
 		 *	  the next in the ring;
-		 *	initialise mb to point to the replacement;
+		 *	initialise bp to point to the replacement;
 		 * 4) if there's a good packet, pass it on for disposal.
 		 */
 		if(rfd->field & RfdOK){
-			pmb = nil;
+			pbp = nil;
 			count = rfd->count & 0x3FFF;
-			if((count < ETHERMAXTU/4) && (pmb = mballoc(count, 0, Maeth3))){
-				memmove(pmb->data, mb->data+sizeof(Rfd)-sizeof(rfd->data), count);
-				pmb->count = count;
-
+			if((count < ETHERMAXTU/4) && (pbp = iallocb(count))){
+				memmove(pbp->rp, bp->rp+offsetof(Rfd, data[0]),
+					count);
+				SETWPCNT(bp, count);
 				rfd->count = 0;
 				rfd->field = 0;
 			}
-			else if(xmb = rfdalloc(rfd->link)){
-				mb->data += sizeof(Rfd)-sizeof(rfd->data);
-				mb->count = count;
+			else if(xbp = rfdalloc(rfd->link)){
+				bp->rp += offsetof(Rfd, data[0]);
+				SETWPCNT(bp, count);
 
-				xmb->next = mb->next;
-				mb->next = 0;
+				xbp->next = bp->next;
+				bp->next = 0;
 
-				pmb = mb;
-				mb = xmb;
+				pbp = bp;
+				bp = xbp;
 			}
-			if(pmb != nil)
-				etheriq(ether, pmb);
+			if(pbp != nil)
+				ETHERIQ(ether, pbp, 1);
 		}
 		else{
 			rfd->count = 0;
@@ -540,12 +694,12 @@ receive(Ether* ether)
 		 * been allocated above, ensure that the new tail points
 		 * to it (next and link).
 		 */
-		rfd = (Rfd*)ctlr->rfdtail->data;
+		rfd = (Rfd*)ctlr->rfdtail->rp;
 		ctlr->rfdtail = ctlr->rfdtail->next;
-		ctlr->rfdtail->next = mb;
-		((Rfd*)ctlr->rfdtail->data)->link = PADDR(mb->data);
-		((Rfd*)ctlr->rfdtail->data)->field |= RfdS;
-		//coherence();
+		ctlr->rfdtail->next = bp;
+		((Rfd*)ctlr->rfdtail->rp)->link = PADDR(bp->rp);
+		((Rfd*)ctlr->rfdtail->rp)->field |= RfdS;
+		coherence();
 		rfd->field &= ~RfdS;
 
 		/*
@@ -553,8 +707,8 @@ receive(Ether* ether)
 		 * head, move on to the next and maintain the sentinel
 		 * between tail and head.
 		 */
-		ctlr->rfdhead = mb->next;
-		mb = ctlr->rfdhead;
+		ctlr->rfdhead = bp->next;
+		bp = ctlr->rfdhead;
 	}
 }
 
@@ -605,9 +759,9 @@ interrupt(Ureg*, void* arg)
 			while(ctlr->cbq){
 				if(!(cb->status & CbC))
 					break;
-				if(cb->mb){
-					mbfree(cb->mb);
-					cb->mb = nil;
+				if(cb->bp){
+					freeb(cb->bp);
+					cb->bp = nil;
 				}
 				if((cb->status & CbU) && ctlr->threshold < 0xE0)
 					ctlr->threshold++;
@@ -624,7 +778,7 @@ interrupt(Ureg*, void* arg)
 		}
 
 		if(status & (StatCX|StatFR|StatCNA|StatRNR|StatMDI|StatSWI))
-			panic("#l%d: status %ux\n", ether->ctlrno, status);
+			panic("#l%d: status %#ux\n", ether->ctlrno, status);
 	}
 }
 
@@ -632,7 +786,7 @@ static void
 ctlrinit(Ctlr* ctlr)
 {
 	int i;
-	Msgbuf *mb;
+	Block *bp;
 	Rfd *rfd;
 	ulong link;
 
@@ -646,16 +800,16 @@ ctlrinit(Ctlr* ctlr)
 	 */
 	link = NullPointer;
 	for(i = 0; i < Nrfd; i++){
-		mb = rfdalloc(link);
+		bp = rfdalloc(link);
 		if(ctlr->rfdhead == nil)
-			ctlr->rfdtail = mb;
-		mb->next = ctlr->rfdhead;
-		ctlr->rfdhead = mb;
-		link = PADDR(mb->data);
+			ctlr->rfdtail = bp;
+		bp->next = ctlr->rfdhead;
+		ctlr->rfdhead = bp;
+		link = PADDR(bp->rp);
 	}
 	ctlr->rfdtail->next = ctlr->rfdhead;
-	rfd = (Rfd*)ctlr->rfdtail->data;
-	rfd->link = PADDR(ctlr->rfdhead->data);
+	rfd = (Rfd*)ctlr->rfdtail->rp;
+	rfd->link = PADDR(ctlr->rfdhead->rp);
 	rfd->field |= RfdS;
 	ctlr->rfdhead = ctlr->rfdhead->next;
 
@@ -664,7 +818,7 @@ ctlrinit(Ctlr* ctlr)
 	 * transmit side.
 	 */
 	ilock(&ctlr->cblock);
-	ctlr->cbr = ialloc(ctlr->ncb*sizeof(Cb), 0);
+	ctlr->cbr = malloc(ctlr->ncb*sizeof(Cb));
 	for(i = 0; i < ctlr->ncb; i++){
 		ctlr->cbr[i].status = CbC|CbOK;
 		ctlr->cbr[i].command = CbS|CbNOP;
@@ -729,7 +883,7 @@ miiw(Ctlr* ctlr, int phyadd, int regadd, int data)
 static int
 hy93c46r(Ctlr* ctlr, int r)
 {
-	int i, op, data;
+	int data, i, op, size;
 
 	/*
 	 * Hyundai HY93C46 or equivalent serial EEPROM.
@@ -737,6 +891,7 @@ hy93c46r(Ctlr* ctlr, int r)
 	 * in the EEPROM is taken straight from Section
 	 * 3.3.4.2 of the Intel 82557 User's Guide.
 	 */
+reread:
 	csr16w(ctlr, Ecr, EEcs);
 	op = EEstart|EEread;
 	for(i = 2; i >= 0; i--){
@@ -748,8 +903,14 @@ hy93c46r(Ctlr* ctlr, int r)
 		microdelay(1);
 	}
 
-	for(i = EEaddrsz-1; i >= 0; i--){
-		data = (((r>>i) & 0x01)<<2)|EEcs;
+	/*
+	 * First time through must work out the EEPROM size.
+	 */
+	if((size = ctlr->eepromsz) == 0)
+		size = 8;
+
+	for(size = size-1; size >= 0; size--){
+		data = (((r>>size) & 0x01)<<2)|EEcs;
 		csr16w(ctlr, Ecr, data);
 		csr16w(ctlr, Ecr, data|EEsk);
 		delay(1);
@@ -771,54 +932,77 @@ hy93c46r(Ctlr* ctlr, int r)
 
 	csr16w(ctlr, Ecr, 0);
 
-	return data;
-}
-
-typedef struct Adapter {
-	int	port;
-	int	irq;
-	int	tbdf;
-} Adapter;
-static Msgbuf* adapter;
-
-static void
-i82557adapter(Msgbuf** mbb, int port, int irq, int tbdf)
-{
-	Msgbuf *mb;
-	Adapter *ap;
-
-	mb = mballoc(sizeof(Adapter), 0, Maeth1);
-	ap = (Adapter*)mb->data;
-	ap->port = port;
-	ap->irq = irq;
-	ap->tbdf = tbdf;
+	if(ctlr->eepromsz == 0){
+		ctlr->eepromsz = 8-size;
+		ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
+		goto reread;
+	}
 
-	mb->next = *mbb;
-	*mbb = mb;
+	return data;
 }
 
 static void
 i82557pci(void)
 {
 	Pcidev *p;
+	Ctlr *ctlr;
+	int nop, port;
 
 	p = nil;
+	nop = 0;
 	while(p = pcimatch(p, 0x8086, 0)){
 		switch(p->did){
 		default:
 			continue;
-		case 0x1209:		/* Intel 82559ER */
-		case 0x1229:		/* Intel 8255[789] */
 		case 0x1031:		/* Intel 82562EM */
+		case 0x1050:		/* Intel 82562EZ */
+		case 0x1039:		/* Intel 82801BD PRO/100 VE */
+		case 0x103A:		/* Intel 82562 PRO/100 VE */
+		case 0x1064:		/* Intel 82562 PRO/100 VE */
 		case 0x2449:		/* Intel 82562ET */
+			nop = 1;
+			/*FALLTHROUGH*/
+		case 0x1209:		/* Intel 82559ER */
+		case 0x1229:		/* Intel 8255[789] */
+		case 0x1030:		/* Intel 82559 InBusiness 10/100  */
 			break;
 		}
+#ifndef FS
+		if(pcigetpms(p) > 0){
+			int i;
+
+			pcisetpms(p, 0);
+	
+			for(i = 0; i < 6; i++)
+				pcicfgw32(p, PciBAR0+i*4, p->mem[i].bar);
+			pcicfgw8(p, PciINTL, p->intl);
+			pcicfgw8(p, PciLTR, p->ltr);
+			pcicfgw8(p, PciCLS, p->cls);
+			pcicfgw16(p, PciPCR, p->pcr);
+		}
+#endif
 		/*
 		 * bar[0] is the memory-mapped register address (4KB),
 		 * bar[1] is the I/O port register address (32 bytes) and
 		 * bar[2] is for the flash ROM (1MB).
 		 */
-		i82557adapter(&adapter, p->mem[1].bar & ~0x01, p->intl, p->tbdf);
+		port = p->mem[1].bar & ~0x01;
+		if(ioalloc(port, p->mem[1].size, 0, "i82557") < 0){
+			print("i82557: port %#ux in use\n", port);
+			continue;
+		}
+
+		ctlr = malloc(sizeof(Ctlr));
+		ctlr->port = port;
+		ctlr->pcidev = p;
+		ctlr->nop = nop;
+
+		if(ctlrhead != nil)
+			ctlrtail->next = ctlr;
+		else
+			ctlrhead = ctlr;
+		ctlrtail = ctlr;
+
 		pcisetbme(p);
 	}
 }
@@ -835,54 +1019,83 @@ static char* mediatable[9] = {
 	"100BASE-FXFD",
 };
 
+static int
+scanphy(Ctlr* ctlr)
+{
+	int i, oui, x;
+
+	for(i = 0; i < 32; i++){
+		if((oui = miir(ctlr, i, 2)) == -1 || oui == 0 || oui == 0xFFFF)
+			continue;
+		oui <<= 6;
+		x = miir(ctlr, i, 3);
+		oui |= x>>10;
+		//print("phy%d: oui %#ux reg1 %#ux\n", i, oui, miir(ctlr, i, 1));
+
+		ctlr->eeprom[6] = i;
+		if(oui == 0xAA00)
+			ctlr->eeprom[6] |= 0x07<<8;
+		else if(oui == 0x80017){
+			if(x & 0x01)
+				ctlr->eeprom[6] |= 0x0A<<8;
+			else
+				ctlr->eeprom[6] |= 0x04<<8;
+		}
+		return i;
+	}
+	return -1;
+}
+
+static void
+shutdown(Ether* ether)
+{
+	Ctlr *ctlr = ether->ctlr;
+
+print("ether82557 shutting down\n");
+	csr32w(ctlr, Port, 0);
+	delay(1);
+	csr8w(ctlr, Interrupt, InterruptM);
+}
+
+
 int
 etheri82557reset(Ether* ether)
 {
-	int anar, anlpar, bmcr, bmsr, i, k, medium, phyaddr, port, x;
+	int anar, anlpar, bmcr, bmsr, i, k, medium, phyaddr, x;
 	unsigned short sum;
-	Msgbuf *mb, **mbb;
-	Adapter *ap;
-	uchar ea[Easize];
+	uchar ea[Eaddrlen];
 	Ctlr *ctlr;
-	static int scandone;
 
-	if(scandone == 0){
+	if(ctlrhead == nil)
 		i82557pci();
-		scandone = 1;
-	}
 
 	/*
-	 * Any adapter matches if no port is supplied,
+	 * Any adapter matches if no ether->port is supplied,
 	 * otherwise the ports must match.
 	 */
-	port = 0;
-	mbb = &adapter;
-	for(mb = *mbb; mb; mb = mb->next){
-		ap = (Adapter*)mb->data;
-		if(ether->port == 0 || ether->port == ap->port){
-			port = ap->port;
-			ether->irq = ap->irq;
-			ether->tbdf = ap->tbdf;
-			*mbb = mb->next;
-			mbfree(mb);
+	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+		if(ctlr->active)
+			continue;
+		if(ether->port == 0 || ether->port == ctlr->port){
+			ctlr->active = 1;
 			break;
 		}
-		mbb = &mb->next;
 	}
-	if(port == 0)
+	if(ctlr == nil)
 		return -1;
 
 	/*
-	 * Allocate a controller structure and start to initialise it.
+	 * Initialise the Ctlr structure.
 	 * Perform a software reset after which should ensure busmastering
 	 * is still enabled. The EtherExpress PRO/100B appears to leave
 	 * the PCI configuration alone (see the 'To do' list above) so punt
 	 * for now.
 	 * Load the RUB and CUB registers for linear addressing (0).
 	 */
-	ether->ctlr = ialloc(sizeof(Ctlr), 0);
-	ctlr = ether->ctlr;
-	ctlr->port = port;
+	ether->ctlr = ctlr;
+	ether->port = ctlr->port;
+	ether->irq = ctlr->pcidev->intl;
+	ether->tbdf = ctlr->pcidev->tbdf;
 
 	ilock(&ctlr->rlock);
 	csr32w(ctlr, Port, 0);
@@ -902,25 +1115,49 @@ etheri82557reset(Ether* ether)
 
 	/*
 	 * Read the EEPROM.
+	 * Do a dummy read first to get the size
+	 * and allocate ctlr->eeprom.
 	 */
+	hy93c46r(ctlr, 0);
 	sum = 0;
-	for(i = 0; i < 0x40; i++){
+	for(i = 0; i < (1<<ctlr->eepromsz); i++){
 		x = hy93c46r(ctlr, i);
 		ctlr->eeprom[i] = x;
 		sum += x;
 	}
 	if(sum != 0xBABA)
-		print("#l%d: EEPROM checksum - 0x%4.4ux\n", ether->ctlrno, sum);
+		print("#l%d: EEPROM checksum - %#4.4ux\n", ether->ctlrno, sum);
 
 	/*
 	 * Eeprom[6] indicates whether there is a PHY and whether
 	 * it's not 10Mb-only, in which case use the given PHY address
 	 * to set any PHY specific options and determine the speed.
+	 * Unfortunately, sometimes the EEPROM is blank except for
+	 * the ether address and checksum; in this case look at the
+	 * controller type and if it's am 82558 or 82559 it has an
+	 * embedded PHY so scan for that.
 	 * If no PHY, assume 82503 (serial) operation.
 	 */
-	if((ctlr->eeprom[6] & 0x1F00) && !(ctlr->eeprom[6] & 0x8000)){
+	if((ctlr->eeprom[6] & 0x1F00) && !(ctlr->eeprom[6] & 0x8000))
 		phyaddr = ctlr->eeprom[6] & 0x00FF;
-
+	else
+	switch(ctlr->pcidev->rid){
+	case 0x01:			/* 82557 A-step */
+	case 0x02:			/* 82557 B-step */
+	case 0x03:			/* 82557 C-step */
+	default:
+		phyaddr = -1;
+		break;
+	case 0x04:			/* 82558 A-step */
+	case 0x05:			/* 82558 B-step */
+	case 0x06:			/* 82559 A-step */
+	case 0x07:			/* 82559 B-step */
+	case 0x08:			/* 82559 C-step */
+	case 0x09:			/* 82559ER A-step */
+		phyaddr = scanphy(ctlr);
+		break;
+	}
+	if(phyaddr >= 0){
 		/*
 		 * Resolve the highest common ability of the two
 		 * link partners. In descending order:
@@ -1052,8 +1289,6 @@ etheri82557reset(Ether* ether)
 
 		if(bmcr & 0x2000)
 			ether->mbps = 100;
-		else
-			ether->mbps = 10;
 
 		ctlr->configdata[8] = 1;
 		ctlr->configdata[15] &= ~0x80;
@@ -1063,9 +1298,23 @@ etheri82557reset(Ether* ether)
 		ctlr->configdata[15] |= 0x80;
 	}
 
+	/*
+	 * Workaround for some broken HUB chips when connected at 10Mb/s
+	 * half-duplex.
+	 * This is a band-aid, but as there's no dynamic auto-negotiation
+	 * code at the moment, only deactivate the workaround code in txstart
+	 * if the link is 100Mb/s.
+	 */
+	if(ether->mbps != 10)
+		ctlr->nop = 0;
+
 	/*
 	 * Load the chip configuration and start it off.
 	 */
+#ifndef FS
+	if(ether->oq == 0)
+		ether->oq = qopen(256*1024, Qmsg, 0, 0);
+#endif
 	configure(ether, 0);
 	command(ctlr, CUstart, PADDR(&ctlr->cbr->status));
 
@@ -1074,9 +1323,9 @@ etheri82557reset(Ether* ether)
 	 * If not, read it from the EEPROM and set in ether->ea prior to loading
 	 * the station address with the Individual Address Setup command.
 	 */
-	memset(ea, 0, Easize);
-	if(memcmp(ea, ether->ea, Easize) == 0){
-		for(i = 0; i < Easize/2; i++){
+	memset(ea, 0, Eaddrlen);
+	if(memcmp(ea, ether->ea, Eaddrlen) == 0){
+		for(i = 0; i < Eaddrlen/2; i++){
 			x = ctlr->eeprom[i];
 			ether->ea[2*i] = x;
 			ether->ea[2*i+1] = x>>8;
@@ -1091,10 +1340,24 @@ etheri82557reset(Ether* ether)
 	/*
 	 * Linkage to the generic ethernet driver.
 	 */
-	ether->port = port;
 	ether->attach = attach;
 	ether->transmit = transmit;
 	ether->interrupt = interrupt;
-
+#ifndef FS
+	ether->ifstat = ifstat;
+
+	ether->arg = ether;
+	ether->promiscuous = promiscuous;
+	ether->shutdown = shutdown;
+	ether->multicast = multicast;
+#endif
 	return 0;
 }
+
+#ifndef FS
+void
+ether82557bothlink(void)
+{
+	addethercard("i82557",  etheri82557reset);
+}
+#endif

+ 23 - 19
sys/src/fs/pc/etherigbe.c

@@ -49,7 +49,7 @@ enum {
 	i82545gmc	= (0x1026<<16)|0x8086,
 	i82547gi   	= (0x1075<<16)|0x8086,
 	i82541gi   	= (0x1076<<16)|0x8086,
-	i82541gi2		= (0x1077<<16)|0x8086,
+	i82541gi2	= (0x1077<<16)|0x8086,
 	i82546gb   	= (0x1079<<16)|0x8086,
 	i82541pi	= (0x107c<<16)|0x8086,
 	i82546eb	= (0x1010<<16)|0x8086,
@@ -194,7 +194,9 @@ enum {					/* Eecd */
 	Do		= 0x00000008,	/* Data Output from the EEPROM */
 	Areq		= 0x00000040,	/* EEPROM Access Request */
 	Agnt		= 0x00000080,	/* EEPROM Access Grant */
+	Eepresent	= 0x00000100,	/* EEPROM Present */
 	Eesz256		= 0x00000200,	/* EEPROM is 256 words not 64 */
+	Eeszaddr	= 0x00000400,	/* EEPROM size for 8254[17] */
 	Spi		= 0x00002000,	/* EEPROM is SPI not Microwire */
 };
 
@@ -470,7 +472,7 @@ enum {
 
 typedef struct Ctlr Ctlr;
 typedef struct Ctlr {
-	ulong	port;
+	int	port;
 	Pcidev*	pcidev;
 	Ctlr*	next;
 	int	active;
@@ -863,8 +865,8 @@ igbelproc(PROCARG(void *arg))
 		case i82540em:
 		case i82540eplp:
 		case i82547gi:
-		case i82541gi2:
 		case i82541gi:
+		case i82541gi2:
 		case i82541pi:
 			break;
 		}
@@ -915,12 +917,12 @@ igbetxinit(Ctlr* ctlr)
 	case i82540em:
 	case i82540eplp:
 	case i82541gi:
+	case i82541gi2:
 	case i82541pi:
 	case i82545gmc:
 	case i82546gb:
 	case i82546eb:
 	case i82547gi:
-	case i82541gi2:
 		r = 8;
 		break;
 	}
@@ -954,11 +956,11 @@ igbetxinit(Ctlr* ctlr)
 	case i82540em:
 	case i82540eplp:
 	case i82547gi:
-	case i82541gi2:
 	case i82545gmc:
 	case i82546gb:
 	case i82546eb:
 	case i82541gi:
+	case i82541gi2:
 	case i82541pi:
 		r = csr32r(ctlr, Txdctl);
 		r &= ~WthreshMASK;
@@ -1088,12 +1090,12 @@ igberxinit(Ctlr* ctlr)
 	case i82540em:
 	case i82540eplp:
 	case i82541gi:
+	case i82541gi2:
 	case i82541pi:
 	case i82545gmc:
 	case i82546gb:
 	case i82546eb:
 	case i82547gi:
-	case i82541gi2:
 		csr32w(ctlr, Radv, 64);
 		break;
 	}
@@ -1220,7 +1222,7 @@ igbeattach(Ether* edev)
 		qunlock(&ctlr->alock);
 		return;
 	}
-	ctlr->rdba = (Rd*)ROUNDUP((ulong)ctlr->alloc, 128);
+	ctlr->rdba = (Rd*)ROUNDUP((uintptr)ctlr->alloc, 128);
 	ctlr->tdba = (Td*)(ctlr->rdba+ctlr->nrd);
 
 	ctlr->rb = malloc(ctlr->nrd*sizeof(Block*));
@@ -1497,8 +1499,8 @@ igbemii(Ctlr* ctlr)
 	case i82540em:
 	case i82540eplp:
 	case i82547gi:
-	case i82541gi2:
 	case i82541gi:
+	case i82541gi2:
 	case i82541pi:
 	case i82545gmc:
 	case i82546gb:
@@ -1520,7 +1522,7 @@ igbemii(Ctlr* ctlr)
 		return -1;
 	}
 	USED(phy);
-//	print("oui %X phyno %d\n", phy->oui, phy->phyno);
+	// print("oui %X phyno %d\n", phy->oui, phy->phyno);
 
 	/*
 	 * 8254X-specific PHY registers not in 802.3:
@@ -1531,8 +1533,8 @@ igbemii(Ctlr* ctlr)
 	 */
 	switch(ctlr->id){
 	case i82547gi:
-	case i82541gi2:
 	case i82541gi:
+	case i82541gi2:
 	case i82541pi:
 	case i82545gmc:
 	case i82546gb:
@@ -1552,7 +1554,6 @@ igbemii(Ctlr* ctlr)
 		miimiw(ctlr->mii, 20, r);
 
 		miireset(ctlr->mii);
-
 		p = 0;
 		if(ctlr->txcw & TxcwPs)
 			p |= AnaP;
@@ -1632,7 +1633,7 @@ at93c46io(Ctlr* ctlr, char* op, int data)
 			break;
 		}
 		csr32w(ctlr, Eecd, eecd);
-		microdelay(1);
+		microdelay(50);
 	}
 	if(loop >= 0)
 		return -1;
@@ -1651,11 +1652,10 @@ at93c46r(Ctlr* ctlr)
 		print("igbe: SPI EEPROM access not implemented\n");
 		return 0;
 	}
-	if(eecd & Eesz256)
+	if(eecd & (Eeszaddr|Eesz256))
 		bits = 8;
 	else
 		bits = 6;
-	snprint(rop, sizeof(rop), "S :%dDCc;", bits+3);
 
 	sum = 0;
 
@@ -1663,11 +1663,11 @@ at93c46r(Ctlr* ctlr)
 	default:
 		areq = 0;
 		break;
+	case i82541gi:
+	case i82547gi:
 	case i82540em:
 	case i82540eplp:
-	case i82541gi:
 	case i82541pi:
-	case i82547gi:
 	case i82541gi2:
 	case i82545gmc:
 	case i82546gb:
@@ -1685,6 +1685,7 @@ at93c46r(Ctlr* ctlr)
 		}
 		break;
 	}
+	snprint(rop, sizeof(rop), "S :%dDCc;", bits+3);
 
 	for(addr = 0; addr < 0x40; addr++){
 		/*
@@ -1779,13 +1780,13 @@ igbedetach(Ctlr* ctlr)
 	}
 	if(csr32r(ctlr, Icr))
 		return -1;
+
 	return 0;
 }
 
 static void
 igbeshutdown(Ether* ether)
 {
-iprint("etherigbe shutting down\n");
 	igbedetach(ether->ctlr);
 }
 
@@ -1796,6 +1797,7 @@ etherigbereset(Ctlr* ctlr)
 
 	if(igbedetach(ctlr))
 		return -1;
+
 	/*
 	 * Read the EEPROM, validate the checksum
 	 * then get the device back to a power-on state.
@@ -1813,6 +1815,8 @@ etherigbereset(Ctlr* ctlr)
 	if ((ctlr->id == i82546gb || ctlr->id == i82546eb) && BUSFNO(ctlr->pcidev->tbdf) == 1)
 		ctlr->eeprom[Ea+2] += 0x100;	// second interface
 	for(i = Ea; i < Eaddrlen/2; i++){
+if(i == Ea && ctlr->id == i82541gi && ctlr->eeprom[i] == 0xFFFF)
+    ctlr->eeprom[i] = 0xD000;
 		ctlr->ra[2*i] = ctlr->eeprom[i];
 		ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8;
 	}
@@ -1846,9 +1850,7 @@ etherigbereset(Ctlr* ctlr)
 		if(ctlr->eeprom[Icw1] & 0x0400){
 			ctrl |= Fd;
 			txcw |= TxcwFd;
-//print("igbe: full duplex\n");
 		}
-//else print("igbe: half duplex\n");
 		if(ctlr->eeprom[Icw1] & 0x0200)
 			ctrl |= Lrst;
 		if(ctlr->eeprom[Icw1] & 0x0010)
@@ -1891,6 +1893,7 @@ etherigbereset(Ctlr* ctlr)
 		csr32w(ctlr, Txcw, txcw);
 	}
 
+
 	/*
 	 * Flow control - values from the datasheet.
 	 */
@@ -1904,6 +1907,7 @@ etherigbereset(Ctlr* ctlr)
 
 	if(!(csr32r(ctlr, Status) & Tbimode) && igbemii(ctlr) < 0)
 		return -1;
+
 	return 0;
 }