Browse Source

Plan 9 from Bell Labs 2004-09-09

David du Colombier 19 years ago
parent
commit
e31c892300

+ 28 - 27
dist/replica/_plan9.db

@@ -1,8 +1,8 @@
 386 - 20000000775 sys sys 1010957353 0
 386 - 20000000775 sys sys 1010957353 0
-386/9load - 775 sys sys 1088798345 188040
-386/9loaddebug - 775 sys sys 1091156989 270242
-386/9loadlite - 775 sys sys 1088798346 125004
-386/9loadlitedebug - 775 sys sys 1089402462 183654
+386/9load - 775 sys sys 1094674490 206624
+386/9loaddebug - 775 sys sys 1094674492 297770
+386/9loadlite - 775 sys sys 1094674491 130360
+386/9loadlitedebug - 775 sys sys 1094674492 192921
 386/9pc - 775 sys sys 1092110936 1817018
 386/9pc - 775 sys sys 1092110936 1817018
 386/9pc.gz - 664 sys sys 1077049336 635727
 386/9pc.gz - 664 sys sys 1077049336 635727
 386/9pccpu - 775 sys sys 1092110939 1473170
 386/9pccpu - 775 sys sys 1092110939 1473170
@@ -11,7 +11,7 @@
 386/9pcdisk.gz - 664 sys sys 1040006345 703136
 386/9pcdisk.gz - 664 sys sys 1040006345 703136
 386/9pcf - 775 sys sys 1092110948 2351243
 386/9pcf - 775 sys sys 1092110948 2351243
 386/9pcf.gz - 664 sys sys 1077049490 872650
 386/9pcf.gz - 664 sys sys 1077049490 872650
-386/9pxeload - 775 sys sys 1088798346 188040
+386/9pxeload - 775 sys sys 1094674490 206624
 386/_9pcdisk.gz - 664 sys sys 1039764191 695837
 386/_9pcdisk.gz - 664 sys sys 1039764191 695837
 386/bin - 20000000775 sys sys 1018897690 0
 386/bin - 20000000775 sys sys 1018897690 0
 386/bin/8a - 775 sys sys 1089397305 112804
 386/bin/8a - 775 sys sys 1089397305 112804
@@ -396,7 +396,7 @@
 386/bin/swap - 775 sys sys 1085077102 60111
 386/bin/swap - 775 sys sys 1085077102 60111
 386/bin/syscall - 775 sys sys 1091849700 71497
 386/bin/syscall - 775 sys sys 1091849700 71497
 386/bin/tail - 775 sys sys 1085077102 63945
 386/bin/tail - 775 sys sys 1085077102 63945
-386/bin/tar - 775 sys sys 1085077102 81780
+386/bin/tar - 775 sys sys 1094612761 81786
 386/bin/tbl - 775 sys sys 1085077103 111047
 386/bin/tbl - 775 sys sys 1085077103 111047
 386/bin/tcs - 775 sys sys 1085077103 256506
 386/bin/tcs - 775 sys sys 1085077103 256506
 386/bin/tee - 775 sys sys 1085077104 38401
 386/bin/tee - 775 sys sys 1085077104 38401
@@ -503,7 +503,7 @@
 386/include/u.h - 664 sys sys 1042604326 1450
 386/include/u.h - 664 sys sys 1042604326 1450
 386/include/ureg.h - 664 sys sys 944946012 523
 386/include/ureg.h - 664 sys sys 944946012 523
 386/init - 775 sys sys 1085077133 98033
 386/init - 775 sys sys 1085077133 98033
-386/ld.com - 775 sys sys 1088798347 64480
+386/ld.com - 775 sys sys 1094674493 69772
 386/lib - 20000000775 sys sys 1016826328 0
 386/lib - 20000000775 sys sys 1016826328 0
 386/lib/ape - 20000000775 sys sys 944969312 0
 386/lib/ape - 20000000775 sys sys 944969312 0
 386/lib/ape/lib9.a - 664 sys sys 1038237538 6378
 386/lib/ape/lib9.a - 664 sys sys 1038237538 6378
@@ -5042,7 +5042,7 @@ sys/man/7/map - 664 sys sys 1032632790 13549
 sys/man/7/scat - 664 sys sys 970069855 8904
 sys/man/7/scat - 664 sys sys 970069855 8904
 sys/man/8 - 20000000775 sys sys 1018384448 0
 sys/man/8 - 20000000775 sys sys 1018384448 0
 sys/man/8/0intro - 664 sys sys 944959679 247
 sys/man/8/0intro - 664 sys sys 944959679 247
-sys/man/8/9load - 664 sys sys 1056073409 8555
+sys/man/8/9load - 664 sys sys 1094676489 9170
 sys/man/8/9pcon - 664 sys sys 1018973955 2226
 sys/man/8/9pcon - 664 sys sys 1018973955 2226
 sys/man/8/INDEX - 664 sys sys 1089339723 2669
 sys/man/8/INDEX - 664 sys sys 1089339723 2669
 sys/man/8/INDEX.html - 664 sys sys 1089321186 7944
 sys/man/8/INDEX.html - 664 sys sys 1089321186 7944
@@ -5079,7 +5079,7 @@ sys/man/8/nfsserver - 664 sys sys 1017251291 3397
 sys/man/8/pcmcia - 664 sys sys 944959679 408
 sys/man/8/pcmcia - 664 sys sys 944959679 408
 sys/man/8/pem - 664 sys sys 1060263669 1189
 sys/man/8/pem - 664 sys sys 1060263669 1189
 sys/man/8/ping - 664 sys sys 1084473185 3436
 sys/man/8/ping - 664 sys sys 1084473185 3436
-sys/man/8/plan9.ini - 664 sys sys 1092082105 20930
+sys/man/8/plan9.ini - 664 sys sys 1094650551 20806
 sys/man/8/pop3 - 664 sys sys 1063854676 2720
 sys/man/8/pop3 - 664 sys sys 1063854676 2720
 sys/man/8/ppp - 664 sys sys 1050361032 4424
 sys/man/8/ppp - 664 sys sys 1050361032 4424
 sys/man/8/prep - 664 sys sys 1079705872 13820
 sys/man/8/prep - 664 sys sys 1079705872 13820
@@ -6449,24 +6449,23 @@ sys/src/boot/pc/apm.c - 664 sys sys 1015007947 289
 sys/src/boot/pc/bcom.c - 664 sys sys 1032215919 6421
 sys/src/boot/pc/bcom.c - 664 sys sys 1032215919 6421
 sys/src/boot/pc/boot.c - 664 sys sys 1021579983 3353
 sys/src/boot/pc/boot.c - 664 sys sys 1021579983 3353
 sys/src/boot/pc/bootld.c - 664 sys sys 1015007948 1801
 sys/src/boot/pc/bootld.c - 664 sys sys 1015007948 1801
-sys/src/boot/pc/bootp.c - 664 sys sys 1015007948 9417
+sys/src/boot/pc/bootp.c - 664 sys sys 1094674486 12069
 sys/src/boot/pc/cga.c - 664 sys sys 1015007948 1362
 sys/src/boot/pc/cga.c - 664 sys sys 1015007948 1362
 sys/src/boot/pc/clock.c - 664 sys sys 1088089722 5783
 sys/src/boot/pc/clock.c - 664 sys sys 1088089722 5783
-sys/src/boot/pc/conf.c - 664 sys sys 1063855536 10128
-sys/src/boot/pc/console.c - 664 sys sys 1068158999 3487
-sys/src/boot/pc/dat.h - 664 sys sys 1056073257 3432
+sys/src/boot/pc/conf.c - 664 sys sys 1094674484 10217
+sys/src/boot/pc/console.c - 664 sys sys 1094674483 3388
+sys/src/boot/pc/dat.h - 664 sys sys 1094674488 3518
 sys/src/boot/pc/devfloppy.c - 664 sys sys 1032215913 15505
 sys/src/boot/pc/devfloppy.c - 664 sys sys 1032215913 15505
 sys/src/boot/pc/devfloppy.h - 664 sys sys 1032409559 4081
 sys/src/boot/pc/devfloppy.h - 664 sys sys 1032409559 4081
 sys/src/boot/pc/devi82365.c - 664 sys sys 1019533020 23202
 sys/src/boot/pc/devi82365.c - 664 sys sys 1019533020 23202
 sys/src/boot/pc/devpccard.c - 664 sys sys 1019533020 41357
 sys/src/boot/pc/devpccard.c - 664 sys sys 1019533020 41357
 sys/src/boot/pc/devsd.c - 664 sys sys 1077033681 11262
 sys/src/boot/pc/devsd.c - 664 sys sys 1077033681 11262
 sys/src/boot/pc/dma.c - 664 sys sys 1015007949 4972
 sys/src/boot/pc/dma.c - 664 sys sys 1015007949 4972
-sys/src/boot/pc/donprint.c - 664 sys sys 1019240172 4212
 sys/src/boot/pc/dosboot.c - 664 sys sys 1088798342 11096
 sys/src/boot/pc/dosboot.c - 664 sys sys 1088798342 11096
 sys/src/boot/pc/dosfs.h - 664 sys sys 1032215924 1467
 sys/src/boot/pc/dosfs.h - 664 sys sys 1032215924 1467
 sys/src/boot/pc/eoffs - 664 sys sys 1015007950 0
 sys/src/boot/pc/eoffs - 664 sys sys 1015007950 0
 sys/src/boot/pc/error.h - 664 sys sys 1015007950 3081
 sys/src/boot/pc/error.h - 664 sys sys 1015007950 3081
-sys/src/boot/pc/ether.c - 664 sys sys 1071175087 4727
+sys/src/boot/pc/ether.c - 664 sys sys 1094674486 5055
 sys/src/boot/pc/ether2000.c - 664 sys sys 1015007950 2609
 sys/src/boot/pc/ether2000.c - 664 sys sys 1015007950 2609
 sys/src/boot/pc/ether2114x.c - 664 sys sys 1066618033 37048
 sys/src/boot/pc/ether2114x.c - 664 sys sys 1066618033 37048
 sys/src/boot/pc/ether589.c - 664 sys sys 1015007950 4628
 sys/src/boot/pc/ether589.c - 664 sys sys 1015007950 4628
@@ -6481,27 +6480,28 @@ sys/src/boot/pc/etherec2t.c - 664 sys sys 1015007951 3598
 sys/src/boot/pc/etherelnk3.c - 664 sys sys 1034454878 44068
 sys/src/boot/pc/etherelnk3.c - 664 sys sys 1034454878 44068
 sys/src/boot/pc/etherelnk3x.c - 664 sys sys 1015007951 24989
 sys/src/boot/pc/etherelnk3x.c - 664 sys sys 1015007951 24989
 sys/src/boot/pc/etherif.h - 664 sys sys 1015007951 1285
 sys/src/boot/pc/etherif.h - 664 sys sys 1015007951 1285
+sys/src/boot/pc/etherigbe.c - 664 sys sys 1094674487 39270
 sys/src/boot/pc/ethermii.c - 664 sys sys 1071175087 4493
 sys/src/boot/pc/ethermii.c - 664 sys sys 1071175087 4493
 sys/src/boot/pc/ethermii.h - 664 sys sys 1071175087 3259
 sys/src/boot/pc/ethermii.h - 664 sys sys 1071175087 3259
 sys/src/boot/pc/etherrhine.c - 664 sys sys 1071175087 12403
 sys/src/boot/pc/etherrhine.c - 664 sys sys 1071175087 12403
-sys/src/boot/pc/fns.h - 664 sys sys 1032215922 4081
-sys/src/boot/pc/fs.c - 664 sys sys 1032215914 1487
-sys/src/boot/pc/fs.h - 664 sys sys 1032215924 627
+sys/src/boot/pc/fns.h - 664 sys sys 1094674488 4146
+sys/src/boot/pc/fs.c - 664 sys sys 1094674483 1509
+sys/src/boot/pc/fs.h - 664 sys sys 1094674488 653
 sys/src/boot/pc/ilock.c - 664 sys sys 1015007952 303
 sys/src/boot/pc/ilock.c - 664 sys sys 1015007952 303
 sys/src/boot/pc/inflate.c - 664 sys sys 1021579984 2802
 sys/src/boot/pc/inflate.c - 664 sys sys 1021579984 2802
 sys/src/boot/pc/io.h - 664 sys sys 1015007952 5420
 sys/src/boot/pc/io.h - 664 sys sys 1015007952 5420
-sys/src/boot/pc/ip.h - 664 sys sys 1089814405 2435
+sys/src/boot/pc/ip.h - 664 sys sys 1094674489 2461
 sys/src/boot/pc/kbd.c - 664 sys sys 1015007952 10188
 sys/src/boot/pc/kbd.c - 664 sys sys 1015007952 10188
 sys/src/boot/pc/kfs.h - 664 sys sys 1032215924 861
 sys/src/boot/pc/kfs.h - 664 sys sys 1032215924 861
 sys/src/boot/pc/kfsboot.c - 664 sys sys 1032215914 4788
 sys/src/boot/pc/kfsboot.c - 664 sys sys 1032215914 4788
-sys/src/boot/pc/l.s - 664 sys sys 1063855535 13012
-sys/src/boot/pc/lib.h - 664 sys sys 1088798344 2089
-sys/src/boot/pc/load.c - 664 sys sys 1088798343 8358
+sys/src/boot/pc/l.s - 664 sys sys 1094674488 13107
+sys/src/boot/pc/lib.h - 664 sys sys 1094674487 2794
+sys/src/boot/pc/load.c - 664 sys sys 1094674484 8635
 sys/src/boot/pc/mbr.s - 664 sys sys 1015007953 6234
 sys/src/boot/pc/mbr.s - 664 sys sys 1015007953 6234
 sys/src/boot/pc/mem.h - 664 sys sys 1015007953 3407
 sys/src/boot/pc/mem.h - 664 sys sys 1015007953 3407
 sys/src/boot/pc/memory.c - 664 sys sys 1019533021 10272
 sys/src/boot/pc/memory.c - 664 sys sys 1019533021 10272
-sys/src/boot/pc/mkfile - 664 sys sys 1077739195 3063
-sys/src/boot/pc/noether.c - 664 sys sys 1018553453 300
+sys/src/boot/pc/mkfile - 664 sys sys 1094674483 3088
+sys/src/boot/pc/noether.c - 664 sys sys 1094674488 358
 sys/src/boot/pc/part.c - 664 sys sys 1032215918 7505
 sys/src/boot/pc/part.c - 664 sys sys 1032215918 7505
 sys/src/boot/pc/pbs.s - 664 sys sys 1017854325 8279
 sys/src/boot/pc/pbs.s - 664 sys sys 1017854325 8279
 sys/src/boot/pc/pbsdisk - 775 sys sys 1017854325 509
 sys/src/boot/pc/pbsdisk - 775 sys sys 1017854325 509
@@ -6510,11 +6510,12 @@ sys/src/boot/pc/pbsdisklba - 775 sys sys 1015007954 509
 sys/src/boot/pc/pbsdisklba.s - 664 sys sys 1015007954 6022
 sys/src/boot/pc/pbsdisklba.s - 664 sys sys 1015007954 6022
 sys/src/boot/pc/pbslba.s - 664 sys sys 1017854326 8147
 sys/src/boot/pc/pbslba.s - 664 sys sys 1017854326 8147
 sys/src/boot/pc/pci.c - 664 sys sys 1065815736 17580
 sys/src/boot/pc/pci.c - 664 sys sys 1065815736 17580
+sys/src/boot/pc/print.c - 664 sys sys 1094674483 219
 sys/src/boot/pc/queue.c - 664 sys sys 1015007954 566
 sys/src/boot/pc/queue.c - 664 sys sys 1015007954 566
-sys/src/boot/pc/sd.h - 664 sys sys 1032215925 2404
+sys/src/boot/pc/sd.h - 664 sys sys 1094674489 2271
 sys/src/boot/pc/sd53c8xx.c - 664 sys sys 1077033951 52135
 sys/src/boot/pc/sd53c8xx.c - 664 sys sys 1077033951 52135
 sys/src/boot/pc/sd53c8xx.i - 664 sys sys 1015007955 27245
 sys/src/boot/pc/sd53c8xx.i - 664 sys sys 1015007955 27245
-sys/src/boot/pc/sdata.c - 664 sys sys 1071615664 35424
+sys/src/boot/pc/sdata.c - 664 sys sys 1094674485 35425
 sys/src/boot/pc/sdmylex.c - 664 sys sys 1015007955 28743
 sys/src/boot/pc/sdmylex.c - 664 sys sys 1015007955 28743
 sys/src/boot/pc/sdscsi.c - 664 sys sys 1077033682 7022
 sys/src/boot/pc/sdscsi.c - 664 sys sys 1077033682 7022
 sys/src/boot/pc/trap.c - 664 sys sys 1018462833 7098
 sys/src/boot/pc/trap.c - 664 sys sys 1018462833 7098
@@ -12337,4 +12338,4 @@ usr/glenda/lib/profile - 664 glenda glenda 1021580005 847
 usr/glenda/readme.acme - 664 glenda glenda 1019860628 4753
 usr/glenda/readme.acme - 664 glenda glenda 1019860628 4753
 usr/glenda/readme.rio - 664 glenda glenda 1019860628 6370
 usr/glenda/readme.rio - 664 glenda glenda 1019860628 6370
 usr/glenda/tmp - 20000000775 glenda glenda 1018802620 0
 usr/glenda/tmp - 20000000775 glenda glenda 1018802620 0
-386/bin/tar - 775 sys sys 1094612761 81786
+sys/src/boot/pc/mkfile - 664 sys sys 1094700526 3090

+ 26 - 25
dist/replica/plan9.db

@@ -1,8 +1,8 @@
 386 - 20000000775 sys sys 1010957353 0
 386 - 20000000775 sys sys 1010957353 0
-386/9load - 775 sys sys 1088798345 188040
-386/9loaddebug - 775 sys sys 1091156989 270242
-386/9loadlite - 775 sys sys 1088798346 125004
-386/9loadlitedebug - 775 sys sys 1089402462 183654
+386/9load - 775 sys sys 1094674490 206624
+386/9loaddebug - 775 sys sys 1094674492 297770
+386/9loadlite - 775 sys sys 1094674491 130360
+386/9loadlitedebug - 775 sys sys 1094674492 192921
 386/9pc - 775 sys sys 1092110936 1817018
 386/9pc - 775 sys sys 1092110936 1817018
 386/9pc.gz - 664 sys sys 1077049336 635727
 386/9pc.gz - 664 sys sys 1077049336 635727
 386/9pccpu - 775 sys sys 1092110939 1473170
 386/9pccpu - 775 sys sys 1092110939 1473170
@@ -11,7 +11,7 @@
 386/9pcdisk.gz - 664 sys sys 1040006345 703136
 386/9pcdisk.gz - 664 sys sys 1040006345 703136
 386/9pcf - 775 sys sys 1092110948 2351243
 386/9pcf - 775 sys sys 1092110948 2351243
 386/9pcf.gz - 664 sys sys 1077049490 872650
 386/9pcf.gz - 664 sys sys 1077049490 872650
-386/9pxeload - 775 sys sys 1088798346 188040
+386/9pxeload - 775 sys sys 1094674490 206624
 386/_9pcdisk.gz - 664 sys sys 1039764191 695837
 386/_9pcdisk.gz - 664 sys sys 1039764191 695837
 386/bin - 20000000775 sys sys 1018897690 0
 386/bin - 20000000775 sys sys 1018897690 0
 386/bin/8a - 775 sys sys 1089397305 112804
 386/bin/8a - 775 sys sys 1089397305 112804
@@ -503,7 +503,7 @@
 386/include/u.h - 664 sys sys 1042604326 1450
 386/include/u.h - 664 sys sys 1042604326 1450
 386/include/ureg.h - 664 sys sys 944946012 523
 386/include/ureg.h - 664 sys sys 944946012 523
 386/init - 775 sys sys 1085077133 98033
 386/init - 775 sys sys 1085077133 98033
-386/ld.com - 775 sys sys 1088798347 64480
+386/ld.com - 775 sys sys 1094674493 69772
 386/lib - 20000000775 sys sys 1016826328 0
 386/lib - 20000000775 sys sys 1016826328 0
 386/lib/ape - 20000000775 sys sys 944969312 0
 386/lib/ape - 20000000775 sys sys 944969312 0
 386/lib/ape/lib9.a - 664 sys sys 1038237538 6378
 386/lib/ape/lib9.a - 664 sys sys 1038237538 6378
@@ -5042,7 +5042,7 @@ sys/man/7/map - 664 sys sys 1032632790 13549
 sys/man/7/scat - 664 sys sys 970069855 8904
 sys/man/7/scat - 664 sys sys 970069855 8904
 sys/man/8 - 20000000775 sys sys 1018384448 0
 sys/man/8 - 20000000775 sys sys 1018384448 0
 sys/man/8/0intro - 664 sys sys 944959679 247
 sys/man/8/0intro - 664 sys sys 944959679 247
-sys/man/8/9load - 664 sys sys 1056073409 8555
+sys/man/8/9load - 664 sys sys 1094676489 9170
 sys/man/8/9pcon - 664 sys sys 1018973955 2226
 sys/man/8/9pcon - 664 sys sys 1018973955 2226
 sys/man/8/INDEX - 664 sys sys 1089339723 2669
 sys/man/8/INDEX - 664 sys sys 1089339723 2669
 sys/man/8/INDEX.html - 664 sys sys 1089321186 7944
 sys/man/8/INDEX.html - 664 sys sys 1089321186 7944
@@ -5079,7 +5079,7 @@ sys/man/8/nfsserver - 664 sys sys 1017251291 3397
 sys/man/8/pcmcia - 664 sys sys 944959679 408
 sys/man/8/pcmcia - 664 sys sys 944959679 408
 sys/man/8/pem - 664 sys sys 1060263669 1189
 sys/man/8/pem - 664 sys sys 1060263669 1189
 sys/man/8/ping - 664 sys sys 1084473185 3436
 sys/man/8/ping - 664 sys sys 1084473185 3436
-sys/man/8/plan9.ini - 664 sys sys 1092082105 20930
+sys/man/8/plan9.ini - 664 sys sys 1094650551 20806
 sys/man/8/pop3 - 664 sys sys 1063854676 2720
 sys/man/8/pop3 - 664 sys sys 1063854676 2720
 sys/man/8/ppp - 664 sys sys 1050361032 4424
 sys/man/8/ppp - 664 sys sys 1050361032 4424
 sys/man/8/prep - 664 sys sys 1079705872 13820
 sys/man/8/prep - 664 sys sys 1079705872 13820
@@ -6449,24 +6449,23 @@ sys/src/boot/pc/apm.c - 664 sys sys 1015007947 289
 sys/src/boot/pc/bcom.c - 664 sys sys 1032215919 6421
 sys/src/boot/pc/bcom.c - 664 sys sys 1032215919 6421
 sys/src/boot/pc/boot.c - 664 sys sys 1021579983 3353
 sys/src/boot/pc/boot.c - 664 sys sys 1021579983 3353
 sys/src/boot/pc/bootld.c - 664 sys sys 1015007948 1801
 sys/src/boot/pc/bootld.c - 664 sys sys 1015007948 1801
-sys/src/boot/pc/bootp.c - 664 sys sys 1015007948 9417
+sys/src/boot/pc/bootp.c - 664 sys sys 1094674486 12069
 sys/src/boot/pc/cga.c - 664 sys sys 1015007948 1362
 sys/src/boot/pc/cga.c - 664 sys sys 1015007948 1362
 sys/src/boot/pc/clock.c - 664 sys sys 1088089722 5783
 sys/src/boot/pc/clock.c - 664 sys sys 1088089722 5783
-sys/src/boot/pc/conf.c - 664 sys sys 1063855536 10128
-sys/src/boot/pc/console.c - 664 sys sys 1068158999 3487
-sys/src/boot/pc/dat.h - 664 sys sys 1056073257 3432
+sys/src/boot/pc/conf.c - 664 sys sys 1094674484 10217
+sys/src/boot/pc/console.c - 664 sys sys 1094674483 3388
+sys/src/boot/pc/dat.h - 664 sys sys 1094674488 3518
 sys/src/boot/pc/devfloppy.c - 664 sys sys 1032215913 15505
 sys/src/boot/pc/devfloppy.c - 664 sys sys 1032215913 15505
 sys/src/boot/pc/devfloppy.h - 664 sys sys 1032409559 4081
 sys/src/boot/pc/devfloppy.h - 664 sys sys 1032409559 4081
 sys/src/boot/pc/devi82365.c - 664 sys sys 1019533020 23202
 sys/src/boot/pc/devi82365.c - 664 sys sys 1019533020 23202
 sys/src/boot/pc/devpccard.c - 664 sys sys 1019533020 41357
 sys/src/boot/pc/devpccard.c - 664 sys sys 1019533020 41357
 sys/src/boot/pc/devsd.c - 664 sys sys 1077033681 11262
 sys/src/boot/pc/devsd.c - 664 sys sys 1077033681 11262
 sys/src/boot/pc/dma.c - 664 sys sys 1015007949 4972
 sys/src/boot/pc/dma.c - 664 sys sys 1015007949 4972
-sys/src/boot/pc/donprint.c - 664 sys sys 1019240172 4212
 sys/src/boot/pc/dosboot.c - 664 sys sys 1088798342 11096
 sys/src/boot/pc/dosboot.c - 664 sys sys 1088798342 11096
 sys/src/boot/pc/dosfs.h - 664 sys sys 1032215924 1467
 sys/src/boot/pc/dosfs.h - 664 sys sys 1032215924 1467
 sys/src/boot/pc/eoffs - 664 sys sys 1015007950 0
 sys/src/boot/pc/eoffs - 664 sys sys 1015007950 0
 sys/src/boot/pc/error.h - 664 sys sys 1015007950 3081
 sys/src/boot/pc/error.h - 664 sys sys 1015007950 3081
-sys/src/boot/pc/ether.c - 664 sys sys 1071175087 4727
+sys/src/boot/pc/ether.c - 664 sys sys 1094674486 5055
 sys/src/boot/pc/ether2000.c - 664 sys sys 1015007950 2609
 sys/src/boot/pc/ether2000.c - 664 sys sys 1015007950 2609
 sys/src/boot/pc/ether2114x.c - 664 sys sys 1066618033 37048
 sys/src/boot/pc/ether2114x.c - 664 sys sys 1066618033 37048
 sys/src/boot/pc/ether589.c - 664 sys sys 1015007950 4628
 sys/src/boot/pc/ether589.c - 664 sys sys 1015007950 4628
@@ -6481,27 +6480,28 @@ sys/src/boot/pc/etherec2t.c - 664 sys sys 1015007951 3598
 sys/src/boot/pc/etherelnk3.c - 664 sys sys 1034454878 44068
 sys/src/boot/pc/etherelnk3.c - 664 sys sys 1034454878 44068
 sys/src/boot/pc/etherelnk3x.c - 664 sys sys 1015007951 24989
 sys/src/boot/pc/etherelnk3x.c - 664 sys sys 1015007951 24989
 sys/src/boot/pc/etherif.h - 664 sys sys 1015007951 1285
 sys/src/boot/pc/etherif.h - 664 sys sys 1015007951 1285
+sys/src/boot/pc/etherigbe.c - 664 sys sys 1094674487 39270
 sys/src/boot/pc/ethermii.c - 664 sys sys 1071175087 4493
 sys/src/boot/pc/ethermii.c - 664 sys sys 1071175087 4493
 sys/src/boot/pc/ethermii.h - 664 sys sys 1071175087 3259
 sys/src/boot/pc/ethermii.h - 664 sys sys 1071175087 3259
 sys/src/boot/pc/etherrhine.c - 664 sys sys 1071175087 12403
 sys/src/boot/pc/etherrhine.c - 664 sys sys 1071175087 12403
-sys/src/boot/pc/fns.h - 664 sys sys 1032215922 4081
-sys/src/boot/pc/fs.c - 664 sys sys 1032215914 1487
-sys/src/boot/pc/fs.h - 664 sys sys 1032215924 627
+sys/src/boot/pc/fns.h - 664 sys sys 1094674488 4146
+sys/src/boot/pc/fs.c - 664 sys sys 1094674483 1509
+sys/src/boot/pc/fs.h - 664 sys sys 1094674488 653
 sys/src/boot/pc/ilock.c - 664 sys sys 1015007952 303
 sys/src/boot/pc/ilock.c - 664 sys sys 1015007952 303
 sys/src/boot/pc/inflate.c - 664 sys sys 1021579984 2802
 sys/src/boot/pc/inflate.c - 664 sys sys 1021579984 2802
 sys/src/boot/pc/io.h - 664 sys sys 1015007952 5420
 sys/src/boot/pc/io.h - 664 sys sys 1015007952 5420
-sys/src/boot/pc/ip.h - 664 sys sys 1089814405 2435
+sys/src/boot/pc/ip.h - 664 sys sys 1094674489 2461
 sys/src/boot/pc/kbd.c - 664 sys sys 1015007952 10188
 sys/src/boot/pc/kbd.c - 664 sys sys 1015007952 10188
 sys/src/boot/pc/kfs.h - 664 sys sys 1032215924 861
 sys/src/boot/pc/kfs.h - 664 sys sys 1032215924 861
 sys/src/boot/pc/kfsboot.c - 664 sys sys 1032215914 4788
 sys/src/boot/pc/kfsboot.c - 664 sys sys 1032215914 4788
-sys/src/boot/pc/l.s - 664 sys sys 1063855535 13012
-sys/src/boot/pc/lib.h - 664 sys sys 1088798344 2089
-sys/src/boot/pc/load.c - 664 sys sys 1088798343 8358
+sys/src/boot/pc/l.s - 664 sys sys 1094674488 13107
+sys/src/boot/pc/lib.h - 664 sys sys 1094674487 2794
+sys/src/boot/pc/load.c - 664 sys sys 1094674484 8635
 sys/src/boot/pc/mbr.s - 664 sys sys 1015007953 6234
 sys/src/boot/pc/mbr.s - 664 sys sys 1015007953 6234
 sys/src/boot/pc/mem.h - 664 sys sys 1015007953 3407
 sys/src/boot/pc/mem.h - 664 sys sys 1015007953 3407
 sys/src/boot/pc/memory.c - 664 sys sys 1019533021 10272
 sys/src/boot/pc/memory.c - 664 sys sys 1019533021 10272
-sys/src/boot/pc/mkfile - 664 sys sys 1077739195 3063
-sys/src/boot/pc/noether.c - 664 sys sys 1018553453 300
+sys/src/boot/pc/mkfile - 664 sys sys 1094700526 3090
+sys/src/boot/pc/noether.c - 664 sys sys 1094674488 358
 sys/src/boot/pc/part.c - 664 sys sys 1032215918 7505
 sys/src/boot/pc/part.c - 664 sys sys 1032215918 7505
 sys/src/boot/pc/pbs.s - 664 sys sys 1017854325 8279
 sys/src/boot/pc/pbs.s - 664 sys sys 1017854325 8279
 sys/src/boot/pc/pbsdisk - 775 sys sys 1017854325 509
 sys/src/boot/pc/pbsdisk - 775 sys sys 1017854325 509
@@ -6510,11 +6510,12 @@ sys/src/boot/pc/pbsdisklba - 775 sys sys 1015007954 509
 sys/src/boot/pc/pbsdisklba.s - 664 sys sys 1015007954 6022
 sys/src/boot/pc/pbsdisklba.s - 664 sys sys 1015007954 6022
 sys/src/boot/pc/pbslba.s - 664 sys sys 1017854326 8147
 sys/src/boot/pc/pbslba.s - 664 sys sys 1017854326 8147
 sys/src/boot/pc/pci.c - 664 sys sys 1065815736 17580
 sys/src/boot/pc/pci.c - 664 sys sys 1065815736 17580
+sys/src/boot/pc/print.c - 664 sys sys 1094674483 219
 sys/src/boot/pc/queue.c - 664 sys sys 1015007954 566
 sys/src/boot/pc/queue.c - 664 sys sys 1015007954 566
-sys/src/boot/pc/sd.h - 664 sys sys 1032215925 2404
+sys/src/boot/pc/sd.h - 664 sys sys 1094674489 2271
 sys/src/boot/pc/sd53c8xx.c - 664 sys sys 1077033951 52135
 sys/src/boot/pc/sd53c8xx.c - 664 sys sys 1077033951 52135
 sys/src/boot/pc/sd53c8xx.i - 664 sys sys 1015007955 27245
 sys/src/boot/pc/sd53c8xx.i - 664 sys sys 1015007955 27245
-sys/src/boot/pc/sdata.c - 664 sys sys 1071615664 35424
+sys/src/boot/pc/sdata.c - 664 sys sys 1094674485 35425
 sys/src/boot/pc/sdmylex.c - 664 sys sys 1015007955 28743
 sys/src/boot/pc/sdmylex.c - 664 sys sys 1015007955 28743
 sys/src/boot/pc/sdscsi.c - 664 sys sys 1077033682 7022
 sys/src/boot/pc/sdscsi.c - 664 sys sys 1077033682 7022
 sys/src/boot/pc/trap.c - 664 sys sys 1018462833 7098
 sys/src/boot/pc/trap.c - 664 sys sys 1018462833 7098

+ 28 - 0
dist/replica/plan9.log

@@ -16659,3 +16659,31 @@
 1094571023 0 c sys/games/lib/fortunes - 664 sys sys 1094570700 249644
 1094571023 0 c sys/games/lib/fortunes - 664 sys sys 1094570700 249644
 1094599829 0 c sys/src/cmd/tar.c - 664 sys sys 1094598836 15585
 1094599829 0 c sys/src/cmd/tar.c - 664 sys sys 1094598836 15585
 1094614232 0 c 386/bin/tar - 775 sys sys 1094612761 81786
 1094614232 0 c 386/bin/tar - 775 sys sys 1094612761 81786
+1094652039 0 c sys/man/8/plan9.ini - 664 sys sys 1094650551 20806
+1094675442 0 c 386/9load - 775 sys sys 1094674490 206624
+1094675442 1 c 386/9loaddebug - 775 sys sys 1094674492 297770
+1094675442 2 c 386/9loadlite - 775 sys sys 1094674491 130360
+1094675442 3 c 386/9loadlitedebug - 775 sys sys 1094674492 192921
+1094675442 4 c 386/9pxeload - 775 sys sys 1094674490 206624
+1094675442 5 c 386/ld.com - 775 sys sys 1094674493 69772
+1094675442 6 c sys/src/boot/pc/bootp.c - 664 sys sys 1094674486 12069
+1094675442 7 c sys/src/boot/pc/conf.c - 664 sys sys 1094674484 10217
+1094675442 8 c sys/src/boot/pc/console.c - 664 sys sys 1094674483 3388
+1094675442 9 c sys/src/boot/pc/dat.h - 664 sys sys 1094674488 3518
+1094675442 10 c sys/src/boot/pc/ether.c - 664 sys sys 1094674486 5055
+1094675442 11 a sys/src/boot/pc/etherigbe.c - 664 sys sys 1094674487 39270
+1094675442 12 c sys/src/boot/pc/fns.h - 664 sys sys 1094674488 4146
+1094675442 13 c sys/src/boot/pc/fs.c - 664 sys sys 1094674483 1509
+1094675442 14 c sys/src/boot/pc/fs.h - 664 sys sys 1094674488 653
+1094675442 15 c sys/src/boot/pc/ip.h - 664 sys sys 1094674489 2461
+1094675442 16 c sys/src/boot/pc/l.s - 664 sys sys 1094674488 13107
+1094675442 17 c sys/src/boot/pc/lib.h - 664 sys sys 1094674487 2794
+1094675442 18 c sys/src/boot/pc/load.c - 664 sys sys 1094674484 8635
+1094675442 19 c sys/src/boot/pc/mkfile - 664 sys sys 1094674483 3088
+1094675442 20 c sys/src/boot/pc/noether.c - 664 sys sys 1094674488 358
+1094675442 21 a sys/src/boot/pc/print.c - 664 sys sys 1094674483 219
+1094675442 22 c sys/src/boot/pc/sd.h - 664 sys sys 1094674489 2271
+1094675442 23 c sys/src/boot/pc/sdata.c - 664 sys sys 1094674485 35425
+1094675442 24 d sys/src/boot/pc/donprint.c - 664 sys sys 1019240172 0
+1094677243 0 c sys/man/8/9load - 664 sys sys 1094676489 9170
+1094700648 0 c sys/src/boot/pc/mkfile - 664 sys sys 1094700526 3090

+ 24 - 0
sys/man/8/9load

@@ -383,6 +383,22 @@ the disk.
 See 
 See 
 .IR dossrv (4)
 .IR dossrv (4)
 for information on ensuring this.
 for information on ensuring this.
+.PP
+.I 9pxeload
+differs slightly in operation from
+.IR 9load .
+It is initially loaded by the PXE BIOS at physical address 0x7C00.
+Only devices which can be automatically configured,
+e.g. most PCI ethernet adapters,
+will be recognised.
+If the file
+.IB /cfg/pxe/ XXXXXXXXXXXX
+can be located via a DHCP server,
+where
+.B XXXXXXXXXXXX
+is the MAC address of a recognised ethernet adapter,
+the contents are obtained and used as a
+.IR plan9.ini .
 .SH FILES
 .SH FILES
 .RI [ drive :]
 .RI [ drive :]
 [
 [
@@ -415,3 +431,11 @@ it attempts to de-install it, but the technique
 used may not always work.
 used may not always work.
 It is safer not to install the Extended Memory Manager before running
 It is safer not to install the Extended Memory Manager before running
 .IR ld .
 .IR ld .
+.PP
+The way
+.I 9pxeload
+obtains the information normally found in a disc
+.I plan9.ini
+file,
+and thereby the kernel to load and boot,
+is not ideal and may change in the future.

+ 3 - 6
sys/man/8/plan9.ini

@@ -315,12 +315,9 @@ attribute.
 .B rtl8139
 .B rtl8139
 The Realtek 8139.
 The Realtek 8139.
 .TP
 .TP
-.B 82543gc
-The Intel RS-82543GC gigabit ethernet controller,
-as found on the Intel PRO/1000[FT] server adapter.
-The older non-[FT] cards based on the 82542 (LSI L2A1157)
-chip are not supported, although support would probably be
-easy to add.
+.B igbe
+The Intel 8254X Gigabit Ethernet controllers,
+as found on the Intel PRO/1000 adapters for copper (not fiber).
 .TP
 .TP
 .B smc91cxx
 .B smc91cxx
 SMC 91cXX chip-based PCMCIA adapters, notably the SMC EtherEZ card.
 SMC 91cXX chip-based PCMCIA adapters, notably the SMC EtherEZ card.

+ 177 - 27
sys/src/boot/pc/bootp.c

@@ -143,14 +143,30 @@ printea(uchar *ea)
 		ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]);
 		ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]);
 }
 }
 
 
+enum {
+	/* this is only true of IPv4, but we're not doing v6 yet */
+	Min_udp_payload = ETHERMINTU - ETHERHDRSIZE - UDP_HDRSIZE,
+};
+
 static void
 static void
 udpsend(int ctlrno, Netaddr *a, void *data, int dlen)
 udpsend(int ctlrno, Netaddr *a, void *data, int dlen)
 {
 {
+	char payload[ETHERMAXTU];
 	Udphdr *uh;
 	Udphdr *uh;
 	Etherhdr *ip;
 	Etherhdr *ip;
 	Etherpkt pkt;
 	Etherpkt pkt;
 	int len, ptcllen;
 	int len, ptcllen;
 
 
+	/*
+	 * if packet is too short, make it longer rather than relying
+	 * on ethernet interface or lower layers to pad it.
+	 */
+	if (dlen < Min_udp_payload) {
+		memmove(payload, data, dlen);
+		data = payload;
+		dlen = Min_udp_payload;
+	}
+
 	uh = (Udphdr*)&pkt;
 	uh = (Udphdr*)&pkt;
 
 
 	memset(uh, 0, sizeof(Etherpkt));
 	memset(uh, 0, sizeof(Etherpkt));
@@ -264,7 +280,7 @@ if(debug) print("not ip...");
 		}
 		}
 
 
 		if(h->udpproto != IP_UDPPROTO) {
 		if(h->udpproto != IP_UDPPROTO) {
-if(debug) print("not udp...");
+if(debug) print("not udp (%d)...", h->udpproto);
 			continue;
 			continue;
 		}
 		}
 
 
@@ -313,6 +329,14 @@ if(debug) print("bad ip\n");
 
 
 static int tftpblockno;
 static int tftpblockno;
 
 
+/*
+ * format of a request packet, from the RFC:
+ *
+            2 bytes     string    1 byte     string   1 byte
+            ------------------------------------------------
+           | Opcode |  Filename  |   0  |    Mode    |   0  |
+            ------------------------------------------------
+ */
 static int
 static int
 tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
 tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
 {
 {
@@ -321,8 +345,8 @@ tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
 
 
 	buf[0] = 0;
 	buf[0] = 0;
 	buf[1] = Tftp_READ;
 	buf[1] = Tftp_READ;
-	len = sprint(buf+2, "%s", name) + 2;
-	len += sprint(buf+len+1, "octet") + 2;
+	len = 2 + sprint(buf+2, "%s", name) + 1;
+	len += sprint(buf+len, "octet") + 1;
 
 
 	oport = a->port;
 	oport = a->port;
 	for(i = 0; i < 5; i++){
 	for(i = 0; i < 5; i++){
@@ -396,11 +420,11 @@ tftpread(int ctlrno, Netaddr *a, Tftp *tftp, int dlen)
 	return -1;
 	return -1;
 }
 }
 
 
-int
-bootp(int ctlrno, char *file, Boot *b)
+static int
+bootpopen(int ctlrno, char *file, Bootp *rep, int dotftpopen)
 {
 {
-	Bootp req, rep;
-	int i, dlen;
+	Bootp req;
+	int i, n;
 	uchar *ea;
 	uchar *ea;
 	char name[128], *filename, *sysname;
 	char name[128], *filename, *sysname;
 
 
@@ -420,7 +444,6 @@ bootp(int ctlrno, char *file, Boot *b)
 		else
 		else
 			filename = name;
 			filename = name;
 	}
 	}
-		
 
 
 	memset(&req, 0, sizeof(req));
 	memset(&req, 0, sizeof(req));
 	req.op = Bootrequest;
 	req.op = Bootrequest;
@@ -436,18 +459,19 @@ bootp(int ctlrno, char *file, Boot *b)
 	myaddr.port = BPportsrc;
 	myaddr.port = BPportsrc;
 	memmove(myaddr.ea, ea, Eaddrlen);
 	memmove(myaddr.ea, ea, Eaddrlen);
 
 
+	etherrxflush(ctlrno);
 	for(i = 0; i < 10; i++) {
 	for(i = 0; i < 10; i++) {
 		server.ip = Bcastip;
 		server.ip = Bcastip;
 		server.port = BPportdst;
 		server.port = BPportdst;
 		memmove(server.ea, broadcast, sizeof(server.ea));
 		memmove(server.ea, broadcast, sizeof(server.ea));
 		udpsend(ctlrno, &server, &req, sizeof(req));
 		udpsend(ctlrno, &server, &req, sizeof(req));
-		if(udprecv(ctlrno, &server, &rep, sizeof(rep)) <= 0)
+		if(udprecv(ctlrno, &server, rep, sizeof(*rep)) <= 0)
 			continue;
 			continue;
-		if(memcmp(req.chaddr, rep.chaddr, Eaddrlen))
+		if(memcmp(req.chaddr, rep->chaddr, Eaddrlen))
 			continue;
 			continue;
-		if(rep.htype != 1 || rep.hlen != Eaddrlen)
+		if(rep->htype != 1 || rep->hlen != Eaddrlen)
 			continue;
 			continue;
-		if(sysname == 0 || strcmp(sysname, rep.sname) == 0)
+		if(sysname == 0 || strcmp(sysname, rep->sname) == 0)
 			break;
 			break;
 	}
 	}
 	if(i >= 10) {
 	if(i >= 10) {
@@ -455,35 +479,161 @@ bootp(int ctlrno, char *file, Boot *b)
 		return -1;
 		return -1;
 	}
 	}
 
 
-	if(filename == 0 || *filename == 0)
-		filename = rep.file;
+	if(!dotftpopen)
+		return 0;
 
 
-	if(rep.sname[0] != '\0')
-		 print("%s ", rep.sname);
+	if(filename == 0 || *filename == 0){
+		if(strcmp(rep->file, "/386/9pxeload") == 0)
+			return -1;
+		filename = rep->file;
+	}
+
+	if(rep->sname[0] != '\0')
+		 print("%s ", rep->sname);
 	print("(%d.%d.%d.%d!%d): %s\n",
 	print("(%d.%d.%d.%d!%d): %s\n",
-		rep.siaddr[0],
-		rep.siaddr[1],
-		rep.siaddr[2],
-		rep.siaddr[3],
+		rep->siaddr[0],
+		rep->siaddr[1],
+		rep->siaddr[2],
+		rep->siaddr[3],
 		server.port,
 		server.port,
 		filename);
 		filename);
 
 
-	myaddr.ip = nhgetl(rep.yiaddr);
+	myaddr.ip = nhgetl(rep->yiaddr);
 	myaddr.port = tftpport++;
 	myaddr.port = tftpport++;
-	server.ip = nhgetl(rep.siaddr);
+	server.ip = nhgetl(rep->siaddr);
 	server.port = TFTPport;
 	server.port = TFTPport;
 
 
-	if((dlen = tftpopen(ctlrno, &server, filename, &tftpb)) < 0)
+	if((n = tftpopen(ctlrno, &server, filename, &tftpb)) < 0)
 		return -1;
 		return -1;
 
 
-	while(bootpass(b, tftpb.data, dlen) == MORE)
-		if((dlen = tftpread(ctlrno, &server, &tftpb, sizeof(tftpb.data))) < sizeof(tftpb.data))
+	return n;
+}
+
+int
+bootpboot(int ctlrno, char *file, Boot *b)
+{
+	int n;
+	Bootp rep;
+
+	if((n = bootpopen(ctlrno, file, &rep, 1)) < 0)
+		return -1;
+
+	while(bootpass(b, tftpb.data, n) == MORE){
+		n = tftpread(ctlrno, &server, &tftpb, sizeof(tftpb.data));
+		if(n < sizeof(tftpb.data))
 			break;
 			break;
+	}
 
 
-	if(0 < dlen && dlen < sizeof(tftpb.data))	/* got to end of file */
-		bootpass(b, tftpb.data, dlen);
+	if(0 < n && n < sizeof(tftpb.data))	/* got to end of file */
+		bootpass(b, tftpb.data, n);
 	else
 	else
 		nak(ctlrno, &server, 3, "ok", 0);	/* tftpclose to abort transfer */
 		nak(ctlrno, &server, 3, "ok", 0);	/* tftpclose to abort transfer */
 	bootpass(b, nil, 0);	/* boot if possible */
 	bootpass(b, nil, 0);	/* boot if possible */
 	return -1;
 	return -1;
 }
 }
+
+#include "fs.h"
+
+#define INIPATHLEN	64
+
+static struct {
+	Fs	fs;
+	char	ini[INIPATHLEN];
+} pxether[MaxEther];
+
+static vlong
+pxediskseek(Fs*, vlong)
+{
+	return -1LL;
+}
+
+static long
+pxediskread(Fs*, void*, long)
+{
+	return -1;
+}
+
+static long
+pxeread(File* f, void* va, long len)
+{
+	int n;
+	Bootp rep;
+	char *p, *v;
+
+	if((n = bootpopen(f->fs->dev, pxether[f->fs->dev].ini, &rep, 1)) < 0)
+		return -1;
+
+	p = v = va;
+	while(n > 0) {
+		if((p-v)+n > len)
+			n = len - (p-v);
+		memmove(p, tftpb.data, n);
+		p += n;
+		if(n != Segsize)
+			break;
+		if((n = tftpread(f->fs->dev, &server, &tftpb, sizeof(tftpb.data))) < 0)
+			return -1;
+	}
+	return p-v;
+}
+
+static int
+pxewalk(File* f, char* name)
+{
+	Bootp rep;
+	char *ini;
+
+	switch(f->walked){
+	default:
+		return -1;
+	case 0:
+		if(strcmp(name, "cfg") == 0){
+			f->walked = 1;
+			return 1;
+		}
+		break;
+	case 1:
+		if(strcmp(name, "pxe") == 0){
+			f->walked = 2;
+			return 1;
+		}
+		break;
+	case 2:
+		if(strcmp(name, "%E") != 0)
+			break;
+		f->walked = 3;
+
+		if(bootpopen(f->fs->dev, nil, &rep, 0) < 0)
+			return 0;
+
+		ini = pxether[f->fs->dev].ini;
+		snprint(ini, INIPATHLEN, "/cfg/pxe/%E", rep.chaddr);
+		f->path = ini;
+
+		return 1;
+	}
+	return 0;
+}
+
+void*
+pxegetfspart(int ctlrno, char* part, int)
+{
+	if(!pxe)
+		return nil;
+	if(strcmp(part, "*") != 0)
+		return nil;
+	if(ctlrno >= MaxEther)
+		return nil;
+
+	pxether[ctlrno].fs.dev = ctlrno;
+	pxether[ctlrno].fs.diskread = pxediskread;
+	pxether[ctlrno].fs.diskseek = pxediskseek;
+
+	pxether[ctlrno].fs.read = pxeread;
+	pxether[ctlrno].fs.walk = pxewalk;
+
+	pxether[ctlrno].fs.root.fs = &pxether[ctlrno].fs;
+	pxether[ctlrno].fs.root.walked = 0;
+
+	return &pxether[ctlrno].fs;
+}

+ 9 - 2
sys/src/boot/pc/conf.c

@@ -311,15 +311,22 @@ getconf(char *name)
 void
 void
 addconf(char *fmt, ...)
 addconf(char *fmt, ...)
 {
 {
-	donprint(BOOTARGS+strlen(BOOTARGS), BOOTARGS+BOOTARGSLEN, fmt, (&fmt+1));
+	va_list arg;
+
+	va_start(arg, fmt);
+	vseprint(BOOTARGS+strlen(BOOTARGS), BOOTARGS+BOOTARGSLEN, fmt, arg);
+	va_end(arg);
 }
 }
 
 
 void
 void
 changeconf(char *fmt, ...)
 changeconf(char *fmt, ...)
 {
 {
+	va_list arg;
 	char *p, *q, pref[20], buf[128];
 	char *p, *q, pref[20], buf[128];
 
 
-	donprint(buf, buf+sizeof buf, fmt, (&fmt+1));
+	va_start(arg, fmt);
+	vseprint(buf, buf+sizeof buf, fmt, arg);
+	va_end(arg);
 	strncpy(pref+1, buf, 19);
 	strncpy(pref+1, buf, 19);
 	pref[19] = '\0';
 	pref[19] = '\0';
 	if(p = strchr(pref, '='))
 	if(p = strchr(pref, '='))

+ 13 - 18
sys/src/boot/pc/console.c

@@ -178,26 +178,18 @@ getstr(char *prompt, char *buf, int size, char *def, int timeout)
 	return 0;
 	return 0;
 }
 }
 
 
-int
-sprint(char *s, char *fmt, ...)
-{
-	return donprint(s, s+PRINTSIZE, fmt, (&fmt+1)) - s;
-}
-
-int
-snprint(char *s, int n, char *fmt, ...)
-{
-	return donprint(s, s+n, fmt, (&fmt+1)) - s;
-}
-
 int
 int
 print(char *fmt, ...)
 print(char *fmt, ...)
 {
 {
-	char buf[PRINTSIZE];
 	int n;
 	int n;
+	va_list arg;
+	char buf[PRINTSIZE];
 
 
-	n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
+	va_start(arg, fmt);
+	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
+	va_end(arg);
 	consputs(buf, n);
 	consputs(buf, n);
+
 	return n;
 	return n;
 }
 }
 
 
@@ -205,12 +197,15 @@ void
 panic(char *fmt, ...)
 panic(char *fmt, ...)
 {
 {
 	int n;
 	int n;
+	va_list arg;
 	char buf[PRINTSIZE];
 	char buf[PRINTSIZE];
 
 
-	consputs("panic: ", 7);
-	n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
-	consputs(buf, n);
-	consputs("\n", 1);
+	strcpy(buf, "panic: ");
+	va_start(arg, fmt);
+	n = vseprint(buf+7, buf+sizeof(buf), fmt, arg) - buf;
+	va_end(arg);
+	buf[n] = '\n';
+	consputs(buf, n+1);
 
 
 //floppymemwrite();
 //floppymemwrite();
 //splhi(); for(;;);
 //splhi(); for(;;);

+ 4 - 0
sys/src/boot/pc/dat.h

@@ -45,6 +45,7 @@ typedef struct IOQ {
 
 
 enum {
 enum {
 	Eaddrlen	= 6,
 	Eaddrlen	= 6,
+	/* next two exclude 4-byte ether CRC */
 	ETHERMINTU	= 60,		/* minimum transmit size */
 	ETHERMINTU	= 60,		/* minimum transmit size */
 	ETHERMAXTU	= 1514,		/* maximum transmit size */
 	ETHERMAXTU	= 1514,		/* maximum transmit size */
 	ETHERHDRSIZE	= 14,		/* size of an ethernet header */
 	ETHERHDRSIZE	= 14,		/* size of an ethernet header */
@@ -161,6 +162,8 @@ typedef struct Type {
 	void	(*addconf)(int);
 	void	(*addconf)(int);
 	int	(*boot)(int, char*, Boot*);
 	int	(*boot)(int, char*, Boot*);
 	void	(*printdevs)(int);
 	void	(*printdevs)(int);
+	char**	parts;
+	char**	inis;
 	int	mask;
 	int	mask;
 	Medium*	media;
 	Medium*	media;
 } Type;
 } Type;
@@ -202,3 +205,4 @@ extern int	debug;
 extern Apminfo	apm;
 extern Apminfo	apm;
 extern char	*defaultpartition;
 extern char	*defaultpartition;
 extern int	iniread;
 extern int	iniread;
+extern int	pxe;

+ 0 - 341
sys/src/boot/pc/donprint.c

@@ -1,341 +0,0 @@
-#include	"u.h"
-#include	"lib.h"
-
-#define	PTR	sizeof(char*)
-#define	SHORT	sizeof(int)
-#define	INT	sizeof(int)
-#define	LONG	sizeof(long)
-#define	IDIGIT	30
-#define	MAXCON	30
-
-#define	FLONG	(1<<0)
-#define	FSHORT	(1<<1)
-#define	FUNSIGN	(1<<2)
-
-typedef struct Op	Op;
-struct Op
-{
-	char	*p;
-	char	*ep;
-	void	*argp;
-	int	f1;
-	int	f2;
-	int	f3;
-};
-
-static	int	noconv(Op*);
-static	int	cconv(Op*);
-static	int	dconv(Op*);
-static	int	hconv(Op*);
-static	int	lconv(Op*);
-static	int	oconv(Op*);
-static	int	sconv(Op*);
-static	int	uconv(Op*);
-static	int	xconv(Op*);
-static	int	Xconv(Op*);
-static	int	percent(Op*);
-static	int	pconv(Op*);
-
-static
-int	(*fmtconv[MAXCON])(Op*) =
-{
-	noconv,
-	cconv, dconv, hconv, lconv,
-	oconv, sconv, uconv, xconv,
-	Xconv, percent, pconv,
-};
-static
-char	fmtindex[128] =
-{
-	['c'] 1,
-	['d'] 2,
-	['h'] 3,
-	['l'] 4,
-	['o'] 5,
-	['s'] 6,
-	['u'] 7,
-	['x'] 8,
-	['X'] 9,
-	['%'] 10,
-	['p'] 11,
-};
-
-static	int	convcount  = { 12 };
-static	int	ucase;
-
-static void
-PUT(Op *o, int c)
-{
-	static int pos;
-	int opos;
-
-	if(c == '\t'){
-		opos = pos;
-		pos = (opos+8) & ~7;
-		while(opos++ < pos && o->p < o->ep)
-			*o->p++ = ' ';
-		return;
-	}
-	if(o->p < o->ep){
-		*o->p++ = c;
-		pos++;
-	}
-	if(c == '\n')
-		pos = 0;
-}
-
-int
-fmtinstall(char c, int (*f)(Op*))
-{
-
-	c &= 0177;
-	if(fmtindex[c] == 0) {
-		if(convcount >= MAXCON)
-			return 1;
-		fmtindex[c] = convcount++;
-	}
-	fmtconv[fmtindex[c]] = f;
-	return 0;
-}
-
-char*
-donprint(char *p, char *ep, char *fmt, void *argp)
-{
-	int sf1, c;
-	Op o;
-
-	o.p = p;
-	o.ep = ep;
-	o.argp = argp;
-
-loop:
-	c = *fmt++;
-	if(c != '%') {
-		if(c == 0) {
-			if(o.p < o.ep)
-				*o.p = 0;
-			return o.p;
-		}
-		PUT(&o, c);
-		goto loop;
-	}
-	o.f1 = 0;
-	o.f2 = -1;
-	o.f3 = 0;
-	c = *fmt++;
-	sf1 = 0;
-	if(c == '-') {
-		sf1 = 1;
-		c = *fmt++;
-	}
-	while(c >= '0' && c <= '9') {
-		o.f1 = o.f1*10 + c-'0';
-		c = *fmt++;
-	}
-	if(sf1)
-		o.f1 = -o.f1;
-	if(c != '.')
-		goto l1;
-	c = *fmt++;
-	while(c >= '0' && c <= '9') {
-		if(o.f2 < 0)
-			o.f2 = 0;
-		o.f2 = o.f2*10 + c-'0';
-		c = *fmt++;
-	}
-l1:
-	if(c == 0)
-		fmt--;
-	c = (*fmtconv[fmtindex[c&0177]])(&o);
-	if(c < 0) {
-		o.f3 |= -c;
-		c = *fmt++;
-		goto l1;
-	}
-	o.argp = (char*)o.argp + c;
-	goto loop;
-}
-
-void
-strconv(char *o, Op *op, int f1, int f2)
-{
-	int n, c;
-	char *p;
-
-	n = strlen(o);
-	if(f1 >= 0)
-		while(n < f1) {
-			PUT(op, ' ');
-			n++;
-		}
-	for(p=o; c = *p++;)
-		if(f2 != 0) {
-			PUT(op, c);
-			f2--;
-		}
-	if(f1 < 0) {
-		f1 = -f1;
-		while(n < f1) {
-			PUT(op, ' ');
-			n++;
-		}
-	}
-}
-
-int
-numbconv(Op *op, int base)
-{
-	char b[IDIGIT];
-	int i, f, n, r;
-	long v;
-	short h;
-
-	f = 0;
-	switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
-	case FLONG:
-		v = *(long*)op->argp;
-		r = LONG;
-		break;
-
-	case FUNSIGN|FLONG:
-		v = *(ulong*)op->argp;
-		r = LONG;
-		break;
-
-	case FSHORT:
-		h = *(int*)op->argp;
-		v = h;
-		r = SHORT;
-		break;
-
-	case FUNSIGN|FSHORT:
-		h = *(int*)op->argp;
-		v = (ushort)h;
-		r = SHORT;
-		break;
-
-	default:
-		v = *(int*)op->argp;
-		r = INT;
-		break;
-
-	case FUNSIGN:
-		v = *(unsigned*)op->argp;
-		r = INT;
-		break;
-	}
-	if(!(op->f3 & FUNSIGN) && v < 0) {
-		v = -v;
-		f = 1;
-	}
-	b[IDIGIT-1] = 0;
-	for(i = IDIGIT-2;; i--) {
-		n = (ulong)v % base;
-		n += '0';
-		if(n > '9'){
-			n += 'a' - ('9'+1);
-			if(ucase)
-				n += 'A'-'a';
-		}
-		b[i] = n;
-		if(i < 2)
-			break;
-		v = (ulong)v / base;
-		if(op->f2 >= 0 && i >= IDIGIT-op->f2)
-			continue;
-		if(v <= 0)
-			break;
-	}
-	if(f)
-		b[--i] = '-';
-	strconv(b+i, op, op->f1, -1);
-	return r;
-}
-
-static	int
-noconv(Op *op)
-{
-
-	strconv("***", op, 0, -1);
-	return 0;
-}
-
-static	int
-cconv(Op *op)
-{
-	char b[2];
-
-	b[0] = *(int*)op->argp;
-	b[1] = 0;
-	strconv(b, op, op->f1, -1);
-	return INT;
-}
-
-static	int
-dconv(Op *op)
-{
-	return numbconv(op, 10);
-}
-
-static	int
-hconv(Op*)
-{
-	return -FSHORT;
-}
-
-static	int
-lconv(Op*)
-{
-	return -FLONG;
-}
-
-static	int
-oconv(Op *op)
-{
-	return numbconv(op, 8);
-}
-
-static	int
-sconv(Op *op)
-{
-	strconv(*(char**)op->argp, op, op->f1, op->f2);
-	return PTR;
-}
-
-static	int
-uconv(Op*)
-{
-	return -FUNSIGN;
-}
-
-static	int
-xconv(Op *op)
-{
-	return numbconv(op, 16);
-}
-
-static	int
-pconv(Op *op)
-{
-	op->f3 |= FLONG|FUNSIGN;
-	return numbconv(op, 16);
-}
-
-static	int
-Xconv(Op *op)
-{
-	int r;
-
-	ucase = 1;
-	r = numbconv(op, 16);
-	ucase = 0;
-	return r;
-}
-
-static	int
-percent(Op *op)
-{
-
-	PUT(op, '%');
-	return 0;
-}

+ 30 - 4
sys/src/boot/pc/ether.c

@@ -4,6 +4,7 @@
 #include "dat.h"
 #include "dat.h"
 #include "fns.h"
 #include "fns.h"
 #include "io.h"
 #include "io.h"
+#include "ip.h"
 
 
 #include "etherif.h"
 #include "etherif.h"
 
 
@@ -12,6 +13,7 @@ static Ether ether[MaxEther];
 extern int ether2114xreset(Ether*);
 extern int ether2114xreset(Ether*);
 extern int elnk3reset(Ether*);
 extern int elnk3reset(Ether*);
 extern int i82557reset(Ether*);
 extern int i82557reset(Ether*);
+extern int igbepnp(Ether *);
 extern int elnk3reset(Ether*);
 extern int elnk3reset(Ether*);
 extern int ether589reset(Ether*);
 extern int ether589reset(Ether*);
 extern int ne2000reset(Ether*);
 extern int ne2000reset(Ether*);
@@ -30,6 +32,7 @@ struct {
 	{ "21140", ether2114xreset, 0, },
 	{ "21140", ether2114xreset, 0, },
 	{ "2114x", ether2114xreset, 0, },
 	{ "2114x", ether2114xreset, 0, },
 	{ "i82557", i82557reset, 0, },
 	{ "i82557", i82557reset, 0, },
+	{ "igbe",  igbepnp, 0, },
 	{ "elnk3", elnk3reset, 0, },
 	{ "elnk3", elnk3reset, 0, },
 	{ "3C509", elnk3reset, 0, },
 	{ "3C509", elnk3reset, 0, },
 	{ "3C575", elnk3reset, 0, },
 	{ "3C575", elnk3reset, 0, },
@@ -55,6 +58,8 @@ etherinit(void)
 	Ether *ctlr;
 	Ether *ctlr;
 	int ctlrno, i, mask, n, x;
 	int ctlrno, i, mask, n, x;
 
 
+	fmtinstall('E', eipfmt);
+
 	etherdetach = xetherdetach;
 	etherdetach = xetherdetach;
 	mask = 0;
 	mask = 0;
 	for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
 	for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
@@ -95,10 +100,7 @@ etherinit(void)
 				print(" addr 0x%luX", ctlr->mem & ~KZERO);
 				print(" addr 0x%luX", ctlr->mem & ~KZERO);
 			if(ctlr->size)
 			if(ctlr->size)
 				print(" size 0x%luX", ctlr->size);
 				print(" size 0x%luX", ctlr->size);
-			print(": ");
-			for(i = 0; i < sizeof(ctlr->ea); i++)
-				print("%2.2uX", ctlr->ea[i]);
-			print("\n");
+			print(": %E\n", ctlr->ea);
 		
 		
 			if(ctlr->nrb == 0)
 			if(ctlr->nrb == 0)
 				ctlr->nrb = Nrb;
 				ctlr->nrb = Nrb;
@@ -220,6 +222,30 @@ etherrxpkt(int ctlrno, Etherpkt* pkt, int timo)
 	return n;
 	return n;
 }
 }
 
 
+int
+etherrxflush(int ctlrno)
+{
+	int n;
+	Ether *ctlr;
+	RingBuf *ring;
+
+	if((ctlr = attach(ctlrno)) == 0)
+		return 0;
+
+	n = 0;
+	for(;;){
+		ring = &ctlr->rb[ctlr->rh];
+		if(wait(ring, Interface, 100) == 0)
+			break;
+
+		ring->owner = Interface;
+		ctlr->rh = NEXT(ctlr->rh, ctlr->nrb);
+		n++;
+	}
+
+	return n;
+}
+
 int
 int
 ethertxpkt(int ctlrno, Etherpkt* pkt, int len, int)
 ethertxpkt(int ctlrno, Etherpkt* pkt, int len, int)
 {
 {

+ 1623 - 0
sys/src/boot/pc/etherigbe.c

@@ -0,0 +1,1623 @@
+/*
+ * bootstrap driver for
+ * Intel RS-82543GC Gigabit Ethernet Controller
+ * as found on the Intel PRO/1000[FT] Server Adapter.
+ * The older non-[FT] cards use the 82542 (LSI L2A1157) chip; no attempt
+ * is made to handle the older chip although it should be possible.
+ *
+ * updated just enough to cope with the
+ * Intel 8254[340]NN Gigabit Ethernet Controller
+ * as found on the Intel PRO/1000 series of adapters:
+ *	82543GC	Intel PRO/1000 T
+ *	82544EI Intel PRO/1000 XT
+ *	82540EM Intel PRO/1000 MT
+ *
+ * The datasheet is not very clear about running on a big-endian system
+ * and this driver assumes little-endian throughout.
+ * To do:
+ *	GMII/MII
+ *	check recovery from receive no buffers condition
+ *	automatic ett adjustment
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+#include "ethermii.h"
+
+/* compatibility with cpu kernels */
+#define iallocb allocb
+#ifndef CACHELINESZ
+#define CACHELINESZ	32		/* pentium & later */
+#endif
+
+/* from pci.c */
+enum
+{					/* command register (pcidev->pcr) */
+	IOen		= (1<<0),
+	MEMen		= (1<<1),
+	MASen		= (1<<2),
+	MemWrInv	= (1<<4),
+	PErrEn		= (1<<6),
+	SErrEn		= (1<<8),
+};
+enum {
+	Ctrl		= 0x00000000,	/* Device Control */
+	Status		= 0x00000008,	/* Device Status */
+	Eecd		= 0x00000010,	/* EEPROM/Flash Control/Data */
+	Ctrlext		= 0x00000018,	/* Extended Device Control */
+	Mdic		= 0x00000020,	/* MDI Control */
+	Fcal		= 0x00000028,	/* Flow Control Address Low */
+	Fcah		= 0x0000002C,	/* Flow Control Address High */
+	Fct		= 0x00000030,	/* Flow Control Type */
+	Icr		= 0x000000C0,	/* Interrupt Cause Read */
+	Ics		= 0x000000C8,	/* Interrupt Cause Set */
+	Ims		= 0x000000D0,	/* Interrupt Mask Set/Read */
+	Imc		= 0x000000D8,	/* Interrupt mask Clear */
+	Rctl		= 0x00000100,	/* Receive Control */
+	Fcttv		= 0x00000170,	/* Flow Control Transmit Timer Value */
+	Txcw		= 0x00000178,	/* Transmit Configuration Word */
+	Tctl		= 0x00000400,	/* Transmit Control */
+	Tipg		= 0x00000410,	/* Transmit IPG */
+	Tbt		= 0x00000448,	/* Transmit Burst Timer */
+	Ait		= 0x00000458,	/* Adaptive IFS Throttle */
+	Fcrtl		= 0x00002160,	/* Flow Control RX Threshold Low */
+	Fcrth		= 0x00002168,	/* Flow Control Rx Threshold High */
+	Rdbal		= 0x00002800,	/* Rdesc Base Address Low */
+	Rdbah		= 0x00002804,	/* Rdesc Base Address High */
+	Rdlen		= 0x00002808,	/* Receive Descriptor Length */
+	Rdh		= 0x00002810,	/* Receive Descriptor Head */
+	Rdt		= 0x00002818,	/* Receive Descriptor Tail */
+	Rdtr		= 0x00002820,	/* Receive Descriptor Timer Ring */
+	Rxdctl		= 0x00002828,	/* Receive Descriptor Control */
+	Radv		= 0x0000282C,	/* Receive Interrupt Absolute Delay Timer */
+	Txdmac		= 0x00003000,	/* Transfer DMA Control */
+	Ett		= 0x00003008,	/* Early Transmit Control */
+	Tdbal		= 0x00003800,	/* Tdesc Base Address Low */
+	Tdbah		= 0x00003804,	/* Tdesc Base Address High */
+	Tdlen		= 0x00003808,	/* Transmit Descriptor Length */
+	Tdh		= 0x00003810,	/* Transmit Descriptor Head */
+	Tdt		= 0x00003818,	/* Transmit Descriptor Tail */
+	Tidv		= 0x00003820,	/* Transmit Interrupt Delay Value */
+	Txdctl		= 0x00003828,	/* Transmit Descriptor Control */
+	Tadv		= 0x0000382C,	/* Transmit Interrupt Absolute Delay Timer */
+
+	Statistics	= 0x00004000,	/* Start of Statistics Area */
+	Gorcl		= 0x88/4,	/* Good Octets Received Count */
+	Gotcl		= 0x90/4,	/* Good Octets Transmitted Count */
+	Torl		= 0xC0/4,	/* Total Octets Received */
+	Totl		= 0xC8/4,	/* Total Octets Transmitted */
+	Nstatistics	= 64,
+
+	Rxcsum		= 0x00005000,	/* Receive Checksum Control */
+	Mta		= 0x00005200,	/* Multicast Table Array */
+	Ral		= 0x00005400,	/* Receive Address Low */
+	Rah		= 0x00005404,	/* Receive Address High */
+	Manc		= 0x00005820,	/* Management Control */
+};
+
+enum {					/* Ctrl */
+	Bem		= 0x00000002,	/* Big Endian Mode */
+	Prior		= 0x00000004,	/* Priority on the PCI bus */
+	Lrst		= 0x00000008,	/* Link Reset */
+	Asde		= 0x00000020,	/* Auto-Speed Detection Enable */
+	Slu		= 0x00000040,	/* Set Link Up */
+	Ilos		= 0x00000080,	/* Invert Loss of Signal (LOS) */
+	SspeedMASK	= 0x00000300,	/* Speed Selection */
+	SspeedSHIFT	= 8,
+	Sspeed10	= 0x00000000,	/* 10Mb/s */
+	Sspeed100	= 0x00000100,	/* 100Mb/s */
+	Sspeed1000	= 0x00000200,	/* 1000Mb/s */
+	Frcspd		= 0x00000800,	/* Force Speed */
+	Frcdplx		= 0x00001000,	/* Force Duplex */
+	SwdpinsloMASK	= 0x003C0000,	/* Software Defined Pins - lo nibble */
+	SwdpinsloSHIFT	= 18,
+	SwdpioloMASK	= 0x03C00000,	/* Software Defined Pins - I or O */
+	SwdpioloSHIFT	= 22,
+	Devrst		= 0x04000000,	/* Device Reset */
+	Rfce		= 0x08000000,	/* Receive Flow Control Enable */
+	Tfce		= 0x10000000,	/* Transmit Flow Control Enable */
+	Vme		= 0x40000000,	/* VLAN Mode Enable */
+};
+
+enum {					/* Status */
+	Lu		= 0x00000002,	/* Link Up */
+	Tckok		= 0x00000004,	/* Transmit clock is running */
+	Rbcok		= 0x00000008,	/* Receive clock is running */
+	Txoff		= 0x00000010,	/* Transmission Paused */
+	Tbimode		= 0x00000020,	/* TBI Mode Indication */
+	SpeedMASK	= 0x000000C0,
+	Speed10		= 0x00000000,	/* 10Mb/s */
+	Speed100	= 0x00000040,	/* 100Mb/s */
+	Speed1000	= 0x00000080,	/* 1000Mb/s */
+	Mtxckok		= 0x00000400,	/* MTX clock is running */
+	Pci66		= 0x00000800,	/* PCI Bus speed indication */
+	Bus64		= 0x00001000,	/* PCI Bus width indication */
+};
+
+enum {					/* Ctrl and Status */
+	Fd		= 0x00000001,	/* Full-Duplex */
+	AsdvMASK	= 0x00000300,
+	Asdv10		= 0x00000000,	/* 10Mb/s */
+	Asdv100		= 0x00000100,	/* 100Mb/s */
+	Asdv1000	= 0x00000200,	/* 1000Mb/s */
+};
+
+enum {					/* Eecd */
+	Sk		= 0x00000001,	/* Clock input to the EEPROM */
+	Cs		= 0x00000002,	/* Chip Select */
+	Di		= 0x00000004,	/* Data Input to the EEPROM */
+	Do		= 0x00000008,	/* Data Output from the EEPROM */
+	Areq		= 0x00000040,	/* EEPROM Access Request */
+	Agnt		= 0x00000080,	/* EEPROM Access Grant */
+	Eesz256		= 0x00000200,	/* EEPROM is 256 words not 64 */
+	Spi		= 0x00002000,	/* EEPROM is SPI not Microwire */
+};
+
+enum {					/* Ctrlext */
+	Gpien		= 0x0000000F,	/* General Purpose Interrupt Enables */
+	SwdpinshiMASK	= 0x000000F0,	/* Software Defined Pins - hi nibble */
+	SwdpinshiSHIFT	= 4,
+	SwdpiohiMASK	= 0x00000F00,	/* Software Defined Pins - I or O */
+	SwdpiohiSHIFT	= 8,
+	Asdchk		= 0x00001000,	/* ASD Check */
+	Eerst		= 0x00002000,	/* EEPROM Reset */
+	Ips		= 0x00004000,	/* Invert Power State */
+	Spdbyps		= 0x00008000,	/* Speed Select Bypass */
+};
+
+enum {					/* EEPROM content offsets */
+	Ea		= 0x00,		/* Ethernet Address */
+	Cf		= 0x03,		/* Compatibility Field */
+	Pba		= 0x08,		/* Printed Board Assembly number */
+	Icw1		= 0x0A,		/* Initialization Control Word 1 */
+	Sid		= 0x0B,		/* Subsystem ID */
+	Svid		= 0x0C,		/* Subsystem Vendor ID */
+	Did		= 0x0D,		/* Device ID */
+	Vid		= 0x0E,		/* Vendor ID */
+	Icw2		= 0x0F,		/* Initialization Control Word 2 */
+};
+
+enum {					/* Mdic */
+	MDIdMASK	= 0x0000FFFF,	/* Data */
+	MDIdSHIFT	= 0,
+	MDIrMASK	= 0x001F0000,	/* PHY Register Address */
+	MDIrSHIFT	= 16,
+	MDIpMASK	= 0x03E00000,	/* PHY Address */
+	MDIpSHIFT	= 21,
+	MDIwop		= 0x04000000,	/* Write Operation */
+	MDIrop		= 0x08000000,	/* Read Operation */
+	MDIready	= 0x10000000,	/* End of Transaction */
+	MDIie		= 0x20000000,	/* Interrupt Enable */
+	MDIe		= 0x40000000,	/* Error */
+};
+
+enum {					/* Icr, Ics, Ims, Imc */
+	Txdw		= 0x00000001,	/* Transmit Descriptor Written Back */
+	Txqe		= 0x00000002,	/* Transmit Queue Empty */
+	Lsc		= 0x00000004,	/* Link Status Change */
+	Rxseq		= 0x00000008,	/* Receive Sequence Error */
+	Rxdmt0		= 0x00000010,	/* Rdesc Minimum Threshold Reached */
+	Rxo		= 0x00000040,	/* Receiver Overrun */
+	Rxt0		= 0x00000080,	/* Receiver Timer Interrupt */
+	Mdac		= 0x00000200,	/* MDIO Access Completed */
+	Rxcfg		= 0x00000400,	/* Receiving /C/ ordered sets */
+	Gpi0		= 0x00000800,	/* General Purpose Interrupts */
+	Gpi1		= 0x00001000,
+	Gpi2		= 0x00002000,
+	Gpi3		= 0x00004000,
+};
+
+/*
+ * The Mdic register isn't implemented on the 82543GC,
+ * the software defined pins are used instead.
+ * These definitions work for the Intel PRO/1000 T Server Adapter.
+ * The direction pin bits are read from the EEPROM.
+ */
+enum {
+	Mdd		= ((1<<2)<<SwdpinsloSHIFT),	/* data */
+	Mddo		= ((1<<2)<<SwdpioloSHIFT),	/* pin direction */
+	Mdc		= ((1<<3)<<SwdpinsloSHIFT),	/* clock */
+	Mdco		= ((1<<3)<<SwdpioloSHIFT),	/* pin direction */
+	Mdr		= ((1<<0)<<SwdpinshiSHIFT),	/* reset */
+	Mdro		= ((1<<0)<<SwdpiohiSHIFT),	/* pin direction */
+};
+
+enum {					/* Txcw */
+	TxcwFd		= 0x00000020,	/* Full Duplex */
+	TxcwHd		= 0x00000040,	/* Half Duplex */
+	TxcwPauseMASK	= 0x00000180,	/* Pause */
+	TxcwPauseSHIFT	= 7,
+	TxcwPs		= (1<<TxcwPauseSHIFT),	/* Pause Supported */
+	TxcwAs		= (2<<TxcwPauseSHIFT),	/* Asymmetric FC desired */
+	TxcwRfiMASK	= 0x00003000,	/* Remote Fault Indication */
+	TxcwRfiSHIFT	= 12,
+	TxcwNpr		= 0x00008000,	/* Next Page Request */
+	TxcwConfig	= 0x40000000,	/* Transmit COnfig Control */
+	TxcwAne		= 0x80000000,	/* Auto-Negotiation Enable */
+};
+
+enum {					/* Rctl */
+	Rrst		= 0x00000001,	/* Receiver Software Reset */
+	Ren		= 0x00000002,	/* Receiver Enable */
+	Sbp		= 0x00000004,	/* Store Bad Packets */
+	Upe		= 0x00000008,	/* Unicast Promiscuous Enable */
+	Mpe		= 0x00000010,	/* Multicast Promiscuous Enable */
+	Lpe		= 0x00000020,	/* Long Packet Reception Enable */
+	LbmMASK		= 0x000000C0,	/* Loopback Mode */
+	LbmOFF		= 0x00000000,	/* No Loopback */
+	LbmTBI		= 0x00000040,	/* TBI Loopback */
+	LbmMII		= 0x00000080,	/* GMII/MII Loopback */
+	LbmXCVR		= 0x000000C0,	/* Transceiver Loopback */
+	RdtmsMASK	= 0x00000300,	/* Rdesc Minimum Threshold Size */
+	RdtmsHALF	= 0x00000000,	/* Threshold is 1/2 Rdlen */
+	RdtmsQUARTER	= 0x00000100,	/* Threshold is 1/4 Rdlen */
+	RdtmsEIGHTH	= 0x00000200,	/* Threshold is 1/8 Rdlen */
+	MoMASK		= 0x00003000,	/* Multicast Offset */
+	Bam		= 0x00008000,	/* Broadcast Accept Mode */
+	BsizeMASK	= 0x00030000,	/* Receive Buffer Size */
+	Bsize2048	= 0x00000000,
+	Bsize1024	= 0x00010000,
+	Bsize512	= 0x00020000,
+	Bsize256	= 0x00030000,
+	Vfe		= 0x00040000,	/* VLAN Filter Enable */
+	Cfien		= 0x00080000,	/* Canonical Form Indicator Enable */
+	Cfi		= 0x00100000,	/* Canonical Form Indicator value */
+	Dpf		= 0x00400000,	/* Discard Pause Frames */
+	Pmcf		= 0x00800000,	/* Pass MAC Control Frames */
+	Bsex		= 0x02000000,	/* Buffer Size Extension */
+	Secrc		= 0x04000000,	/* Strip CRC from incoming packet */
+};
+
+enum {					/* Tctl */
+	Trst		= 0x00000001,	/* Transmitter Software Reset */
+	Ten		= 0x00000002,	/* Transmit Enable */
+	Psp		= 0x00000008,	/* Pad Short Packets */
+	CtMASK		= 0x00000FF0,	/* Collision Threshold */
+	CtSHIFT		= 4,
+	ColdMASK	= 0x003FF000,	/* Collision Distance */
+	ColdSHIFT	= 12,
+	Swxoff		= 0x00400000,	/* Sofware XOFF Transmission */
+	Pbe		= 0x00800000,	/* Packet Burst Enable */
+	Rtlc		= 0x01000000,	/* Re-transmit on Late Collision */
+	Nrtu		= 0x02000000,	/* No Re-transmit on Underrrun */
+};
+
+enum {					/* [RT]xdctl */
+	PthreshMASK	= 0x0000003F,	/* Prefetch Threshold */
+	PthreshSHIFT	= 0,
+	HthreshMASK	= 0x00003F00,	/* Host Threshold */
+	HthreshSHIFT	= 8,
+	WthreshMASK	= 0x003F0000,	/* Writebacj Threshold */
+	WthreshSHIFT	= 16,
+	Gran		= 0x01000000,	/* Granularity */
+};
+
+enum {					/* Rxcsum */
+	PcssMASK	= 0x000000FF,	/* Packet Checksum Start */
+	PcssSHIFT	= 0,
+	Ipofl		= 0x00000100,	/* IP Checksum Off-load Enable */
+	Tuofl		= 0x00000200,	/* TCP/UDP Checksum Off-load Enable */
+};
+
+enum {					/* Manc */
+	Arpen		= 0x00002000,	/* Enable ARP Request Filtering */
+};
+
+typedef struct Rdesc {			/* Receive Descriptor */
+	uint	addr[2];
+	ushort	length;
+	ushort	checksum;
+	uchar	status;
+	uchar	errors;
+	ushort	special;
+} Rdesc;
+
+enum {					/* Rdesc status */
+	Rdd		= 0x01,		/* Descriptor Done */
+	Reop		= 0x02,		/* End of Packet */
+	Ixsm		= 0x04,		/* Ignore Checksum Indication */
+	Vp		= 0x08,		/* Packet is 802.1Q (matched VET) */
+	Tcpcs		= 0x20,		/* TCP Checksum Calculated on Packet */
+	Ipcs		= 0x40,		/* IP Checksum Calculated on Packet */
+	Pif		= 0x80,		/* Passed in-exact filter */
+};
+
+enum {					/* Rdesc errors */
+	Ce		= 0x01,		/* CRC Error or Alignment Error */
+	Se		= 0x02,		/* Symbol Error */
+	Seq		= 0x04,		/* Sequence Error */
+	Cxe		= 0x10,		/* Carrier Extension Error */
+	Tcpe		= 0x20,		/* TCP/UDP Checksum Error */
+	Ipe		= 0x40,		/* IP Checksum Error */
+	Rxe		= 0x80,		/* RX Data Error */
+};
+
+typedef struct Tdesc {			/* Legacy+Normal Transmit Descriptor */
+	uint	addr[2];
+	uint	control;		/* varies with descriptor type */
+	uint	status;			/* varies with descriptor type */
+} Tdesc;
+
+enum {					/* Tdesc control */
+	LenMASK		= 0x000FFFFF,	/* Data/Packet Length Field */
+	LenSHIFT	= 0,
+	DtypeCD		= 0x00000000,	/* Data Type 'Context Descriptor' */
+	DtypeDD		= 0x00100000,	/* Data Type 'Data Descriptor' */
+	PtypeTCP	= 0x01000000,	/* TCP/UDP Packet Type (CD) */
+	Teop		= 0x01000000,	/* End of Packet (DD) */
+	PtypeIP		= 0x02000000,	/* IP Packet Type (CD) */
+	Ifcs		= 0x02000000,	/* Insert FCS (DD) */
+	Tse		= 0x04000000,	/* TCP Segmentation Enable */
+	Rs		= 0x08000000,	/* Report Status */
+	Rps		= 0x10000000,	/* Report Status Sent */
+	Dext		= 0x20000000,	/* Descriptor Extension */
+	Vle		= 0x40000000,	/* VLAN Packet Enable */
+	Ide		= 0x80000000,	/* Interrupt Delay Enable */
+};
+
+enum {					/* Tdesc status */
+	Tdd		= 0x00000001,	/* Descriptor Done */
+	Ec		= 0x00000002,	/* Excess Collisions */
+	Lc		= 0x00000004,	/* Late Collision */
+	Tu		= 0x00000008,	/* Transmit Underrun */
+	CssMASK		= 0x0000FF00,	/* Checksum Start Field */
+	CssSHIFT	= 8,
+};
+
+enum {
+	Nrdesc		= 128,		/* multiple of 8 */
+	Ntdesc		= 128,		/* multiple of 8 */
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+	int	port;
+	Pcidev*	pcidev;
+	Ctlr*	next;
+	int	active;
+	int	id;
+	int	cls;
+	ushort	eeprom[0x40];
+
+	int*	nic;
+	Lock	imlock;
+	int	im;			/* interrupt mask */
+
+	Mii*	mii;
+
+	Lock	slock;
+	uint	statistics[Nstatistics];
+
+	uchar	ra[Eaddrlen];		/* receive address */
+	ulong	mta[128];		/* multicast table array */
+
+	Rdesc*	rdba;			/* receive descriptor base address */
+	Block**	rb;			/* receive buffers */
+	int	rdh;			/* receive descriptor head */
+	int	rdt;			/* receive descriptor tail */
+
+	Tdesc*	tdba;			/* transmit descriptor base address */
+	Lock	tdlock;
+	Block**	tb;			/* transmit buffers */
+	int	tdh;			/* transmit descriptor head */
+	int	tdt;			/* transmit descriptor tail */
+	int	ett;			/* early transmit threshold */
+
+	int	txcw;
+	int	fcrtl;
+	int	fcrth;
+
+	/* bootstrap goo */
+	Block*	bqhead;	/* transmission queue */
+	Block*	bqtail;
+} Ctlr;
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+#define csr32r(c, r)	(*((c)->nic+((r)/4)))
+#define csr32w(c, r, v)	(*((c)->nic+((r)/4)) = (v))
+
+static void
+igbeim(Ctlr* ctlr, int im)
+{
+	ilock(&ctlr->imlock);
+	ctlr->im |= im;
+	csr32w(ctlr, Ims, ctlr->im);
+	iunlock(&ctlr->imlock);
+}
+
+static void
+igbeattach(Ether* edev)
+{
+	int ctl;
+	Ctlr *ctlr;
+
+	/*
+	 * To do here:
+	 *	one-time stuff;
+	 *	start off a kproc for link status change:
+	 *		adjust queue length depending on speed;
+	 *		flow control.
+	 *	more needed here...
+	 */
+	ctlr = edev->ctlr;
+	igbeim(ctlr, 0);
+	ctl = csr32r(ctlr, Rctl)|Ren;
+	csr32w(ctlr, Rctl, ctl);
+	ctl = csr32r(ctlr, Tctl)|Ten;
+	csr32w(ctlr, Tctl, ctl);
+}
+
+static char* statistics[Nstatistics] = {
+	"CRC Error",
+	"Alignment Error",
+	"Symbol Error",
+	"RX Error",
+	"Missed Packets",
+	"Single Collision",
+	"Excessive Collisions",
+	"Multiple Collision",
+	"Late Collisions",
+	nil,
+	"Collision",
+	"Transmit Underrun",
+	"Defer",
+	"Transmit - No CRS",
+	"Sequence Error",
+	"Carrier Extension Error",
+	"Receive Error Length",
+	nil,
+	"XON Received",
+	"XON Transmitted",
+	"XOFF Received",
+	"XOFF Transmitted",
+	"FC Received Unsupported",
+	"Packets Received (64 Bytes)",
+	"Packets Received (65-127 Bytes)",
+	"Packets Received (128-255 Bytes)",
+	"Packets Received (256-511 Bytes)",
+	"Packets Received (512-1023 Bytes)",
+	"Packets Received (1024-1522 Bytes)",
+	"Good Packets Received",
+	"Broadcast Packets Received",
+	"Multicast Packets Received",
+	"Good Packets Transmitted",
+	nil,
+	"Good Octets Received",
+	nil,
+	"Good Octets Transmitted",
+	nil,
+	nil,
+	nil,
+	"Receive No Buffers",
+	"Receive Undersize",
+	"Receive Fragment",
+	"Receive Oversize",
+	"Receive Jabber",
+	nil,
+	nil,
+	nil,
+	"Total Octets Received",
+	nil,
+	"Total Octets Transmitted",
+	nil,
+	"Total Packets Received",
+	"Total Packets Transmitted",
+	"Packets Transmitted (64 Bytes)",
+	"Packets Transmitted (65-127 Bytes)",
+	"Packets Transmitted (128-255 Bytes)",
+	"Packets Transmitted (256-511 Bytes)",
+	"Packets Transmitted (512-1023 Bytes)",
+	"Packets Transmitted (1024-1522 Bytes)",
+	"Multicast Packets Transmitted",
+	"Broadcast Packets Transmitted",
+	"TCP Segmentation Context Transmitted",
+	"TCP Segmentation Context Fail",
+};
+
+static void
+txstart(Ether *edev)
+{
+	int tdh, tdt, len, olen;
+	Ctlr *ctlr = edev->ctlr;
+	Block *bp;
+	Tdesc *tdesc;
+
+	/*
+	 * Try to fill the ring back up, moving buffers from the transmit q.
+	 */
+	tdh = PREV(ctlr->tdh, Ntdesc);
+	for(tdt = ctlr->tdt; tdt != tdh; tdt = NEXT(tdt, Ntdesc)){
+		/* pull off the head of the transmission queue */
+		if((bp = ctlr->bqhead) == nil)		/* was qget(edev->oq) */
+			break;
+		ctlr->bqhead = bp->next;
+		if (ctlr->bqtail == bp)
+			ctlr->bqtail = nil;
+		len = olen = BLEN(bp);
+
+		/*
+		 * if packet is too short, make it longer rather than relying
+		 * on ethernet interface to pad it and complain so the caller
+		 * will get fixed.  I don't think Psp is working right, or it's
+		 * getting cleared.
+		 */
+		if (len < ETHERMINTU) {
+			if (bp->rp + ETHERMINTU <= bp->lim)
+				bp->wp = bp->rp + ETHERMINTU;
+			else
+				bp->wp = bp->lim;
+			len = BLEN(bp);
+			print("txstart: extended short pkt %d -> %d bytes\n",
+				olen, len);
+		}
+
+		/* set up a descriptor for it */
+		tdesc = &ctlr->tdba[tdt];
+		tdesc->addr[0] = PCIWADDR(bp->rp);
+		tdesc->addr[1] = 0;
+		tdesc->control = /* Ide| */ Rs|Dext|Ifcs|Teop|DtypeDD|len;
+		tdesc->status = 0;
+
+		ctlr->tb[tdt] = bp;
+	}
+	ctlr->tdt = tdt;
+	csr32w(ctlr, Tdt, tdt);
+	igbeim(ctlr, Txdw);
+}
+
+static Block *
+fromringbuf(Ether *ether)
+{
+	RingBuf *tb = &ether->tb[ether->ti];
+	Block *bp = allocb(tb->len);
+
+	memmove(bp->wp, tb->pkt, tb->len);
+	memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
+	bp->wp += tb->len;
+	return bp;
+}
+
+static void
+igbetransmit(Ether* edev)
+{
+	Block *bp;
+	Ctlr *ctlr;
+	Tdesc *tdesc;
+	RingBuf *tb;
+	int tdh;
+
+	/*
+	 * For now there are no smarts here. Tuning comes later.
+	 */
+	ctlr = edev->ctlr;
+	ilock(&ctlr->tdlock);
+
+	/*
+	 * Free any completed packets
+	 * - try to get the soft tdh to catch the tdt;
+	 * - if the packet had an underrun bump the threshold
+	 *   - the Tu bit doesn't seem to ever be set, perhaps
+	 *     because Rs mode is used?
+	 */
+	tdh = ctlr->tdh;
+	for(;;){
+		tdesc = &ctlr->tdba[tdh];
+		if(!(tdesc->status & Tdd))
+			break;
+		if(tdesc->status & Tu){
+			ctlr->ett++;
+			csr32w(ctlr, Ett, ctlr->ett);
+		}
+		tdesc->status = 0;
+		if(ctlr->tb[tdh] != nil){
+			freeb(ctlr->tb[tdh]);
+			ctlr->tb[tdh] = nil;
+		}
+		tdh = NEXT(tdh, Ntdesc);
+	}
+	ctlr->tdh = tdh;
+
+	/* copy packets from the software RingBuf to the transmission q */
+	/* from boot ether83815.c */
+	while((tb = &edev->tb[edev->ti])->owner == Interface){
+		bp = fromringbuf(edev);
+
+		/* put the buffer on the transmit queue */
+		if(ctlr->bqhead)
+			ctlr->bqtail->next = bp;
+		else
+			ctlr->bqhead = bp;
+		ctlr->bqtail = bp;
+
+		txstart(edev);		/* kick transmitter */
+		tb->owner = Host;	/* give descriptor back */
+
+		edev->ti = NEXT(edev->ti, edev->ntb);
+	}
+
+	iunlock(&ctlr->tdlock);
+}
+
+static void
+igbereplenish(Ctlr* ctlr)
+{
+	int rdt;
+	Block *bp;
+	Rdesc *rdesc;
+
+	rdt = ctlr->rdt;
+	while(NEXT(rdt, Nrdesc) != ctlr->rdh){
+		rdesc = &ctlr->rdba[rdt];
+		if(ctlr->rb[rdt] != nil){
+			/* nothing to do */
+		}
+		else if((bp = iallocb(2048)) != nil){
+			ctlr->rb[rdt] = bp;
+			rdesc->addr[0] = PCIWADDR(bp->rp);
+			rdesc->addr[1] = 0;
+		}
+		else
+			break;
+		rdesc->status = 0;
+
+		rdt = NEXT(rdt, Nrdesc);
+	}
+	ctlr->rdt = rdt;
+	csr32w(ctlr, Rdt, rdt);
+}
+
+static void
+toringbuf(Ether *ether, Block *bp)
+{
+	RingBuf *rb = &ether->rb[ether->ri];
+
+	if (rb->owner == Interface) {
+		rb->len = BLEN(bp);
+		memmove(rb->pkt, bp->rp, rb->len);
+		rb->owner = Host;
+		ether->ri = NEXT(ether->ri, ether->nrb);
+	}
+	/* else no one is expecting packets from the network */
+}
+
+static void
+igbeinterrupt(Ureg*, void* arg)
+{
+	Block *bp;
+	Ctlr *ctlr;
+	Ether *edev;
+	Rdesc *rdesc;
+	int icr, im, rdh, txdw = 0;
+
+	edev = arg;
+	ctlr = edev->ctlr;
+
+	ilock(&ctlr->imlock);
+	csr32w(ctlr, Imc, ~0);
+	im = ctlr->im;
+
+	for(icr = csr32r(ctlr, Icr); icr & ctlr->im; icr = csr32r(ctlr, Icr)){
+		/*
+		 * Link status changed.
+		 */
+		if(icr & (Rxseq|Lsc)){
+			/*
+			 * More here...
+			 */
+		}
+
+		/*
+		 * Process any received packets.
+		 */
+		rdh = ctlr->rdh;
+		for(;;){
+			rdesc = &ctlr->rdba[rdh];
+			if(!(rdesc->status & Rdd))
+				break;
+			if ((rdesc->status & Reop) && rdesc->errors == 0) {
+				bp = ctlr->rb[rdh];
+				ctlr->rb[rdh] = nil;
+				/*
+				 * it appears that the original 82543 needed
+				 * to have the Ethernet CRC excluded, but that
+				 * the newer chips do not?
+				 */
+				bp->wp += rdesc->length /* -4 */;
+				toringbuf(edev, bp);
+				freeb(bp);
+			} else if ((rdesc->status & Reop) && rdesc->errors)
+				print("igbe: input packet error 0x%ux\n",
+					rdesc->errors);
+			rdesc->status = 0;
+			rdh = NEXT(rdh, Nrdesc);
+		}
+		ctlr->rdh = rdh;
+
+		if(icr & Rxdmt0)
+			igbereplenish(ctlr);
+		if(icr & Txdw){
+			im &= ~Txdw;
+			txdw++;
+		}
+	}
+
+	ctlr->im = im;
+	csr32w(ctlr, Ims, im);
+	iunlock(&ctlr->imlock);
+
+	if(txdw)
+		igbetransmit(edev);
+}
+
+static int
+igbeinit(Ether* edev)
+{
+	int csr, i, r, ctrl;
+	MiiPhy *phy;
+	Ctlr *ctlr;
+
+	ctlr = edev->ctlr;
+
+	/*
+	 * Set up the receive addresses.
+	 * There are 16 addresses. The first should be the MAC address.
+	 * The others are cleared and not marked valid (MS bit of Rah).
+	 */
+	csr = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0];
+	csr32w(ctlr, Ral, csr);
+	csr = 0x80000000|(edev->ea[5]<<8)|edev->ea[4];
+	csr32w(ctlr, Rah, csr);
+	for(i = 1; i < 16; i++){
+		csr32w(ctlr, Ral+i*8, 0);
+		csr32w(ctlr, Rah+i*8, 0);
+	}
+
+	/*
+	 * Clear the Multicast Table Array.
+	 * It's a 4096 bit vector accessed as 128 32-bit registers.
+	 */
+	for(i = 0; i < 128; i++)
+		csr32w(ctlr, Mta+i*4, 0);
+
+	/*
+	 * Receive initialisation.
+	 * Mostly defaults from the datasheet, will
+	 * need some tuning for performance:
+	 *	Rctl	descriptor mimimum threshold size
+	 *		discard pause frames
+	 *		strip CRC
+	 * 	Rdtr	interrupt delay
+	 * 	Rxdctl	all the thresholds
+	 */
+	csr32w(ctlr, Rctl, 0);
+
+	/*
+	 * Allocate the descriptor ring and load its
+	 * address and length into the NIC.
+	 */
+	ctlr->rdba = xspanalloc(Nrdesc*sizeof(Rdesc), 128 /* was 16 */, 0);
+	csr32w(ctlr, Rdbal, PCIWADDR(ctlr->rdba));
+	csr32w(ctlr, Rdbah, 0);
+	csr32w(ctlr, Rdlen, Nrdesc*sizeof(Rdesc));
+
+	/*
+	 * Initialise the ring head and tail pointers and
+	 * populate the ring with Blocks.
+	 * The datasheet says the tail pointer is set to beyond the last
+	 * descriptor hardware can process, which implies the initial
+	 * condition is Rdh == Rdt. However, experience shows Rdt must
+	 * always be 'behind' Rdh; the replenish routine ensures this.
+	 */
+	ctlr->rdh = 0;
+	csr32w(ctlr, Rdh, ctlr->rdh);
+	ctlr->rdt = 0;
+	csr32w(ctlr, Rdt, ctlr->rdt);
+	ctlr->rb = malloc(sizeof(Block*)*Nrdesc);
+	igbereplenish(ctlr);
+
+	/*
+	 * Set up Rctl but don't enable receiver (yet).
+	 */
+	csr32w(ctlr, Rdtr, 0);
+	switch(ctlr->id){
+	case (0x100E<<16)|0x8086:		/* 82540EM */
+	case (0x101E<<16)|0x8086:		/* 82540EPLP */
+		csr32w(ctlr, Radv, 64);
+		break;
+	}
+	csr32w(ctlr, Rxdctl, (8<<WthreshSHIFT)|(8<<HthreshSHIFT)|4);
+	/*
+	 * Enable checksum offload.
+	 */
+	csr32w(ctlr, Rxcsum, Tuofl|Ipofl|(ETHERHDRSIZE<<PcssSHIFT));
+
+	csr32w(ctlr, Rctl, Dpf|Bsize2048|Bam|RdtmsHALF);
+	igbeim(ctlr, Rxt0|Rxo|Rxdmt0|Rxseq);
+
+	/*
+	 * Transmit initialisation.
+	 * Mostly defaults from the datasheet, will
+	 * need some tuning for performance. The normal mode will
+	 * be full-duplex and things to tune for half-duplex are
+	 *	Tctl	re-transmit on late collision
+	 *	Tipg	all IPG times
+	 *	Tbt	burst timer
+	 *	Ait	adaptive IFS throttle
+	 * and in general
+	 *	Txdmac	packet prefetching
+	 *	Ett	transmit early threshold
+	 *	Tidv	interrupt delay value
+	 *	Txdctl	all the thresholds
+	 */
+	csr32w(ctlr, Tctl, (0x0F<<CtSHIFT)|Psp|(66<<ColdSHIFT));	/* Fd */
+	switch(ctlr->id){
+	default:
+		r = 6;
+		break;
+	case (0x1004<<16)|0x8086:	/* 82543GC */
+	case (0x1008<<16)|0x8086:	/* 82544EI */
+	case (0x100E<<16)|0x8086:	/* 82440EM */
+	case (0x101E<<16)|0x8086:	/* 82540EPLP */
+		r = 8;
+		break;
+	}
+	csr32w(ctlr, Tipg, (6<<20)|(8<<10)|r);
+	csr32w(ctlr, Ait, 0);
+	csr32w(ctlr, Txdmac, 0);
+	csr32w(ctlr, Tidv, 128);
+
+	/*
+	 * Allocate the descriptor ring and load its
+	 * address and length into the NIC.
+	 */
+	ctlr->tdba = xspanalloc(Ntdesc*sizeof(Tdesc), 128 /* was 16 */, 0);
+	csr32w(ctlr, Tdbal, PCIWADDR(ctlr->tdba));
+	csr32w(ctlr, Tdbah, 0);
+	csr32w(ctlr, Tdlen, Ntdesc*sizeof(Tdesc));
+
+	/*
+	 * Initialise the ring head and tail pointers.
+	 */
+	ctlr->tdh = 0;
+	csr32w(ctlr, Tdh, ctlr->tdh);
+	ctlr->tdt = 0;
+	csr32w(ctlr, Tdt, ctlr->tdt);
+	ctlr->tb = malloc(sizeof(Block*)*Ntdesc);
+//	ctlr->im |= Txqe|Txdw;
+
+	r = (4<<WthreshSHIFT)|(4<<HthreshSHIFT)|(8<<PthreshSHIFT);
+	switch(ctlr->id){
+	default:
+		break;
+	case (0x100E<<16)|0x8086:	/* 82540EM */
+	case (0x101E<<16)|0x8086:	/* 82540EPLP */
+		r = csr32r(ctlr, Txdctl);
+		r &= ~WthreshMASK;
+		r |= Gran|(4<<WthreshSHIFT);
+
+		csr32w(ctlr, Tadv, 64);
+		break;
+	}
+	csr32w(ctlr, Txdctl, r);
+
+	r = csr32r(ctlr, Tctl);
+	r |= Ten;
+	csr32w(ctlr, Tctl, r);
+
+	if(ctlr->mii == nil || ctlr->mii->curphy == nil) {
+		print("igbe: no mii (yet)\n");
+		return 0;
+	}
+	/* wait for the link to come up */
+	if (miistatus(ctlr->mii) < 0)
+		return -1;
+	print("igbe: phy: ");
+	phy = ctlr->mii->curphy;
+	if (phy->fd)
+		print("full duplex");
+	else
+		print("half duplex");
+	print(", %d Mb/s\n", phy->speed);
+
+	/*
+	 * Flow control.
+	 */
+	ctrl = csr32r(ctlr, Ctrl);
+	if(phy->rfc)
+		ctrl |= Rfce;
+	if(phy->tfc)
+		ctrl |= Tfce;
+	csr32w(ctlr, Ctrl, ctrl);
+
+	return 0;
+}
+
+static int
+i82543mdior(Ctlr* ctlr, int n)
+{
+	int ctrl, data, i, r;
+
+	/*
+	 * Read n bits from the Management Data I/O Interface.
+	 */
+	ctrl = csr32r(ctlr, Ctrl);
+	r = (ctrl & ~Mddo)|Mdco;
+	data = 0;
+	for(i = n-1; i >= 0; i--){
+		if(csr32r(ctlr, Ctrl) & Mdd)
+			data |= (1<<i);
+		csr32w(ctlr, Ctrl, Mdc|r);
+		csr32w(ctlr, Ctrl, r);
+	}
+	csr32w(ctlr, Ctrl, ctrl);
+
+	return data;
+}
+
+static int
+i82543mdiow(Ctlr* ctlr, int bits, int n)
+{
+	int ctrl, i, r;
+
+	/*
+	 * Write n bits to the Management Data I/O Interface.
+	 */
+	ctrl = csr32r(ctlr, Ctrl);
+	r = Mdco|Mddo|ctrl;
+	for(i = n-1; i >= 0; i--){
+		if(bits & (1<<i))
+			r |= Mdd;
+		else
+			r &= ~Mdd;
+		csr32w(ctlr, Ctrl, Mdc|r);
+		csr32w(ctlr, Ctrl, r);
+	}
+	csr32w(ctlr, Ctrl, ctrl);
+
+	return 0;
+}
+
+static int
+i82543miimir(Mii* mii, int pa, int ra)
+{
+	int data;
+	Ctlr *ctlr;
+
+	ctlr = mii->ctlr;
+
+	/*
+	 * MII Management Interface Read.
+	 *
+	 * Preamble;
+	 * ST+OP+PHYAD+REGAD;
+	 * TA + 16 data bits.
+	 */
+	i82543mdiow(ctlr, 0xFFFFFFFF, 32);
+	i82543mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);
+	data = i82543mdior(ctlr, 18);
+
+	if(data & 0x10000)
+		return -1;
+
+	return data & 0xFFFF;
+}
+
+static int
+i82543miimiw(Mii* mii, int pa, int ra, int data)
+{
+	Ctlr *ctlr;
+
+	ctlr = mii->ctlr;
+
+	/*
+	 * MII Management Interface Write.
+	 *
+	 * Preamble;
+	 * ST+OP+PHYAD+REGAD+TA + 16 data bits;
+	 * Z.
+	 */
+	i82543mdiow(ctlr, 0xFFFFFFFF, 32);
+	data &= 0xFFFF;
+	data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);
+	i82543mdiow(ctlr, data, 32);
+
+	return 0;
+}
+
+static int
+igbemiimir(Mii* mii, int pa, int ra)
+{
+	Ctlr *ctlr;
+	int mdic, timo;
+
+	ctlr = mii->ctlr;
+
+	csr32w(ctlr, Mdic, MDIrop|(pa<<MDIpSHIFT)|(ra<<MDIrSHIFT));
+	mdic = 0;
+	for(timo = 64; timo; timo--){
+		mdic = csr32r(ctlr, Mdic);
+		if(mdic & (MDIe|MDIready))
+			break;
+		microdelay(1);
+	}
+
+	if((mdic & (MDIe|MDIready)) == MDIready)
+		return mdic & 0xFFFF;
+	return -1;
+}
+
+static int
+igbemiimiw(Mii* mii, int pa, int ra, int data)
+{
+	Ctlr *ctlr;
+	int mdic, timo;
+
+	ctlr = mii->ctlr;
+
+	data &= MDIdMASK;
+	csr32w(ctlr, Mdic, MDIwop|(pa<<MDIpSHIFT)|(ra<<MDIrSHIFT)|data);
+	mdic = 0;
+	for(timo = 64; timo; timo--){
+		mdic = csr32r(ctlr, Mdic);
+		if(mdic & (MDIe|MDIready))
+			break;
+		microdelay(1);
+	}
+	if((mdic & (MDIe|MDIready)) == MDIready)
+		return 0;
+	return -1;
+}
+
+static int
+igbemii(Ctlr* ctlr)
+{
+	MiiPhy *phy;
+	int ctrl, p, r;
+
+	r = csr32r(ctlr, Status);
+	if(r & Tbimode)
+		return -1;
+	if((ctlr->mii = malloc(sizeof(Mii))) == nil)
+		return -1;
+	ctlr->mii->ctlr = ctlr;
+
+	ctrl = csr32r(ctlr, Ctrl);
+	ctrl |= Slu;
+
+	switch(ctlr->id){
+	case (0x1004<<16)|0x8086:		/* 82543GC */
+		ctrl |= Frcdplx|Frcspd;
+		csr32w(ctlr, Ctrl, ctrl);
+
+		/*
+		 * The reset pin direction (Mdro) should already
+		 * be set from the EEPROM load.
+		 * If it's not set this configuration is unexpected
+		 * so bail.
+		 */
+		r = csr32r(ctlr, Ctrlext);
+		if(!(r & Mdro))
+			return -1;
+		csr32w(ctlr, Ctrlext, r);
+		delay(20);
+		r = csr32r(ctlr, Ctrlext);
+		r &= ~Mdr;
+		csr32w(ctlr, Ctrlext, r);
+		delay(20);
+		r = csr32r(ctlr, Ctrlext);
+		r |= Mdr;
+		csr32w(ctlr, Ctrlext, r);
+		delay(20);
+
+		ctlr->mii->mir = i82543miimir;
+		ctlr->mii->miw = i82543miimiw;
+		break;
+	case (0x1008<<16)|0x8086:		/* 82544EI*/
+	case (0x100E<<16)|0x8086:		/* 82540EM */
+	case (0x101E<<16)|0x8086:		/* 82540EPLP */
+		ctrl &= ~(Frcdplx|Frcspd);
+		csr32w(ctlr, Ctrl, ctrl);
+		ctlr->mii->mir = igbemiimir;
+		ctlr->mii->miw = igbemiimiw;
+		break;
+	default:
+		free(ctlr->mii);
+		ctlr->mii = nil;
+		return -1;
+	}
+
+	if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){
+		free(ctlr->mii);
+		ctlr->mii = nil;
+		return -1;
+	}
+	print("oui %X phyno %d\n", phy->oui, phy->phyno);
+
+	/*
+	 * 8254X-specific PHY registers not in 802.3:
+	 *	0x10	PHY specific control
+	 *	0x14	extended PHY specific control
+	 * Set appropriate values then reset the PHY to have
+	 * changes noted.
+	 */
+	r = miimir(ctlr->mii, 0x10);
+	r |= 0x0800;				/* assert CRS on Tx */
+	r |= 0x0060;				/* auto-crossover all speeds */
+	r |= 0x0002;				/* polarity reversal enabled */
+	miimiw(ctlr->mii, 0x10, r);
+
+	r = miimir(ctlr->mii, 0x14);
+	r |= 0x0070;				/* +25MHz clock */
+	r &= ~0x0F00;
+	r |= 0x0100;				/* 1x downshift */
+	miimiw(ctlr->mii, 0x14, r);
+
+	miireset(ctlr->mii);
+
+	p = 0;
+	if(ctlr->txcw & TxcwPs)
+		p |= AnaP;
+	if(ctlr->txcw & TxcwAs)
+		p |= AnaAP;
+	miiane(ctlr->mii, ~0, p, ~0);
+
+	return 0;
+}
+
+static int
+at93c46io(Ctlr* ctlr, char* op, int data)
+{
+	char *lp, *p;
+	int i, loop, eecd, r;
+
+	eecd = csr32r(ctlr, Eecd);
+
+	r = 0;
+	loop = -1;
+	lp = nil;
+	for(p = op; *p != '\0'; p++){
+		switch(*p){
+		default:
+			return -1;
+		case ' ':
+			continue;
+		case ':':			/* start of loop */
+			loop = strtol(p+1, &lp, 0)-1;
+			lp--;
+			if(p == lp)
+				loop = 7;
+			p = lp;
+			continue;
+		case ';':			/* end of loop */
+			if(lp == nil)
+				return -1;
+			loop--;
+			if(loop >= 0)
+				p = lp;
+			else
+				lp = nil;
+			continue;
+		case 'C':			/* assert clock */
+			eecd |= Sk;
+			break;
+		case 'c':			/* deassert clock */
+			eecd &= ~Sk;
+			break;
+		case 'D':			/* next bit in 'data' byte */
+			if(loop < 0)
+				return -1;
+			if(data & (1<<loop))
+				eecd |= Di;
+			else
+				eecd &= ~Di;
+			break;
+		case 'O':			/* collect data output */
+			i = (csr32r(ctlr, Eecd) & Do) != 0;
+			if(loop >= 0)
+				r |= (i<<loop);
+			else
+				r = i;
+			continue;
+		case 'I':			/* assert data input */
+			eecd |= Di;
+			break;
+		case 'i':			/* deassert data input */
+			eecd &= ~Di;
+			break;
+		case 'S':			/* enable chip select */
+			eecd |= Cs;
+			break;
+		case 's':			/* disable chip select */
+			eecd &= ~Cs;
+			break;
+		}
+		csr32w(ctlr, Eecd, eecd);
+		microdelay(1);
+	}
+	if(loop >= 0)
+		return -1;
+	return r;
+}
+
+static int
+at93c46r(Ctlr* ctlr)
+{
+	ushort sum;
+	char rop[20];
+	int addr, areq, bits, data, eecd, i;
+
+	eecd = csr32r(ctlr, Eecd);
+	if(eecd & Spi){
+		print("igbe: SPI EEPROM access not implemented\n");
+		return 0;
+	}
+	if(eecd & Eesz256)
+		bits = 8;
+	else
+		bits = 6;
+	snprint(rop, sizeof(rop), "S :%dDCc;", bits+3);
+
+	sum = 0;
+
+	switch(ctlr->id){
+	default:
+		areq = 0;
+		break;
+	case (0x100E<<16)|0x8086:		/* 82540EM */
+	case (0x101E<<16)|0x8086:		/* 82540EPLP */
+		areq = 1;
+		csr32w(ctlr, Eecd, eecd|Areq);
+		for(i = 0; i < 1000; i++){
+			if((eecd = csr32r(ctlr, Eecd)) & Agnt)
+				break;
+			microdelay(5);
+		}
+		if(!(eecd & Agnt)){
+			print("igbe: not granted EEPROM access\n");
+			goto release;
+		}
+		break;
+	}
+
+	for(addr = 0; addr < 0x40; addr++){
+		/*
+		 * Read a word at address 'addr' from the Atmel AT93C46
+		 * 3-Wire Serial EEPROM or compatible. The EEPROM access is
+		 * controlled by 4 bits in Eecd. See the AT93C46 datasheet
+		 * for protocol details.
+		 */
+		if(at93c46io(ctlr, rop, (0x06<<bits)|addr) != 0){
+			print("igbe: can't set EEPROM address 0x%2.2X\n", addr);
+			goto release;
+		}
+		data = at93c46io(ctlr, ":16COc;", 0);
+		at93c46io(ctlr, "sic", 0);
+		ctlr->eeprom[addr] = data;
+		sum += data;
+	}
+
+release:
+	if(areq)
+		csr32w(ctlr, Eecd, eecd & ~Areq);
+	return sum;
+}
+
+static void
+detach(Ctlr *ctlr)
+{
+	int r;
+
+	/*
+	 * Perform a device reset to get the chip back to the
+	 * power-on state, followed by an EEPROM reset to read
+	 * the defaults for some internal registers.
+	 */
+	csr32w(ctlr, Imc, ~0);
+	csr32w(ctlr, Rctl, 0);
+	csr32w(ctlr, Tctl, 0);
+
+	delay(10);
+
+	csr32w(ctlr, Ctrl, Devrst);
+	while(csr32r(ctlr, Ctrl) & Devrst)
+		;
+
+	csr32w(ctlr, Ctrlext, Eerst);
+	while(csr32r(ctlr, Ctrlext) & Eerst)
+		;
+
+	switch(ctlr->id){
+	default:
+		break;
+	case (0x100E<<16)|0x8086:		/* 82540EM */
+	case (0x101E<<16)|0x8086:		/* 82540EPLP */
+		r = csr32r(ctlr, Manc);
+		r &= ~Arpen;
+		csr32w(ctlr, Manc, r);
+		break;
+	}
+
+	csr32w(ctlr, Imc, ~0);
+	while(csr32r(ctlr, Icr))
+		;
+}
+
+static void
+igbedetach(Ether *edev)
+{
+	detach(edev->ctlr);
+}
+
+static void
+igbeshutdown(Ether* ether)
+{
+print("igbeshutdown\n");
+	igbedetach(ether);
+}
+
+static int
+igbereset(Ctlr* ctlr)
+{
+	int ctrl, i, pause, r, swdpio, txcw;
+
+	detach(ctlr);
+
+	/*
+	 * Read the EEPROM, validate the checksum
+	 * then get the device back to a power-on state.
+	 */
+	if((r = at93c46r(ctlr)) != 0xBABA){
+		print("igbe: bad EEPROM checksum - 0x%4.4uX\n", r);
+		return -1;
+	}
+
+	/*
+	 * Snarf and set up the receive addresses.
+	 * There are 16 addresses. The first should be the MAC address.
+	 * The others are cleared and not marked valid (MS bit of Rah).
+	 */
+	for(i = Ea; i < Eaddrlen/2; i++){
+		ctlr->ra[2*i] = ctlr->eeprom[i];
+		ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8;
+	}
+	r = (ctlr->ra[3]<<24)|(ctlr->ra[2]<<16)|(ctlr->ra[1]<<8)|ctlr->ra[0];
+	csr32w(ctlr, Ral, r);
+	r = 0x80000000|(ctlr->ra[5]<<8)|ctlr->ra[4];
+	csr32w(ctlr, Rah, r);
+	for(i = 1; i < 16; i++){
+		csr32w(ctlr, Ral+i*8, 0);
+		csr32w(ctlr, Rah+i*8, 0);
+	}
+
+	/*
+	 * Clear the Multicast Table Array.
+	 * It's a 4096 bit vector accessed as 128 32-bit registers.
+	 */
+	memset(ctlr->mta, 0, sizeof(ctlr->mta));
+	for(i = 0; i < 128; i++)
+		csr32w(ctlr, Mta+i*4, 0);
+
+	/*
+	 * Just in case the Eerst didn't load the defaults
+	 * (doesn't appear to fully on the 8243GC), do it manually.
+	 */
+	txcw = csr32r(ctlr, Txcw);
+	txcw &= ~(TxcwAne|TxcwPauseMASK|TxcwFd);
+	ctrl = csr32r(ctlr, Ctrl);
+	ctrl &= ~(SwdpioloMASK|Frcspd|Ilos|Lrst|Fd);
+
+	if(ctlr->eeprom[Icw1] & 0x0400){
+		ctrl |= Fd;
+		txcw |= TxcwFd;
+	}
+	if(ctlr->eeprom[Icw1] & 0x0200)
+		ctrl |= Lrst;
+	if(ctlr->eeprom[Icw1] & 0x0010)
+		ctrl |= Ilos;
+	if(ctlr->eeprom[Icw1] & 0x0800)
+		ctrl |= Frcspd;
+	swdpio = (ctlr->eeprom[Icw1] & 0x01E0)>>5;
+	ctrl |= swdpio<<SwdpioloSHIFT;
+	csr32w(ctlr, Ctrl, ctrl);
+
+	ctrl = csr32r(ctlr, Ctrlext);
+	ctrl &= ~(Ips|SwdpiohiMASK);
+	swdpio = (ctlr->eeprom[Icw2] & 0x00F0)>>4;
+	if(ctlr->eeprom[Icw1] & 0x1000)
+		ctrl |= Ips;
+	ctrl |= swdpio<<SwdpiohiSHIFT;
+	csr32w(ctlr, Ctrlext, ctrl);
+
+	if(ctlr->eeprom[Icw2] & 0x0800)
+		txcw |= TxcwAne;
+	pause = (ctlr->eeprom[Icw2] & 0x3000)>>12;
+	txcw |= pause<<TxcwPauseSHIFT;
+	switch(pause){
+	default:
+		ctlr->fcrtl = 0x00002000;
+		ctlr->fcrth = 0x00004000;
+		txcw |= TxcwAs|TxcwPs;
+		break;
+	case 0:
+		ctlr->fcrtl = 0x00002000;
+		ctlr->fcrth = 0x00004000;
+		break;
+	case 2:
+		ctlr->fcrtl = 0;
+		ctlr->fcrth = 0;
+		txcw |= TxcwAs;
+		break;
+	}
+	ctlr->txcw = txcw;
+	csr32w(ctlr, Txcw, txcw);
+
+	/*
+	 * Flow control - values from the datasheet.
+	 */
+	csr32w(ctlr, Fcal, 0x00C28001);
+	csr32w(ctlr, Fcah, 0x00000100);
+	csr32w(ctlr, Fct, 0x00008808);
+	csr32w(ctlr, Fcttv, 0x00000100);
+
+	csr32w(ctlr, Fcrtl, ctlr->fcrtl);
+	csr32w(ctlr, Fcrth, ctlr->fcrth);
+
+	ilock(&ctlr->imlock);
+	csr32w(ctlr, Imc, ~0);
+	ctlr->im = Lsc;
+	csr32w(ctlr, Ims, ctlr->im);
+	iunlock(&ctlr->imlock);
+
+	if(!(csr32r(ctlr, Status) & Tbimode) && igbemii(ctlr) < 0) {
+		print("igbe: igbemii failed\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static void
+igbepci(void)
+{
+	int port, cls;
+	Pcidev *p;
+	Ctlr *ctlr;
+
+	p = nil;
+	while(p = pcimatch(p, 0, 0)){
+		if(p->ccrb != 0x02 || p->ccru != 0)
+			continue;
+
+		switch((p->did<<16)|p->vid){
+		case (0x1000<<16)|0x8086:	/* LSI L2A1157 (82542) */
+		default:
+			continue;
+		case (0x1001<<16)|0x8086:	/* Intel PRO/1000 F */
+			break;
+		case (0x1004<<16)|0x8086:	/* 82543GC - copper (PRO/1000 T) */
+		case (0x1008<<16)|0x8086:	/* 82544EI - copper */
+		case (0x100E<<16)|0x8086:	/* 82540EM - copper */
+		case (0x101E<<16)|0x8086:	/* 82540EPLP - copper */
+			break;
+		}
+
+		port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
+		if(port == 0){
+			print("igbe: can't map %8.8luX\n", p->mem[0].bar);
+			continue;
+		}
+
+		/*
+		 * from etherga620.c:
+		 * If PCI Write-and-Invalidate is enabled set the max write DMA
+		 * value to the host cache-line size (32 on Pentium or later).
+		 */
+		if(p->pcr & MemWrInv){
+			cls = pcicfgr8(p, PciCLS) * 4;
+			if(cls != CACHELINESZ)
+				pcicfgw8(p, PciCLS, CACHELINESZ/4);
+		}
+
+		cls = pcicfgr8(p, PciCLS);
+		switch(cls){
+			default:
+				print("igbe: unexpected CLS - %d bytes\n",
+					cls*sizeof(long));
+				break;
+			case 0x00:
+			case 0xFF:
+				/* alphapc 164lx returns 0 */
+				print("igbe: unusable PciCLS: %d, using %d longs\n",
+					cls, CACHELINESZ/sizeof(long));
+				cls = CACHELINESZ/sizeof(long);
+				pcicfgw8(p, PciCLS, cls);
+				break;
+			case 0x08:
+			case 0x10:
+				break;
+		}
+
+		ctlr = malloc(sizeof(Ctlr));
+		ctlr->port = port;
+		ctlr->pcidev = p;
+		ctlr->id = (p->did<<16)|p->vid;
+		ctlr->cls = cls*4;
+		ctlr->nic = KADDR(ctlr->port);
+print("status0 %8.8uX\n", csr32r(ctlr, Status));
+		if(igbereset(ctlr)){
+			free(ctlr);
+			continue;
+		}
+print("status1 %8.8uX\n", csr32r(ctlr, Status));
+		pcisetbme(p);
+
+		if(ctlrhead != nil)
+			ctlrtail->next = ctlr;
+		else
+			ctlrhead = ctlr;
+		ctlrtail = ctlr;
+	}
+}
+
+int
+igbepnp(Ether* edev)
+{
+	int i;
+	Ctlr *ctlr;
+	uchar ea[Eaddrlen];
+
+	if(ctlrhead == nil)
+		igbepci();
+
+	/*
+	 * 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;
+		if(edev->port == 0 || edev->port == ctlr->port){
+			ctlr->active = 1;
+			break;
+		}
+	}
+	if(ctlr == nil)
+		return -1;
+
+	edev->ctlr = ctlr;
+	edev->port = ctlr->port;
+	edev->irq = ctlr->pcidev->intl;
+	edev->tbdf = ctlr->pcidev->tbdf;
+//	edev->mbps = 1000;
+
+	/*
+	 * Check if the adapter's station address is to be overridden.
+	 * If not, read it from the EEPROM and set in ether->ea prior to
+	 * loading the station address in the hardware.
+	 */
+	memset(ea, 0, Eaddrlen);
+	if(memcmp(ea, edev->ea, Eaddrlen) == 0){
+		for(i = 0; i < Eaddrlen/2; i++){
+			edev->ea[2*i] = ctlr->eeprom[i];
+			edev->ea[2*i+1] = ctlr->eeprom[i]>>8;
+		}
+	}
+	igbeinit(edev);
+
+	/*
+	 * Linkage to the generic ethernet driver.
+	 */
+	edev->attach = igbeattach;
+	edev->transmit = igbetransmit;
+	edev->interrupt = igbeinterrupt;
+	edev->detach = igbedetach;
+
+	return 0;
+}

+ 10 - 8
sys/src/boot/pc/fns.h

@@ -4,7 +4,7 @@ Alarm*	alarm(int, void (*)(Alarm*), void*);
 void	alarminit(void);
 void	alarminit(void);
 Block*	allocb(int);
 Block*	allocb(int);
 void	apminit(void);
 void	apminit(void);
-int	bootp(int, char*, Boot*);
+int	bootpboot(int, char*, Boot*);
 int	bootpass(Boot*, void*, int);
 int	bootpass(Boot*, void*, int);
 void	cancel(Alarm*);
 void	cancel(Alarm*);
 int	cdinit(void);
 int	cdinit(void);
@@ -23,6 +23,7 @@ uchar*	etheraddr(int);
 int	etherinit(void);
 int	etherinit(void);
 void	etherinitdev(int, char*);
 void	etherinitdev(int, char*);
 void	etherprintdevs(int);
 void	etherprintdevs(int);
+int	etherrxflush(int);
 int	etherrxpkt(int, Etherpkt*, int);
 int	etherrxpkt(int, Etherpkt*, int);
 int	ethertxpkt(int, Etherpkt*, int, int);
 int	ethertxpkt(int, Etherpkt*, int, int);
 #define	evenaddr(x)		/* 386 doesn't care */
 #define	evenaddr(x)		/* 386 doesn't care */
@@ -30,7 +31,7 @@ int	floppyboot(int, char*, Boot*);
 int	floppyinit(void);
 int	floppyinit(void);
 void	floppyinitdev(int, char*);
 void	floppyinitdev(int, char*);
 void	floppyprintdevs(int);
 void	floppyprintdevs(int);
-void* floppygetfspart(int, char*, int);
+void*	floppygetfspart(int, char*, int);
 void	freeb(Block*);
 void	freeb(Block*);
 char*	getconf(char*);
 char*	getconf(char*);
 ulong	getcr0(void);
 ulong	getcr0(void);
@@ -61,7 +62,7 @@ void	meminit(ulong);
 void	microdelay(int);
 void	microdelay(int);
 void	mmuinit(void);
 void	mmuinit(void);
 #define	nelem(x)	(sizeof(x)/sizeof(x[0]))
 #define	nelem(x)	(sizeof(x)/sizeof(x[0]))
-char *nextelem(char*, char*);
+char*	nextelem(char*, char*);
 uchar	nvramread(int);
 uchar	nvramread(int);
 void	outb(int, int);
 void	outb(int, int);
 void	outs(int, ushort);
 void	outs(int, ushort);
@@ -77,9 +78,9 @@ void	pcicfgw8(Pcidev*, int, int);
 void	pcicfgw16(Pcidev*, int, int);
 void	pcicfgw16(Pcidev*, int, int);
 void	pcicfgw32(Pcidev*, int, int);
 void	pcicfgw32(Pcidev*, int, int);
 void	pcihinv(Pcidev*);
 void	pcihinv(Pcidev*);
-Pcidev* pcimatch(Pcidev*, int, int);
-uchar pciintl(Pcidev *);
-uchar pciipin(Pcidev *, uchar);
+Pcidev*	pcimatch(Pcidev*, int, int);
+uchar	pciintl(Pcidev *);
+uchar	pciipin(Pcidev *, uchar);
 void	pcireset(void);
 void	pcireset(void);
 void	pcisetbme(Pcidev*);
 void	pcisetbme(Pcidev*);
 int	pcmcistuple(int, int, void*, int);
 int	pcmcistuple(int, int, void*, int);
@@ -89,6 +90,7 @@ void	pcmunmap(int, PCMmap*);
 void	ptcheck(char*);
 void	ptcheck(char*);
 void	putcr3(ulong);
 void	putcr3(ulong);
 void	putidt(Segdesc*, int);
 void	putidt(Segdesc*, int);
+void*	pxegetfspart(int, char*, int);
 void	qinit(IOQ*);
 void	qinit(IOQ*);
 void	readlsconf(void);
 void	readlsconf(void);
 void	sdaddconf(int);
 void	sdaddconf(int);
@@ -119,7 +121,7 @@ void*	xspanalloc(ulong, int, ulong);
 
 
 #define malloc(n)	ialloc(n, 0)
 #define malloc(n)	ialloc(n, 0)
 #define mallocz(n, c)	ialloc(n, 0)
 #define mallocz(n, c)	ialloc(n, 0)
-#define free(v) while(0)
+#define free(v)		while(0)
 
 
 #define	GSHORT(p)	(((p)[1]<<8)|(p)[0])
 #define	GSHORT(p)	(((p)[1]<<8)|(p)[0])
 #define	GLONG(p)	((GSHORT(p+2)<<16)|GSHORT(p))
 #define	GLONG(p)	((GSHORT(p+2)<<16)|GSHORT(p))
@@ -134,7 +136,7 @@ void*	xspanalloc(ulong, int, ulong);
 
 
 
 
 #define xalloc(n)	ialloc(n, 0)
 #define xalloc(n)	ialloc(n, 0)
-#define xfree(v) while(0)
+#define xfree(v)	while(0)
 #define lock(l)		if(l){/* nothing to do */;}else{/* nothing to do */;}
 #define lock(l)		if(l){/* nothing to do */;}else{/* nothing to do */;}
 #define unlock(l)	if(l){/* nothing to do */;}else{/* nothing to do */;}
 #define unlock(l)	if(l){/* nothing to do */;}else{/* nothing to do */;}
 
 

+ 2 - 1
sys/src/boot/pc/fs.c

@@ -21,7 +21,7 @@ nextelem(char *path, char *elem)
 	if(*path==0 || *path==' ')
 	if(*path==0 || *path==' ')
 		return 0;
 		return 0;
 	for(i=0; *path!='\0' && *path!='/' && *path!=' '; i++){
 	for(i=0; *path!='\0' && *path!='/' && *path!=' '; i++){
-		if(i==28){
+		if(i==NAMELEN){
 			print("name component too long\n");
 			print("name component too long\n");
 			return 0;
 			return 0;
 		}
 		}
@@ -40,6 +40,7 @@ fswalk(Fs *fs, char *path, File *f)
 	if(BADPTR(fs->walk))
 	if(BADPTR(fs->walk))
 		panic("fswalk bad pointer fs->walk");
 		panic("fswalk bad pointer fs->walk");
 
 
+	f->path = path;
 	while(path = nextelem(path, element)){
 	while(path = nextelem(path, element)){
 		switch(fs->walk(f, element)){
 		switch(fs->walk(f, element)){
 		case -1:
 		case -1:

+ 4 - 2
sys/src/boot/pc/fs.h

@@ -1,5 +1,5 @@
 typedef struct File File;
 typedef struct File File;
-typedef struct Fs	Fs;
+typedef struct Fs Fs;
 
 
 #include "dosfs.h"
 #include "dosfs.h"
 #include "kfs.h"
 #include "kfs.h"
@@ -8,8 +8,10 @@ struct File{
 	union{
 	union{
 		Dosfile	dos;
 		Dosfile	dos;
 		Kfsfile	kfs;
 		Kfsfile	kfs;
+		int walked;
 	};
 	};
 	Fs	*fs;
 	Fs	*fs;
+	char	*path;
 };
 };
 
 
 struct Fs{
 struct Fs{
@@ -19,7 +21,7 @@ struct Fs{
 	};
 	};
 	int	dev;				/* device id */
 	int	dev;				/* device id */
 	long	(*diskread)(Fs*, void*, long);	/* disk read routine */
 	long	(*diskread)(Fs*, void*, long);	/* disk read routine */
-	vlong	(*diskseek)(Fs*, vlong);		/* disk seek routine */
+	vlong	(*diskseek)(Fs*, vlong);	/* disk seek routine */
 	long	(*read)(File*, void*, long);
 	long	(*read)(File*, void*, long);
 	int	(*walk)(File*, char*);
 	int	(*walk)(File*, char*);
 	File	root;
 	File	root;

+ 2 - 0
sys/src/boot/pc/ip.h

@@ -96,3 +96,5 @@ struct Netaddr
 	ushort	port;
 	ushort	port;
 	char	ea[Eaddrlen];
 	char	ea[Eaddrlen];
 };
 };
+
+extern int	eipfmt(Fmt*);

+ 7 - 0
sys/src/boot/pc/l.s

@@ -807,3 +807,10 @@ TEXT hello(SB), $0
 
 
 TEXT rock(SB), $0
 TEXT rock(SB), $0
 	BYTE $0; BYTE $0; BYTE $0; BYTE $0;
 	BYTE $0; BYTE $0; BYTE $0; BYTE $0;
+
+GLOBL pxe(SB), $4
+#ifdef PXE
+DATA	pxe+0(SB)/4, $1
+#else
+DATA	pxe+0(SB)/4, $0
+#endif /* PXE */

+ 29 - 6
sys/src/boot/pc/lib.h

@@ -25,18 +25,38 @@ extern	long	strlen(char*);
 extern	char*	strrchr(char*, char);
 extern	char*	strrchr(char*, char);
 extern	char*	strstr(char*, char*);
 extern	char*	strstr(char*, char*);
 
 
+
 /*
 /*
  * print routines
  * print routines
  */
  */
-extern	char*	donprint(char*, char*, char*, void*);
+typedef struct Fmt	Fmt;
+typedef int (*Fmts)(Fmt*);
+struct Fmt{
+	uchar	runes;			/* output buffer is runes or chars? */
+	void	*start;			/* of buffer */
+	void	*to;			/* current place in the buffer */
+	void	*stop;			/* end of the buffer; overwritten if flush fails */
+	int	(*flush)(Fmt *);	/* called when to == stop */
+	void	*farg;			/* to make flush a closure */
+	int	nfmt;			/* num chars formatted so far */
+	va_list	args;			/* args passed to dofmt */
+	int	r;			/* % format Rune */
+	int	width;
+	int	prec;
+	ulong	flags;
+};
+extern	int	print(char*, ...);
+extern	char*	vseprint(char*, char*, char*, va_list);
 extern	int	sprint(char*, char*, ...);
 extern	int	sprint(char*, char*, ...);
 extern 	int	snprint(char*, int, char*, ...);
 extern 	int	snprint(char*, int, char*, ...);
-extern	int	print(char*, ...);
+extern	int	fmtinstall(int, int (*)(Fmt*));
 
 
-#define	PRINTSIZE	256
-#pragma varargck argpos print 1
-#pragma varargck argpos snprint 3
-#pragma varargck argpos sprint 2
+#pragma	varargck	argpos	fmtprint	2
+#pragma	varargck	argpos	print		1
+#pragma	varargck	argpos	seprint		3
+#pragma	varargck	argpos	snprint		3
+#pragma	varargck	argpos	sprint		2
+#pragma varargck	type	"H" void*
 
 
 #pragma	varargck	type	"lld"	vlong
 #pragma	varargck	type	"lld"	vlong
 #pragma	varargck	type	"llx"	vlong
 #pragma	varargck	type	"llx"	vlong
@@ -66,6 +86,9 @@ extern	int	print(char*, ...);
 #pragma	varargck	type	"|"	int
 #pragma	varargck	type	"|"	int
 #pragma	varargck	type	"p"	void*
 #pragma	varargck	type	"p"	void*
 #pragma varargck	type	"lux"	void*
 #pragma varargck	type	"lux"	void*
+#pragma	varargck	type	"E"	uchar*
+
+#define PRINTSIZE	256
 
 
 /*
 /*
  * one-of-a-kind
  * one-of-a-kind

+ 34 - 18
sys/src/boot/pc/load.c

@@ -7,35 +7,59 @@
 
 
 #include "fs.h"
 #include "fs.h"
 
 
+static char *diskparts[] = { "dos", "9fat", "fs", "data", "cdboot", 0 };
+static char *etherparts[] = { "*", 0 };
+
+static char *diskinis[] = {
+	"plan9/plan9.ini",
+	"plan9.ini",
+	0
+};
+static char *etherinis[] = {
+	"/cfg/pxe/%E",
+	0
+};
+
 Type types[] = {
 Type types[] = {
 	{	Tfloppy,
 	{	Tfloppy,
 		Fini|Ffs,
 		Fini|Ffs,
 		floppyinit, floppyinitdev,
 		floppyinit, floppyinitdev,
 		floppygetfspart, 0, floppyboot,
 		floppygetfspart, 0, floppyboot,
 		floppyprintdevs,
 		floppyprintdevs,
+		diskparts,
+		diskinis,
 	},
 	},
 	{	Tcd,
 	{	Tcd,
 		Fini|Ffs,
 		Fini|Ffs,
 		cdinit, sdinitdev,
 		cdinit, sdinitdev,
 		sdgetfspart, sdaddconf, sdboot,
 		sdgetfspart, sdaddconf, sdboot,
 		sdprintdevs,
 		sdprintdevs,
+		diskparts,
+		diskinis,
 	},
 	},
 	{	Tether,
 	{	Tether,
-		Fbootp,
+		Fini|Fbootp,
 		etherinit, etherinitdev,
 		etherinit, etherinitdev,
-		0, 0, bootp,
+		pxegetfspart, 0, bootpboot,
 		etherprintdevs,
 		etherprintdevs,
+		etherparts,
+		etherinis,
 	},
 	},
 	{	Tsd,
 	{	Tsd,
 		Fini|Ffs,
 		Fini|Ffs,
 		sdinit, sdinitdev,
 		sdinit, sdinitdev,
 		sdgetfspart, sdaddconf, sdboot,
 		sdgetfspart, sdaddconf, sdboot,
 		sdprintdevs,
 		sdprintdevs,
+		diskparts,
+		diskinis,
 	},
 	},
 	{	Tnil,
 	{	Tnil,
 		0,
 		0,
-		0, 0, 0, 0,
-		{ 0, },
+		nil, nil, nil, nil, nil, nil,
+		nil,
+		nil,
+		0,
+		nil,
 	},
 	},
 };
 };
 
 
@@ -107,12 +131,6 @@ static Mode modes[NMode+1] = {
 	[Manual]	{ "manual", Manual, },
 	[Manual]	{ "manual", Manual, },
 };
 };
 
 
-static char *inis[] = {
-	"plan9/plan9.ini",
-	"plan9.ini",
-	0
-};
-
 char **ini;
 char **ini;
 
 
 int scsi0port;
 int scsi0port;
@@ -178,8 +196,6 @@ allocm(Type *tp)
 	return *l;
 	return *l;
 }
 }
 
 
-char *parts[] = { "dos", "9fat", "fs", "data", "cdboot", 0 };
-
 Medium*
 Medium*
 probe(int type, int flag, int dev)
 probe(int type, int flag, int dev)
 {
 {
@@ -221,15 +237,15 @@ probe(int type, int flag, int dev)
 
 
 			if(mp->flag & Fini){
 			if(mp->flag & Fini){
 				mp->flag &= ~Fini;
 				mp->flag &= ~Fini;
-				for(partp = parts; *partp; partp++){
+				for(partp = tp->parts; *partp; partp++){
 					if((fs = (*tp->getfspart)(i, *partp, 0)) == nil)
 					if((fs = (*tp->getfspart)(i, *partp, 0)) == nil)
 						continue;
 						continue;
 
 
-					for(ini = inis; *ini; ini++){
+					for(ini = tp->inis; *ini; ini++){
 						if(fswalk(fs, *ini, &f) > 0){
 						if(fswalk(fs, *ini, &f) > 0){
 							mp->inifs = fs;
 							mp->inifs = fs;
 							mp->part = *partp;
 							mp->part = *partp;
-							mp->ini = *ini;
+							mp->ini = f.path;
 							mp->flag |= Fini;
 							mp->flag |= Fini;
 							goto Break2;
 							goto Break2;
 						}
 						}
@@ -267,8 +283,8 @@ main(void)
 
 
 	readlsconf();
 	readlsconf();
 	for(tp = types; tp->type != Tnil; tp++){
 	for(tp = types; tp->type != Tnil; tp++){
-		if(tp->type == Tether)
-			continue;
+		//if(tp->type == Tether)
+		//	continue;
 		if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
 		if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
 			print("using %s!%s!%s\n", mp->name, mp->part, mp->ini);
 			print("using %s!%s!%s\n", mp->name, mp->part, mp->ini);
 			iniread = !dotini(mp->inifs);
 			iniread = !dotini(mp->inifs);
@@ -313,7 +329,7 @@ done:
 		if(mode == Mlocal)
 		if(mode == Mlocal)
 			flag &= ~Fbootp;
 			flag &= ~Fbootp;
 		if((mp = probe(Tany, flag, Dany)) && mp->type->type != Tfloppy)
 		if((mp = probe(Tany, flag, Dany)) && mp->type->type != Tfloppy)
-			boot(mp, 0);
+			boot(mp, "");
 	}
 	}
 
 
 	def[0] = 0;
 	def[0] = 0;

+ 5 - 4
sys/src/boot/pc/mkfile

@@ -19,13 +19,13 @@ CORE=\
 	clock.$O\
 	clock.$O\
 	console.$O\
 	console.$O\
 	dosboot.$O\
 	dosboot.$O\
-	donprint.$O\
 	devfloppy.$O\
 	devfloppy.$O\
 	dma.$O\
 	dma.$O\
 	fs.$O\
 	fs.$O\
 	ilock.$O\
 	ilock.$O\
 	kbd.$O\
 	kbd.$O\
 	kfsboot.$O\
 	kfsboot.$O\
+	print.$O\
 	queue.$O\
 	queue.$O\
 	trap.$O\
 	trap.$O\
 
 
@@ -61,6 +61,7 @@ ETHER=\
 	ether8390.$O\
 	ether8390.$O\
 	etherec2t.$O\
 	etherec2t.$O\
 	etherelnk3.$O\
 	etherelnk3.$O\
+	etherigbe.$O\
 	ethermii.$O\
 	ethermii.$O\
 	etherrhine.$O\
 	etherrhine.$O\
 
 
@@ -86,15 +87,15 @@ CFLAGS=-FVw -I.
 all:V:	$TARG
 all:V:	$TARG
 
 
 9load:	l.$O $CORE $LOAD $ETHER
 9load:	l.$O $CORE $LOAD $ETHER
-	$LD -o $target -H3 -T0x80010000 -l $prereq -lflate -lc
+	$LD -o $target -H3 -T0x80010000 -l $prereq -lflate -lc -lip
 	ls -l $target
 	ls -l $target
 
 
 9pxeload:	lpxe.$O $CORE $LOAD $ETHER
 9pxeload:	lpxe.$O $CORE $LOAD $ETHER
-	$LD -o $target -H3 -T0x80007C00 -l $prereq -lflate -lc
+	$LD -o $target -H3 -T0x80007C00 -l $prereq -lflate -lc -lip
 	ls -l $target
 	ls -l $target
 
 
 9loaddebug:	l.$O $CORE $LOAD $ETHER
 9loaddebug:	l.$O $CORE $LOAD $ETHER
-	$LD -o $target -T0x80010000 -l $prereq -lflate -lc
+	$LD -o $target -T0x80010000 -l $prereq -lflate -lc -lip
 	ls -l $target
 	ls -l $target
 	# acid $target
 	# acid $target
 	# map({"text", 0x80010000, 0x80090000, 0x00000020})
 	# map({"text", 0x80010000, 0x80090000, 0x00000020})

+ 7 - 1
sys/src/boot/pc/noether.c

@@ -28,7 +28,13 @@ etherrxpkt(int, Etherpkt*, int)
 }
 }
 
 
 int
 int
-bootp(int, char*, Boot*)
+bootpboot(int, char*, Boot*)
 {
 {
 	return -1;
 	return -1;
 }
 }
+
+void*
+pxegetfspart(int, char*, int)
+{
+	return nil;
+}

+ 25 - 0
sys/src/boot/pc/print.c

@@ -0,0 +1,25 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+static Lock fmtl;
+
+void
+_fmtlock(void)
+{
+	lock(&fmtl);
+}
+
+void
+_fmtunlock(void)
+{
+	unlock(&fmtl);
+}
+
+int
+_efgfmt(Fmt*)
+{
+	return -1;
+}

+ 0 - 6
sys/src/boot/pc/sd.h

@@ -113,12 +113,6 @@ extern SDev* scsiid(SDev*, SDifc*);
 #define IrqATA1 15
 #define IrqATA1 15
 #define qlock(i)	while(0)
 #define qlock(i)	while(0)
 #define qunlock(i)	while(0)
 #define qunlock(i)	while(0)
-#undef va_start
-#undef va_end
-#define va_list void**
-#define va_start(a, b) (a=(&(b)+1))
-#define va_end(x) 
-#define doprint donprint
 
 
 #define putstrn consputs
 #define putstrn consputs
 
 

+ 1 - 1
sys/src/boot/pc/sdata.c

@@ -285,7 +285,7 @@ atadebug(int cmdport, int ctlport, char* fmt, ...)
 	}
 	}
 
 
 	va_start(arg, fmt);
 	va_start(arg, fmt);
-	n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf;
+	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
 	va_end(arg);
 	va_end(arg);
 
 
 	if(cmdport){
 	if(cmdport){