Browse Source

Plan 9 from Bell Labs 2007-05-12

David du Colombier 17 years ago
parent
commit
19a1ce130b

+ 50 - 24
dist/replica/_plan9.db

@@ -53,7 +53,7 @@
 386/bin/auth/debug - 775 sys sys 1168402268 101566
 386/bin/auth/disable - 775 sys sys 1020319057 146
 386/bin/auth/enable - 775 sys sys 1020319057 134
-386/bin/auth/factotum - 775 sys sys 1178568247 321180
+386/bin/auth/factotum - 775 sys sys 1178853707 321175
 386/bin/auth/fgui - 775 sys sys 1176520475 218973
 386/bin/auth/guard.srv - 775 sys sys 1178568248 143650
 386/bin/auth/iam - 775 sys sys 1085076981 50791
@@ -194,7 +194,7 @@
 386/bin/crop - 775 sys sys 1168402298 116374
 386/bin/cwfs - 775 sys sys 1178568265 365217
 386/bin/date - 775 sys sys 1178568265 41845
-386/bin/db - 775 sys sys 1172203054 346003
+386/bin/db - 775 sys sys 1178908092 345933
 386/bin/dc - 775 sys sys 1168402299 99260
 386/bin/dd - 775 sys sys 1159039156 45991
 386/bin/deroff - 775 sys sys 1168402299 74474
@@ -440,7 +440,7 @@
 386/bin/tprof - 775 sys sys 1172203056 297762
 386/bin/tr - 775 sys sys 1168402355 62088
 386/bin/trace - 775 sys sys 1178568308 180414
-386/bin/troff - 775 sys sys 1176520503 360243
+386/bin/troff - 775 sys sys 1178853709 361158
 386/bin/troff2html - 775 sys sys 1178568308 84524
 386/bin/tweak - 775 sys sys 1168402356 193256
 386/bin/unicode - 775 sys sys 1168402356 62747
@@ -482,7 +482,7 @@
 386/bin/usb - 20000000775 sys sys 1019538890 0
 386/bin/usb/usbaudio - 775 sys sys 1178568318 188012
 386/bin/usb/usbd - 775 sys sys 1176520513 130769
-386/bin/usb/usbmouse - 775 sys sys 1176520514 109605
+386/bin/usb/usbmouse - 775 sys sys 1178853709 109673
 386/bin/usb/usbprinter - 775 sys sys 1089408719 222
 386/bin/vac - 775 sys sys 1178568318 169885
 386/bin/vacfs - 775 sys sys 1178568319 174693
@@ -563,7 +563,7 @@
 386/lib/libhttpd.a - 664 sys sys 1177283321 99734
 386/lib/libip.a - 664 sys sys 1178826954 34710
 386/lib/libl.a - 664 sys sys 1168402367 5372
-386/lib/libmach.a - 664 sys sys 1173410637 785440
+386/lib/libmach.a - 664 sys sys 1178892112 809418
 386/lib/libmemdraw.a - 664 sys sys 1168402369 284092
 386/lib/libmemlayer.a - 664 sys sys 1168402369 47360
 386/lib/libmp.a - 664 sys sys 1176520528 79978
@@ -884,7 +884,7 @@ dist/replica - 20000000775 sys sys 1166743907 0
 dist/replica/cd - 664 sys sys 1149084099 922
 dist/replica/kfs - 664 sys sys 1019527929 237
 dist/replica/network - 775 sys sys 1139499513 956
-dist/replica/plan9.proto - 664 sys sys 1177628403 2840
+dist/replica/plan9.proto - 664 sys sys 1178910941 2871
 env - 20000000775 sys sys 1104813586 0
 fd - 20000000775 sys sys 1020896384 0
 lib - 20000000775 sys sys 1161442421 0
@@ -5442,6 +5442,13 @@ power/include/ureg.h - 664 sys sys 1032057837 997
 power/lib - 20000000775 sys sys 1039727909 0
 power/lib/ape - 20000000775 sys sys 1020896376 0
 power/mkfile - 664 sys sys 948141304 46
+power64 - 20000000775 sys sys 1178892028 0
+power64/bin - 20000000775 sys sys 1178891955 0
+power64/include - 20000000775 sys sys 1178892069 0
+power64/include/u.h - 664 sys sys 1178892069 2886
+power64/include/ureg.h - 664 sys sys 1178892069 915
+power64/lib - 20000000775 sys sys 1178891973 0
+power64/mkfile - 664 sys sys 1178892028 46
 rc - 20000000775 sys sys 1039727911 0
 rc/bin - 20000000775 sys sys 1158798931 0
 rc/bin/0a - 775 sys sys 1143293821 24
@@ -5985,7 +5992,7 @@ sys/games/lib/sudoku/images/9.bit - 664 sys sys 1117226542 537
 sys/include - 20000000775 sys sys 1072904891 0
 sys/include/9p.h - 664 sys sys 1134337548 4759
 sys/include/String.h - 664 sys sys 1091904425 1319
-sys/include/a.out.h - 664 sys sys 1148106925 1418
+sys/include/a.out.h - 664 sys sys 1178892101 1473
 sys/include/ape - 20000000775 sys sys 1070327361 0
 sys/include/ape/Plan9libnet.h - 664 sys sys 944948760 487
 sys/include/ape/ar.h - 664 sys sys 944948759 354
@@ -6072,7 +6079,7 @@ sys/include/ip.h - 664 sys sys 1178768502 2597
 sys/include/keyboard.h - 664 sys sys 1131637696 865
 sys/include/libc.h - 664 sys sys 1168306860 19851
 sys/include/libsec.h - 664 sys sys 1124709121 9345
-sys/include/mach.h - 664 sys sys 1143814376 8641
+sys/include/mach.h - 664 sys sys 1178892102 8758
 sys/include/memdraw.h - 664 sys sys 1091904419 5645
 sys/include/memlayer.h - 664 sys sys 1051031022 1851
 sys/include/mouse.h - 664 sys sys 1035232010 1003
@@ -8036,6 +8043,7 @@ sys/src/9/pc/ether8139.c - 664 sys sys 1175019929 18584
 sys/src/9/pc/ether8169.c - 664 sys sys 1172259757 25466
 sys/src/9/pc/ether82543gc.c - 664 sys sys 1131290377 32294
 sys/src/9/pc/ether82557.c - 664 sys sys 1153082663 30197
+sys/src/9/pc/ether82563.c - 664 sys sys 1178932992 32729
 sys/src/9/pc/ether83815.c - 664 sys sys 1172259521 26346
 sys/src/9/pc/ether8390.c - 664 sys sys 1131290377 17702
 sys/src/9/pc/ether8390.h - 664 sys sys 1015014517 1511
@@ -8150,7 +8158,7 @@ sys/src/9/port/debugalloc.c - 664 sys sys 1014931171 10402
 sys/src/9/port/dev.c - 664 sys sys 1146151714 8177
 sys/src/9/port/devaudio.c - 664 sys sys 1170456648 21199
 sys/src/9/port/devbridge.c - 664 sys sys 1055688301 24308
-sys/src/9/port/devcap.c - 664 sys sys 1178320320 4160
+sys/src/9/port/devcap.c - 664 sys sys 1178886040 4141
 sys/src/9/port/devcons.c - 664 sys sys 1176658321 22943
 sys/src/9/port/devdraw.c - 664 sys sys 1147023550 44447
 sys/src/9/port/devdup.c - 664 sys sys 1014931172 2332
@@ -9097,7 +9105,7 @@ sys/src/boot/pc/dosboot.c - 664 sys sys 1097716791 11240
 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/error.h - 664 sys sys 1015007950 3081
-sys/src/boot/pc/ether.c - 664 sys sys 1174077249 5326
+sys/src/boot/pc/ether.c - 664 sys sys 1178926685 5380
 sys/src/boot/pc/ether2000.c - 664 sys sys 1015007950 2609
 sys/src/boot/pc/ether2114x.c - 664 sys sys 1144977462 38028
 sys/src/boot/pc/ether589.c - 664 sys sys 1144961189 4624
@@ -9106,9 +9114,11 @@ sys/src/boot/pc/ether8003.c - 664 sys sys 1015007950 6446
 sys/src/boot/pc/ether8139.c - 664 sys sys 1121393459 14823
 sys/src/boot/pc/ether8169.c - 664 sys sys 1156429147 21582
 sys/src/boot/pc/ether82557.c - 664 sys sys 1140802406 19090
+sys/src/boot/pc/ether82563.c - 664 sys sys 1178926666 24957
 sys/src/boot/pc/ether83815.c - 664 sys sys 1144961190 21993
 sys/src/boot/pc/ether8390.c - 664 sys sys 1112382847 16209
 sys/src/boot/pc/ether8390.h - 664 sys sys 1015007951 1392
+sys/src/boot/pc/etherdp83820.c - 664 sys sys 1178926667 28729
 sys/src/boot/pc/etherec2t.c - 664 sys sys 1015007951 3598
 sys/src/boot/pc/etherelnk3.c - 664 sys sys 1158012439 44736
 sys/src/boot/pc/etherelnk3x.c - 664 sys sys 1015007951 24989
@@ -9135,7 +9145,7 @@ sys/src/boot/pc/load.c - 664 sys sys 1175289729 9410
 sys/src/boot/pc/mbr.s - 664 sys sys 1015007953 6234
 sys/src/boot/pc/mem.h - 664 sys sys 1130887225 3371
 sys/src/boot/pc/memory.c - 664 sys sys 1019533021 10272
-sys/src/boot/pc/mkfile - 664 sys sys 1174077157 3132
+sys/src/boot/pc/mkfile - 664 sys sys 1178926615 3166
 sys/src/boot/pc/noether.c - 664 sys sys 1094674488 358
 sys/src/boot/pc/part.c - 664 sys sys 1114697151 7153
 sys/src/boot/pc/pbs.s - 664 sys sys 1143465387 8291
@@ -14524,14 +14534,14 @@ sys/src/fs/fs/dat.h - 664 sys sys 1140168010 611
 sys/src/fs/fs/fns.h - 664 sys sys 1172679929 2168
 sys/src/fs/fs/io.h - 664 sys sys 1157939329 6720
 sys/src/fs/fs/mem.h - 664 sys sys 1140168013 2909
-sys/src/fs/fs/mkfile - 664 sys sys 1157939040 1692
+sys/src/fs/fs/mkfile - 664 sys sys 1178933399 1708
 sys/src/fs/fs64 - 20000000775 sys sys 1157943044 0
 sys/src/fs/fs64/9fsfs64.c - 664 sys sys 1151399221 3612
 sys/src/fs/fs64/dat.h - 664 sys sys 1140168005 611
 sys/src/fs/fs64/fns.h - 664 sys sys 1172679929 2330
 sys/src/fs/fs64/io.h - 664 sys sys 1157939329 6720
 sys/src/fs/fs64/mem.h - 664 sys sys 1151398965 3041
-sys/src/fs/fs64/mkfile - 664 sys sys 1157938677 1632
+sys/src/fs/fs64/mkfile - 664 sys sys 1178933399 1648
 sys/src/fs/ip - 20000000775 sys sys 1140167931 0
 sys/src/fs/ip/arp.c - 664 sys sys 1097578954 8696
 sys/src/fs/ip/icmp.c - 664 sys sys 1015109981 991
@@ -14556,6 +14566,7 @@ sys/src/fs/pc/ether2114x.c - 664 sys sys 1015110044 31874
 sys/src/fs/pc/ether8139.c - 664 sys sys 1086569718 18552
 sys/src/fs/pc/ether8169.c - 664 sys sys 1157939501 25385
 sys/src/fs/pc/ether82557.c - 664 sys sys 1154067789 30710
+sys/src/fs/pc/ether82563.c - 664 sys sys 1178933417 26994
 sys/src/fs/pc/ether83815.c - 664 sys sys 1140335463 26764
 sys/src/fs/pc/ether83815.mii.c - 664 sys sys 1049156663 31622
 sys/src/fs/pc/etherdat.h - 664 sys sys 1157938367 72
@@ -14563,7 +14574,7 @@ sys/src/fs/pc/etherdp83820.c - 664 sys sys 1146355081 32045
 sys/src/fs/pc/etherelnk3.c - 664 sys sys 1015110054 42732
 sys/src/fs/pc/etherga620.c - 664 sys sys 1146785153 24748
 sys/src/fs/pc/etherga620fw.h - 664 sys sys 1032126775 222295
-sys/src/fs/pc/etherif.c - 664 sys sys 1157938488 6605
+sys/src/fs/pc/etherif.c - 664 sys sys 1178933411 6667
 sys/src/fs/pc/etherif.h - 664 sys sys 1015110057 730
 sys/src/fs/pc/etherigbe.c - 664 sys sys 1141208695 46676
 sys/src/fs/pc/etherm10g.c - 664 sys sys 1174594317 25743
@@ -14585,7 +14596,7 @@ sys/src/fs/pc/script.i - 664 sys sys 1015110072 27323
 sys/src/fs/pc/scsi.c - 664 sys sys 1151385561 8701
 sys/src/fs/pc/scsibuslogic.c - 664 sys sys 1015110077 28645
 sys/src/fs/pc/scsincr53c8xx.c - 664 sys sys 1146798658 53619
-sys/src/fs/pc/sdata.c - 664 sys sys 1151726802 64709
+sys/src/fs/pc/sdata.c - 664 sys sys 1178933365 64719
 sys/src/fs/pc/sdmv50xx.c - 664 sys sys 1151486130 39434
 sys/src/fs/pc/sdscsi.c - 664 sys sys 1146786984 7017
 sys/src/fs/pc/toy.c - 664 sys sys 1140167948 2166
@@ -14605,7 +14616,7 @@ sys/src/fs/port/console.c - 664 sys sys 1101627646 4886
 sys/src/fs/port/data.c - 664 sys sys 1140167986 4510
 sys/src/fs/port/dentry.c - 664 sys sys 1098156404 6345
 sys/src/fs/port/devcons.c - 664 sys sys 1157942528 4896
-sys/src/fs/port/devsd.c - 664 sys sys 1174081262 15110
+sys/src/fs/port/devsd.c - 664 sys sys 1178933380 15116
 sys/src/fs/port/fcmd.c - 664 sys sys 1146785267 1255
 sys/src/fs/port/fs.h - 664 sys sys 1140168001 682
 sys/src/fs/port/iobuf.c - 664 sys sys 1140167988 4956
@@ -15400,22 +15411,26 @@ sys/src/libmach/7obj.c - 664 sys sys 1148106912 2425
 sys/src/libmach/8.c - 664 sys sys 1168034569 2071
 sys/src/libmach/8db.c - 664 sys sys 1136322405 50889
 sys/src/libmach/8obj.c - 664 sys sys 1148106912 2258
+sys/src/libmach/9.c - 664 sys sys 1178892114 3625
+sys/src/libmach/9c - 20000000775 sys sys 1178892193 0
+sys/src/libmach/9c/9.out.h - 664 sys sys 1178892193 4669
+sys/src/libmach/9obj.c - 664 sys sys 1178892115 2747
 sys/src/libmach/access.c - 664 sys sys 1131289377 4588
 sys/src/libmach/elf.h - 664 sys sys 1131292881 2301
-sys/src/libmach/executable.c - 664 sys sys 1172172965 16228
+sys/src/libmach/executable.c - 664 sys sys 1178892113 16424
 sys/src/libmach/k.c - 664 sys sys 1138471021 3381
 sys/src/libmach/kdb.c - 664 sys sys 1136322404 21222
 sys/src/libmach/kobj.c - 664 sys sys 1148106912 2275
 sys/src/libmach/machdata.c - 664 sys sys 1131289377 8799
 sys/src/libmach/map.c - 664 sys sys 1131289376 3056
 sys/src/libmach/mips2ureg.h - 664 sys sys 1143821483 886
-sys/src/libmach/mkfile - 664 sys sys 1144151016 482
-sys/src/libmach/obj.c - 664 sys sys 1148106918 5986
+sys/src/libmach/mkfile - 664 sys sys 1178892111 493
+sys/src/libmach/obj.c - 664 sys sys 1178892113 6067
 sys/src/libmach/obj.h - 664 sys sys 1148170078 648
 sys/src/libmach/q.c - 664 sys sys 1158071179 3641
-sys/src/libmach/qdb.c - 664 sys sys 1136322404 27544
+sys/src/libmach/qdb.c - 664 sys sys 1178892114 30360
 sys/src/libmach/qobj.c - 664 sys sys 1148106912 2368
-sys/src/libmach/setmach.c - 664 sys sys 1172172965 2911
+sys/src/libmach/setmach.c - 664 sys sys 1178892113 3016
 sys/src/libmach/swap.c - 664 sys sys 1131289376 1056
 sys/src/libmach/sym.c - 664 sys sys 1138471012 26745
 sys/src/libmach/u.c - 664 sys sys 1138471017 3447
@@ -15816,6 +15831,17 @@ usr/glenda/lib/profile - 664 glenda glenda 1105128663 890
 usr/glenda/readme.acme - 664 glenda glenda 1019860628 4753
 usr/glenda/readme.rio - 664 glenda glenda 1019860628 6370
 usr/glenda/tmp - 20000000775 glenda glenda 1018802620 0
-386/bin/usb/usbmouse - 775 sys sys 1178853709 109673
-386/bin/auth/factotum - 775 sys sys 1178853707 321175
-386/bin/troff - 775 sys sys 1178853709 361158
+386/bin/acid - 775 sys sys 1178939750 405146
+386/bin/ar - 775 sys sys 1178939751 114363
+386/bin/snap - 775 sys sys 1178939753 316147
+386/bin/snapfs - 775 sys sys 1178939754 390312
+386/bin/file - 775 sys sys 1178939751 128125
+386/bin/kprof - 775 sys sys 1178939752 106496
+386/bin/ktrace - 775 sys sys 1178939752 124176
+386/bin/nm - 775 sys sys 1178939752 130155
+386/bin/prof - 775 sys sys 1178939753 111959
+386/bin/size - 775 sys sys 1178939753 79772
+386/bin/strip - 775 sys sys 1178939754 81761
+386/bin/aux/ms2 - 775 sys sys 1178939751 88464
+386/bin/tprof - 775 sys sys 1178939755 300947
+386/lib/libmach.a - 664 sys sys 1178939757 807390

+ 46 - 31
dist/replica/plan9.db

@@ -19,7 +19,7 @@
 386/bin/8l - 775 sys sys 1148500567 115711
 386/bin/9660srv - 775 sys sys 1168402261 104975
 386/bin/aan - 775 sys sys 1178568241 129834
-386/bin/acid - 775 sys sys 1172808055 401961
+386/bin/acid - 775 sys sys 1178939750 405146
 386/bin/acme - 775 sys sys 1178568242 430826
 386/bin/ape - 20000000775 sys sys 1016944144 0
 386/bin/ape/basename - 775 sys sys 1173754547 134719
@@ -38,7 +38,7 @@
 386/bin/ape/tar - 775 sys sys 1168402264 62184
 386/bin/ape/uname - 775 sys sys 1173754552 134895
 386/bin/aquarela - 775 sys sys 1178568243 337616
-386/bin/ar - 775 sys sys 1178568244 112312
+386/bin/ar - 775 sys sys 1178939751 114363
 386/bin/archfs - 775 sys sys 1178568244 146734
 386/bin/ascii - 775 sys sys 1168402265 64884
 386/bin/astro - 775 sys sys 1178568245 137403
@@ -118,7 +118,7 @@
 386/bin/aux/mklatinkbd - 775 sys sys 1168402282 64407
 386/bin/aux/mnihongo - 775 sys sys 1168402283 140020
 386/bin/aux/mouse - 775 sys sys 1148500597 44061
-386/bin/aux/ms2 - 775 sys sys 1172203053 87397
+386/bin/aux/ms2 - 775 sys sys 1178939751 88464
 386/bin/aux/msexceltables - 775 sys sys 1168402283 82921
 386/bin/aux/mswordstrings - 775 sys sys 1168402283 65541
 386/bin/aux/na - 775 sys sys 1168402284 154423
@@ -194,7 +194,7 @@
 386/bin/crop - 775 sys sys 1168402298 116374
 386/bin/cwfs - 775 sys sys 1178568265 365217
 386/bin/date - 775 sys sys 1178568265 41845
-386/bin/db - 775 sys sys 1172203054 346003
+386/bin/db - 775 sys sys 1178908092 345933
 386/bin/dc - 775 sys sys 1168402299 99260
 386/bin/dd - 775 sys sys 1159039156 45991
 386/bin/deroff - 775 sys sys 1168402299 74474
@@ -231,7 +231,7 @@
 386/bin/faces - 775 sys sys 1178568269 193152
 386/bin/factor - 775 sys sys 1168402307 61699
 386/bin/fcp - 775 sys sys 1168402307 82433
-386/bin/file - 775 sys sys 1172203054 125007
+386/bin/file - 775 sys sys 1178939751 128125
 386/bin/fmt - 775 sys sys 1168402307 65567
 386/bin/fortune - 775 sys sys 1168402308 67356
 386/bin/fossil - 20000000775 sys sys 1042005470 0
@@ -320,8 +320,8 @@
 386/bin/join - 775 sys sys 1168402330 114382
 386/bin/jpg - 775 sys sys 1168402330 174923
 386/bin/kbmap - 775 sys sys 1168402330 144015
-386/bin/kprof - 775 sys sys 1172203054 105429
-386/bin/ktrace - 775 sys sys 1172203054 123109
+386/bin/kprof - 775 sys sys 1178939752 106496
+386/bin/ktrace - 775 sys sys 1178939752 124176
 386/bin/lens - 775 sys sys 1168402332 151119
 386/bin/lex - 775 sys sys 1168402332 99261
 386/bin/lnfs - 775 sys sys 1168402333 99675
@@ -354,7 +354,7 @@
 386/bin/netstat - 775 sys sys 1169612032 85184
 386/bin/news - 775 sys sys 1168402341 71956
 386/bin/nfs - 775 sys sys 1178568297 320109
-386/bin/nm - 775 sys sys 1172203055 127037
+386/bin/nm - 775 sys sys 1178939752 130155
 386/bin/nntpfs - 775 sys sys 1178568298 165231
 386/bin/ns - 775 sys sys 1168402343 65492
 386/bin/p - 775 sys sys 1168402343 65220
@@ -372,7 +372,7 @@
 386/bin/ppm - 775 sys sys 1168402345 149765
 386/bin/pr - 775 sys sys 1178568298 76251
 386/bin/primes - 775 sys sys 1172289653 63329
-386/bin/prof - 775 sys sys 1172203055 110892
+386/bin/prof - 775 sys sys 1178939753 111959
 386/bin/proof - 775 sys sys 1176520492 179040
 386/bin/ps - 775 sys sys 1168402346 68812
 386/bin/pwd - 775 sys sys 1148500685 36932
@@ -401,10 +401,10 @@
 386/bin/sed - 775 sys sys 1168402348 89763
 386/bin/seq - 775 sys sys 1162241047 38441
 386/bin/sha1sum - 775 sys sys 1168402348 61366
-386/bin/size - 775 sys sys 1172203055 78705
+386/bin/size - 775 sys sys 1178939753 79772
 386/bin/sleep - 775 sys sys 1158088708 3875
-386/bin/snap - 775 sys sys 1178568301 312892
-386/bin/snapfs - 775 sys sys 1178568302 387057
+386/bin/snap - 775 sys sys 1178939753 316147
+386/bin/snapfs - 775 sys sys 1178939754 390312
 386/bin/sniffer - 775 sys sys 1038443185 99028
 386/bin/snoopy - 775 sys sys 1178568303 185244
 386/bin/sort - 775 sys sys 1178568303 81057
@@ -417,7 +417,7 @@
 386/bin/sshnet - 775 sys sys 1178568305 288132
 386/bin/stats - 775 sys sys 1168402350 190989
 386/bin/strings - 775 sys sys 1168402350 62855
-386/bin/strip - 775 sys sys 1172203055 80694
+386/bin/strip - 775 sys sys 1178939754 81761
 386/bin/sum - 775 sys sys 1148500691 39505
 386/bin/swap - 775 sys sys 1168402350 62373
 386/bin/syscall - 775 sys sys 1178568305 73944
@@ -437,7 +437,7 @@
 386/bin/topng - 775 sys sys 1178568307 137219
 386/bin/toppm - 775 sys sys 1168402354 165616
 386/bin/touch - 775 sys sys 1178568308 62586
-386/bin/tprof - 775 sys sys 1172203056 297762
+386/bin/tprof - 775 sys sys 1178939755 300947
 386/bin/tr - 775 sys sys 1168402355 62088
 386/bin/trace - 775 sys sys 1178568308 180414
 386/bin/troff - 775 sys sys 1178853709 361158
@@ -563,7 +563,7 @@
 386/lib/libhttpd.a - 664 sys sys 1177283321 99734
 386/lib/libip.a - 664 sys sys 1178826954 34710
 386/lib/libl.a - 664 sys sys 1168402367 5372
-386/lib/libmach.a - 664 sys sys 1173410637 785440
+386/lib/libmach.a - 664 sys sys 1178939757 807390
 386/lib/libmemdraw.a - 664 sys sys 1168402369 284092
 386/lib/libmemlayer.a - 664 sys sys 1168402369 47360
 386/lib/libmp.a - 664 sys sys 1176520528 79978
@@ -884,7 +884,7 @@ dist/replica - 20000000775 sys sys 1166743907 0
 dist/replica/cd - 664 sys sys 1149084099 922
 dist/replica/kfs - 664 sys sys 1019527929 237
 dist/replica/network - 775 sys sys 1139499513 956
-dist/replica/plan9.proto - 664 sys sys 1177628403 2840
+dist/replica/plan9.proto - 664 sys sys 1178910941 2871
 env - 20000000775 sys sys 1104813586 0
 fd - 20000000775 sys sys 1020896384 0
 lib - 20000000775 sys sys 1161442421 0
@@ -5442,6 +5442,13 @@ power/include/ureg.h - 664 sys sys 1032057837 997
 power/lib - 20000000775 sys sys 1039727909 0
 power/lib/ape - 20000000775 sys sys 1020896376 0
 power/mkfile - 664 sys sys 948141304 46
+power64 - 20000000775 sys sys 1178892028 0
+power64/bin - 20000000775 sys sys 1178891955 0
+power64/include - 20000000775 sys sys 1178892069 0
+power64/include/u.h - 664 sys sys 1178892069 2886
+power64/include/ureg.h - 664 sys sys 1178892069 915
+power64/lib - 20000000775 sys sys 1178891973 0
+power64/mkfile - 664 sys sys 1178892028 46
 rc - 20000000775 sys sys 1039727911 0
 rc/bin - 20000000775 sys sys 1158798931 0
 rc/bin/0a - 775 sys sys 1143293821 24
@@ -5985,7 +5992,7 @@ sys/games/lib/sudoku/images/9.bit - 664 sys sys 1117226542 537
 sys/include - 20000000775 sys sys 1072904891 0
 sys/include/9p.h - 664 sys sys 1134337548 4759
 sys/include/String.h - 664 sys sys 1091904425 1319
-sys/include/a.out.h - 664 sys sys 1148106925 1418
+sys/include/a.out.h - 664 sys sys 1178892101 1473
 sys/include/ape - 20000000775 sys sys 1070327361 0
 sys/include/ape/Plan9libnet.h - 664 sys sys 944948760 487
 sys/include/ape/ar.h - 664 sys sys 944948759 354
@@ -6072,7 +6079,7 @@ sys/include/ip.h - 664 sys sys 1178768502 2597
 sys/include/keyboard.h - 664 sys sys 1131637696 865
 sys/include/libc.h - 664 sys sys 1168306860 19851
 sys/include/libsec.h - 664 sys sys 1124709121 9345
-sys/include/mach.h - 664 sys sys 1143814376 8641
+sys/include/mach.h - 664 sys sys 1178892102 8758
 sys/include/memdraw.h - 664 sys sys 1091904419 5645
 sys/include/memlayer.h - 664 sys sys 1051031022 1851
 sys/include/mouse.h - 664 sys sys 1035232010 1003
@@ -8036,6 +8043,7 @@ sys/src/9/pc/ether8139.c - 664 sys sys 1175019929 18584
 sys/src/9/pc/ether8169.c - 664 sys sys 1172259757 25466
 sys/src/9/pc/ether82543gc.c - 664 sys sys 1131290377 32294
 sys/src/9/pc/ether82557.c - 664 sys sys 1153082663 30197
+sys/src/9/pc/ether82563.c - 664 sys sys 1178932992 32729
 sys/src/9/pc/ether83815.c - 664 sys sys 1172259521 26346
 sys/src/9/pc/ether8390.c - 664 sys sys 1131290377 17702
 sys/src/9/pc/ether8390.h - 664 sys sys 1015014517 1511
@@ -8150,7 +8158,7 @@ sys/src/9/port/debugalloc.c - 664 sys sys 1014931171 10402
 sys/src/9/port/dev.c - 664 sys sys 1146151714 8177
 sys/src/9/port/devaudio.c - 664 sys sys 1170456648 21199
 sys/src/9/port/devbridge.c - 664 sys sys 1055688301 24308
-sys/src/9/port/devcap.c - 664 sys sys 1178320320 4160
+sys/src/9/port/devcap.c - 664 sys sys 1178886040 4141
 sys/src/9/port/devcons.c - 664 sys sys 1176658321 22943
 sys/src/9/port/devdraw.c - 664 sys sys 1147023550 44447
 sys/src/9/port/devdup.c - 664 sys sys 1014931172 2332
@@ -9097,7 +9105,7 @@ sys/src/boot/pc/dosboot.c - 664 sys sys 1097716791 11240
 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/error.h - 664 sys sys 1015007950 3081
-sys/src/boot/pc/ether.c - 664 sys sys 1174077249 5326
+sys/src/boot/pc/ether.c - 664 sys sys 1178926685 5380
 sys/src/boot/pc/ether2000.c - 664 sys sys 1015007950 2609
 sys/src/boot/pc/ether2114x.c - 664 sys sys 1144977462 38028
 sys/src/boot/pc/ether589.c - 664 sys sys 1144961189 4624
@@ -9106,9 +9114,11 @@ sys/src/boot/pc/ether8003.c - 664 sys sys 1015007950 6446
 sys/src/boot/pc/ether8139.c - 664 sys sys 1121393459 14823
 sys/src/boot/pc/ether8169.c - 664 sys sys 1156429147 21582
 sys/src/boot/pc/ether82557.c - 664 sys sys 1140802406 19090
+sys/src/boot/pc/ether82563.c - 664 sys sys 1178926666 24957
 sys/src/boot/pc/ether83815.c - 664 sys sys 1144961190 21993
 sys/src/boot/pc/ether8390.c - 664 sys sys 1112382847 16209
 sys/src/boot/pc/ether8390.h - 664 sys sys 1015007951 1392
+sys/src/boot/pc/etherdp83820.c - 664 sys sys 1178926667 28729
 sys/src/boot/pc/etherec2t.c - 664 sys sys 1015007951 3598
 sys/src/boot/pc/etherelnk3.c - 664 sys sys 1158012439 44736
 sys/src/boot/pc/etherelnk3x.c - 664 sys sys 1015007951 24989
@@ -9135,7 +9145,7 @@ sys/src/boot/pc/load.c - 664 sys sys 1175289729 9410
 sys/src/boot/pc/mbr.s - 664 sys sys 1015007953 6234
 sys/src/boot/pc/mem.h - 664 sys sys 1130887225 3371
 sys/src/boot/pc/memory.c - 664 sys sys 1019533021 10272
-sys/src/boot/pc/mkfile - 664 sys sys 1174077157 3132
+sys/src/boot/pc/mkfile - 664 sys sys 1178926615 3166
 sys/src/boot/pc/noether.c - 664 sys sys 1094674488 358
 sys/src/boot/pc/part.c - 664 sys sys 1114697151 7153
 sys/src/boot/pc/pbs.s - 664 sys sys 1143465387 8291
@@ -14524,14 +14534,14 @@ sys/src/fs/fs/dat.h - 664 sys sys 1140168010 611
 sys/src/fs/fs/fns.h - 664 sys sys 1172679929 2168
 sys/src/fs/fs/io.h - 664 sys sys 1157939329 6720
 sys/src/fs/fs/mem.h - 664 sys sys 1140168013 2909
-sys/src/fs/fs/mkfile - 664 sys sys 1157939040 1692
+sys/src/fs/fs/mkfile - 664 sys sys 1178933399 1708
 sys/src/fs/fs64 - 20000000775 sys sys 1157943044 0
 sys/src/fs/fs64/9fsfs64.c - 664 sys sys 1151399221 3612
 sys/src/fs/fs64/dat.h - 664 sys sys 1140168005 611
 sys/src/fs/fs64/fns.h - 664 sys sys 1172679929 2330
 sys/src/fs/fs64/io.h - 664 sys sys 1157939329 6720
 sys/src/fs/fs64/mem.h - 664 sys sys 1151398965 3041
-sys/src/fs/fs64/mkfile - 664 sys sys 1157938677 1632
+sys/src/fs/fs64/mkfile - 664 sys sys 1178933399 1648
 sys/src/fs/ip - 20000000775 sys sys 1140167931 0
 sys/src/fs/ip/arp.c - 664 sys sys 1097578954 8696
 sys/src/fs/ip/icmp.c - 664 sys sys 1015109981 991
@@ -14556,6 +14566,7 @@ sys/src/fs/pc/ether2114x.c - 664 sys sys 1015110044 31874
 sys/src/fs/pc/ether8139.c - 664 sys sys 1086569718 18552
 sys/src/fs/pc/ether8169.c - 664 sys sys 1157939501 25385
 sys/src/fs/pc/ether82557.c - 664 sys sys 1154067789 30710
+sys/src/fs/pc/ether82563.c - 664 sys sys 1178933417 26994
 sys/src/fs/pc/ether83815.c - 664 sys sys 1140335463 26764
 sys/src/fs/pc/ether83815.mii.c - 664 sys sys 1049156663 31622
 sys/src/fs/pc/etherdat.h - 664 sys sys 1157938367 72
@@ -14563,7 +14574,7 @@ sys/src/fs/pc/etherdp83820.c - 664 sys sys 1146355081 32045
 sys/src/fs/pc/etherelnk3.c - 664 sys sys 1015110054 42732
 sys/src/fs/pc/etherga620.c - 664 sys sys 1146785153 24748
 sys/src/fs/pc/etherga620fw.h - 664 sys sys 1032126775 222295
-sys/src/fs/pc/etherif.c - 664 sys sys 1157938488 6605
+sys/src/fs/pc/etherif.c - 664 sys sys 1178933411 6667
 sys/src/fs/pc/etherif.h - 664 sys sys 1015110057 730
 sys/src/fs/pc/etherigbe.c - 664 sys sys 1141208695 46676
 sys/src/fs/pc/etherm10g.c - 664 sys sys 1174594317 25743
@@ -14585,7 +14596,7 @@ sys/src/fs/pc/script.i - 664 sys sys 1015110072 27323
 sys/src/fs/pc/scsi.c - 664 sys sys 1151385561 8701
 sys/src/fs/pc/scsibuslogic.c - 664 sys sys 1015110077 28645
 sys/src/fs/pc/scsincr53c8xx.c - 664 sys sys 1146798658 53619
-sys/src/fs/pc/sdata.c - 664 sys sys 1151726802 64709
+sys/src/fs/pc/sdata.c - 664 sys sys 1178933365 64719
 sys/src/fs/pc/sdmv50xx.c - 664 sys sys 1151486130 39434
 sys/src/fs/pc/sdscsi.c - 664 sys sys 1146786984 7017
 sys/src/fs/pc/toy.c - 664 sys sys 1140167948 2166
@@ -14605,7 +14616,7 @@ sys/src/fs/port/console.c - 664 sys sys 1101627646 4886
 sys/src/fs/port/data.c - 664 sys sys 1140167986 4510
 sys/src/fs/port/dentry.c - 664 sys sys 1098156404 6345
 sys/src/fs/port/devcons.c - 664 sys sys 1157942528 4896
-sys/src/fs/port/devsd.c - 664 sys sys 1174081262 15110
+sys/src/fs/port/devsd.c - 664 sys sys 1178933380 15116
 sys/src/fs/port/fcmd.c - 664 sys sys 1146785267 1255
 sys/src/fs/port/fs.h - 664 sys sys 1140168001 682
 sys/src/fs/port/iobuf.c - 664 sys sys 1140167988 4956
@@ -15400,22 +15411,26 @@ sys/src/libmach/7obj.c - 664 sys sys 1148106912 2425
 sys/src/libmach/8.c - 664 sys sys 1168034569 2071
 sys/src/libmach/8db.c - 664 sys sys 1136322405 50889
 sys/src/libmach/8obj.c - 664 sys sys 1148106912 2258
+sys/src/libmach/9.c - 664 sys sys 1178892114 3625
+sys/src/libmach/9c - 20000000775 sys sys 1178892193 0
+sys/src/libmach/9c/9.out.h - 664 sys sys 1178892193 4669
+sys/src/libmach/9obj.c - 664 sys sys 1178892115 2747
 sys/src/libmach/access.c - 664 sys sys 1131289377 4588
 sys/src/libmach/elf.h - 664 sys sys 1131292881 2301
-sys/src/libmach/executable.c - 664 sys sys 1172172965 16228
+sys/src/libmach/executable.c - 664 sys sys 1178892113 16424
 sys/src/libmach/k.c - 664 sys sys 1138471021 3381
 sys/src/libmach/kdb.c - 664 sys sys 1136322404 21222
 sys/src/libmach/kobj.c - 664 sys sys 1148106912 2275
 sys/src/libmach/machdata.c - 664 sys sys 1131289377 8799
 sys/src/libmach/map.c - 664 sys sys 1131289376 3056
 sys/src/libmach/mips2ureg.h - 664 sys sys 1143821483 886
-sys/src/libmach/mkfile - 664 sys sys 1144151016 482
-sys/src/libmach/obj.c - 664 sys sys 1148106918 5986
+sys/src/libmach/mkfile - 664 sys sys 1178892111 493
+sys/src/libmach/obj.c - 664 sys sys 1178892113 6067
 sys/src/libmach/obj.h - 664 sys sys 1148170078 648
 sys/src/libmach/q.c - 664 sys sys 1158071179 3641
-sys/src/libmach/qdb.c - 664 sys sys 1136322404 27544
+sys/src/libmach/qdb.c - 664 sys sys 1178892114 30360
 sys/src/libmach/qobj.c - 664 sys sys 1148106912 2368
-sys/src/libmach/setmach.c - 664 sys sys 1172172965 2911
+sys/src/libmach/setmach.c - 664 sys sys 1178892113 3016
 sys/src/libmach/swap.c - 664 sys sys 1131289376 1056
 sys/src/libmach/sym.c - 664 sys sys 1138471012 26745
 sys/src/libmach/u.c - 664 sys sys 1138471017 3447

+ 49 - 0
dist/replica/plan9.log

@@ -48814,3 +48814,52 @@
 1178854206 0 c 386/bin/usb/usbmouse - 775 sys sys 1178853709 109673
 1178854206 1 c 386/bin/auth/factotum - 775 sys sys 1178853707 321175
 1178854206 2 c 386/bin/troff - 775 sys sys 1178853709 361158
+1178886605 0 c sys/src/9/port/devcap.c - 664 sys sys 1178886040 4141
+1178892007 0 a sys/src/libmach/9.c - 664 sys sys 1178892114 3625
+1178892007 1 a sys/src/libmach/9obj.c - 664 sys sys 1178892115 2747
+1178892007 2 c sys/src/libmach/executable.c - 664 sys sys 1178892113 16424
+1178892007 3 c sys/src/libmach/mkfile - 664 sys sys 1178892111 493
+1178892007 4 c sys/src/libmach/obj.c - 664 sys sys 1178892113 6067
+1178892007 5 c sys/src/libmach/qdb.c - 664 sys sys 1178892114 30360
+1178892007 6 c sys/src/libmach/setmach.c - 664 sys sys 1178892113 3016
+1178893806 0 c 386/lib/libmach.a - 664 sys sys 1178892112 809418
+1178893806 1 c sys/include/a.out.h - 664 sys sys 1178892101 1473
+1178893806 2 c sys/include/mach.h - 664 sys sys 1178892102 8758
+1178893806 3 a sys/src/libmach/9c - 20000000775 sys sys 1178892193 0
+1178893806 4 a sys/src/libmach/9c/9.out.h - 664 sys sys 1178892193 4669
+1178908216 0 c 386/bin/db - 775 sys sys 1178908092 345933
+1178911812 0 a power64 - 20000000775 sys sys 1178892028 0
+1178911812 1 a power64/bin - 20000000775 sys sys 1178891955 0
+1178911812 2 a power64/include - 20000000775 sys sys 1178892069 0
+1178911812 3 a power64/include/u.h - 664 sys sys 1178892069 2886
+1178911812 4 a power64/include/ureg.h - 664 sys sys 1178892069 915
+1178911812 5 a power64/lib - 20000000775 sys sys 1178891973 0
+1178911812 6 a power64/mkfile - 664 sys sys 1178892028 46
+1178911812 7 c dist/replica/plan9.proto - 664 sys sys 1178910941 2871
+1178928008 0 a sys/src/9/pc/ether82563.c - 664 sys sys 1178927170 33008
+1178928008 1 c sys/src/boot/pc/ether.c - 664 sys sys 1178926685 5380
+1178928008 2 c sys/src/boot/pc/mkfile - 664 sys sys 1178926615 3166
+1178928008 3 a sys/src/boot/pc/ether82563.c - 664 sys sys 1178926666 24957
+1178928008 4 a sys/src/boot/pc/etherdp83820.c - 664 sys sys 1178926667 28729
+1178929806 0 c sys/src/9/pc/ether82563.c - 664 sys sys 1178928293 32728
+1178933406 0 c sys/src/9/pc/ether82563.c - 664 sys sys 1178932992 32729
+1178933406 1 c sys/src/fs/fs/mkfile - 664 sys sys 1178933399 1708
+1178933406 2 c sys/src/fs/fs64/mkfile - 664 sys sys 1178933399 1648
+1178933406 3 a sys/src/fs/pc/ether82563.c - 664 sys sys 1178933417 26994
+1178933406 4 c sys/src/fs/pc/etherif.c - 664 sys sys 1178933411 6667
+1178933406 5 c sys/src/fs/pc/sdata.c - 664 sys sys 1178933365 64719
+1178933406 6 c sys/src/fs/port/devsd.c - 664 sys sys 1178933380 15116
+1178940604 0 c 386/bin/acid - 775 sys sys 1178939750 405146
+1178940604 1 c 386/bin/ar - 775 sys sys 1178939751 114363
+1178940604 2 c 386/bin/snap - 775 sys sys 1178939753 316147
+1178940604 3 c 386/bin/snapfs - 775 sys sys 1178939754 390312
+1178940604 4 c 386/bin/file - 775 sys sys 1178939751 128125
+1178940604 5 c 386/bin/kprof - 775 sys sys 1178939752 106496
+1178940604 6 c 386/bin/ktrace - 775 sys sys 1178939752 124176
+1178940604 7 c 386/bin/nm - 775 sys sys 1178939752 130155
+1178940604 8 c 386/bin/prof - 775 sys sys 1178939753 111959
+1178940604 9 c 386/bin/size - 775 sys sys 1178939753 79772
+1178940604 10 c 386/bin/strip - 775 sys sys 1178939754 81761
+1178940604 11 c 386/bin/aux/ms2 - 775 sys sys 1178939751 88464
+1178940604 12 c 386/bin/tprof - 775 sys sys 1178939755 300947
+1178940604 13 c 386/lib/libmach.a - 664 sys sys 1178939757 807390

+ 2 - 0
dist/replica/plan9.proto

@@ -45,6 +45,8 @@ mips	- sys sys
 	+	- sys sys
 power	- sys sys
 	+	- sys sys
+power64	- sys sys
+	+	- sys sys
 sparc	- sys sys
 	+	- sys sys
 sparc64	- sys sys

+ 87 - 0
power64/include/u.h

@@ -0,0 +1,87 @@
+#define nil		((void*)0)
+typedef	unsigned short	ushort;
+typedef	unsigned char	uchar;
+typedef	unsigned long	ulong;
+typedef	unsigned int	uint;
+typedef	signed char	schar;
+typedef	long long	vlong;
+typedef	unsigned long long uvlong;
+typedef unsigned long long uintptr;
+typedef unsigned long	usize;
+typedef	ushort		Rune;
+typedef 	union FPdbleword FPdbleword;
+typedef uintptr	jmp_buf[2];
+#define	JMPBUFSP	0
+#define	JMPBUFPC	1
+#define	JMPBUFDPC	0
+typedef unsigned int	mpdigit;	/* for /sys/include/mp.h */
+typedef unsigned char u8int;
+typedef unsigned short u16int;
+typedef unsigned int	u32int;
+typedef unsigned long long u64int;
+
+/* FPSCR */
+#define	FPSFX	(1<<31)	/* exception summary (sticky) */
+#define	FPSEX	(1<<30)	/* enabled exception summary */
+#define	FPSVX	(1<<29)	/* invalid operation exception summary */
+#define	FPSOX	(1<<28)	/* overflow exception OX (sticky) */
+#define	FPSUX	(1<<27)	/* underflow exception UX (sticky) */
+#define	FPSZX	(1<<26)	/* zero divide exception ZX (sticky) */
+#define	FPSXX	(1<<25)	/* inexact exception XX (sticky) */
+#define	FPSVXSNAN (1<<24)	/* invalid operation exception for SNaN (sticky) */
+#define	FPSVXISI	(1<<23)	/* invalid operation exception for ∞-∞ (sticky) */
+#define	FPSVXIDI	(1<<22)	/* invalid operation exception for ∞/∞ (sticky) */
+#define	FPSVXZDZ (1<<21)	/* invalid operation exception for 0/0 (sticky) */
+#define	FPSVXIMZ	(1<<20)	/* invalid operation exception for ∞*0 (sticky) */
+#define	FPSVXVC	(1<<19)	/* invalid operation exception for invalid compare (sticky) */
+#define	FPSFR	(1<<18)	/* fraction rounded */
+#define	FPSFI	(1<<17)	/* fraction inexact */
+#define	FPSFPRF	(1<<16)	/* floating point result class */
+#define	FPSFPCC	(0xF<<12)	/* <, >, =, unordered */
+#define	FPVXCVI	(1<<8)	/* enable exception for invalid integer convert (sticky) */
+#define	FPVE	(1<<7)	/* invalid operation exception enable */
+#define	FPOVFL	(1<<6)	/* enable overflow exceptions */
+#define	FPUNFL	(1<<5)	/* enable underflow */
+#define	FPZDIV	(1<<4)	/* enable zero divide */
+#define	FPINEX	(1<<3)	/* enable inexact exceptions */
+#define	FPRMASK	(3<<0)	/* rounding mode */
+#define	FPRNR	(0<<0)
+#define	FPRZ	(1<<0)
+#define	FPRPINF	(2<<0)
+#define	FPRNINF	(3<<0)
+#define	FPPEXT	0
+#define	FPPSGL	0
+#define	FPPDBL	0
+#define	FPPMASK	0
+#define	FPINVAL	FPVE
+
+#define	FPAOVFL	FPSOX
+#define	FPAINEX	FPSXX
+#define	FPAUNFL	FPSUX
+#define	FPAZDIV	FPSZX
+#define	FPAINVAL	FPSVX
+
+union FPdbleword
+{
+	double	x;
+	struct {	/* big endian */
+		ulong hi;
+		ulong lo;
+	};
+};
+
+typedef	char*	va_list;
+#define va_start(list, start) list =\
+	(sizeof(start) < 8?\
+		(char*)((vlong*)&(start)+1):\
+		(char*)(&(start)+1))
+#define va_end(list)\
+	USED(list)
+#define va_arg(list, mode)\
+	((sizeof(mode) == 1)?\
+		((mode*)(list += 8))[-1]:\
+	(sizeof(mode) == 2)?\
+		((mode*)(list += 8))[-1]:\
+	(sizeof(mode) == 4)?\
+		((mode*)(list += 8))[-1]:\
+		((mode*)(list += sizeof(mode)))[-1])

+ 44 - 0
power64/include/ureg.h

@@ -0,0 +1,44 @@
+struct Ureg
+{
+/*  0*/	u64int	cause;	/* trap or interrupt vector */
+/*  8*/	u64int	msr; /* SRR1 */
+/* 16*/	u64int	pc;	/* SRR0 */
+/* 24*/	u64int	unused;
+/* 32*/	u64int	lr;
+/* 36*/	u32int	pad;
+/* 40*/	u32int	cr;
+/* 48*/	u64int	xer;
+/* 56*/	u64int	ctr;
+/* 64*/	u64int	r0;
+/* 72*/	union{ u64int r1;	u64int	sp;	u64int	usp; };
+/* 80*/	u64int	r2;
+/* 88*/	u64int	r3;
+/* 96*/	u64int	r4;
+/*104*/	u64int	r5;
+/*112*/	u64int	r6;
+/*120*/	u64int	r7;
+/*128*/	u64int	r8;
+/*136*/	u64int	r9;
+/*144*/	u64int	r10;
+/*152*/	u64int	r11;
+/*160*/	u64int	r12;
+/*168*/	u64int	r13;
+/*176*/	u64int	r14;
+/*184*/	u64int	r15;
+/*192*/	u64int	r16;
+/*200*/	u64int	r17;
+/*208*/	u64int	r18;
+/*216*/	u64int	r19;
+/*224*/	u64int	r20;
+/*232*/	u64int	r21;
+/*240*/	u64int	r22;
+/*248*/	u64int	r23;
+/*256*/	u64int	r24;
+/*264*/	u64int	r25;
+/*272*/	u64int	r26;
+/*280*/	u64int	r27;
+/*288*/	u64int	r28;
+/*296*/	u64int	r29;
+/*304*/	u64int	r30;
+/*312*/	u64int	r31;
+};

+ 6 - 0
power64/mkfile

@@ -0,0 +1,6 @@
+</sys/src/mkfile.proto
+
+CC=9c
+LD=9l
+O=9
+AS=9a

+ 2 - 1
sys/include/a.out.h

@@ -29,9 +29,10 @@ struct	Exec
 #define	P_MAGIC		_MAGIC(0, 24)		/* mips 3000 LE */
 #define	U_MAGIC		_MAGIC(0, 25)		/* sparc64 */
 #define	S_MAGIC		_MAGIC(HDR_MAGIC, 26)	/* amd64 */
+#define	T_MAGIC		_MAGIC(HDR_MAGIC, 27)	/* powerpc64 */
 
 #define	MIN_MAGIC	8
-#define	MAX_MAGIC	26			/* <= 90 */
+#define	MAX_MAGIC	27			/* <= 90 */
 
 #define	DYN_MAGIC	0x80000000		/* dlm */
 

+ 7 - 1
sys/include/mach.h

@@ -14,7 +14,8 @@
  *		sparc64,
  *		mips2 (R4000)
  *		arm
- *		power pc
+ *		powerpc,
+ *		powerpc64
  *		alpha
  */
 enum
@@ -34,6 +35,7 @@ enum
 	NMIPS,
 	MSPARC64,
 	MAMD64,
+	MPOWER64,
 				/* types of executables */
 	FNONE = 0,		/* unidentified */
 	FMIPS,			/* v.out */
@@ -61,6 +63,8 @@ enum
 	FSPARC64,		/* u.out */
 	FAMD64,			/* 6.out */
 	FAMD64B,		/* 6.out bootable */
+	FPOWER64,		/* 9.out */
+	FPOWER64B,		/* 9.out bootable */
 
 	ANONE = 0,		/* dissembler types */
 	AMIPS,
@@ -77,6 +81,7 @@ enum
 	AALPHA,
 	ASPARC64,
 	AAMD64,
+	APOWER64,
 				/* object file types */
 	Obj68020 = 0,		/* .2 */
 	ObjSparc,		/* .k */
@@ -93,6 +98,7 @@ enum
 	ObjSparc64,		/* .u */
 	ObjAmd64,		/* .6 */
 	ObjSpim,		/* .0 */
+	ObjPower64,		/* .9 */
 	Maxobjtype,
 
 	CNONE  = 0,		/* symbol table classes */

+ 1394 - 0
sys/src/9/pc/ether82563.c

@@ -0,0 +1,1394 @@
+/*
+ * Intel 82563 Gigabit Ethernet Controller
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+
+
+/*
+ * these are in the order they appear in the manual, not numeric order.
+ * It was too hard to find them in the book. Ref 21489, rev 2.6
+ */
+
+enum {
+	/* General */
+
+	Ctrl		= 0x00000000,	/* Device Control */
+	Status		= 0x00000008,	/* Device Status */
+	Eec		= 0x00000010,	/* EEPROM/Flash Control/Data */
+	Eerd		= 0x00000014,	/* EEPROM Read */
+	Ctrlext		= 0x00000018,	/* Extended Device Control */
+	Fla		= 0x0000001c,	/* Flash Access */
+	Mdic		= 0x00000020,	/* MDI Control */
+	Seresctl	= 0x00000024,	/* Serdes ana */
+	Fcal		= 0x00000028,	/* Flow Control Address Low */
+	Fcah		= 0x0000002C,	/* Flow Control Address High */
+	Fct		= 0x00000030,	/* Flow Control Type */
+	Kumctrlsta	= 0x00000034,	/* Kumeran Controll and Status Register */
+	Vet		= 0x00000038,	/* VLAN EtherType */
+	Fcttv		= 0x00000170,	/* Flow Control Transmit Timer Value */
+	Txcw		= 0x00000178,	/* Transmit Configuration Word */
+	Rxcw		= 0x00000180,	/* Receive Configuration Word */
+	Ledctl		= 0x00000E00,	/* LED control */
+	Pba		= 0x00001000,	/* Packet Buffer Allocation */
+
+	/* Interrupt */
+
+	Icr		= 0x000000C0,	/* Interrupt Cause Read */
+	Ics		= 0x000000C8,	/* Interrupt Cause Set */
+	Ims		= 0x000000D0,	/* Interrupt Mask Set/Read */
+	Imc		= 0x000000D8,	/* Interrupt mask Clear */
+	Iam		= 0x000000E0,	/* Interrupt acknowledge Auto Mask */
+
+	/* Receive */
+
+	Rctl		= 0x00000100,	/* Control */
+	Ert		= 0x00002008,	/* Early Receive Threshold (573[EVL] only) */
+	Fcrtl		= 0x00002160,	/* Flow Control RX Threshold Low */
+	Fcrth		= 0x00002168,	/* Flow Control Rx Threshold High */
+	Psrctl		= 0x00002170,	/* Packet Split Receive Control */
+	Rdbal		= 0x00002800,	/* Rdesc Base Address Low Queue 0 */
+	Rdbah		= 0x00002804,	/* Rdesc Base Address High Queue 0 */
+	Rdlen		= 0x00002808,	/* Descriptor Length Queue 0 */
+	Rdh		= 0x00002810,	/* Descriptor Head Queue 0 */
+	Rdt		= 0x00002818,	/* Descriptor Tail Queue 0 */
+	Rdtr		= 0x00002820,	/* Descriptor Timer Ring */
+	Rxdctl		= 0x00002828,	/* Descriptor Control */
+	Radv		= 0x0000282C,	/* Interrupt Absolute Delay Timer */
+	Rdbal1		= 0x00002900,	/* Rdesc Base Address Low Queue 1 */
+	Rdbah1		= 0x00002804,	/* Rdesc Base Address High Queue 1 */
+	Rdlen1		= 0x00002908,	/* Descriptor Length Queue 1 */
+	Rdh1		= 0x00002910,	/* Descriptor Head Queue 1 */
+	Rdt1		= 0x00002918,	/* Descriptor Tail Queue 1 */
+	Rxdctl1		= 0x00002928,	/* Descriptor Control Queue 1 */
+	Rsrpd		= 0x00002c00,	/* Small Packet Detect */
+	Raid		= 0x00002c08,	/* ACK interrupt delay */
+	Cpuvec		= 0x00002c10,	/* CPU Vector */
+	Rxcsum		= 0x00005000,	/* Checksum Control */
+	Rfctl		= 0x00005008,	/* Filter Control */
+	Mta		= 0x00005200,	/* Multicast Table Array */
+	Ral		= 0x00005400,	/* Address Low */
+	Rah		= 0x00005404,	/* Address High */
+	Vfta		= 0x00005600,	/* VLAN Filter Table Array */
+	Mrqc		= 0x00005818,	/* Multiple Receive Queues Command */
+	Rssim		= 0x00005864,	/* RSS Interrupt Mask */
+	Rssir		= 0x00005868,	/* RSS Interrupt Request */
+	Reta		= 0x00005c00,	/* Redirection Table */
+	Rssrk		= 0x00005c80,	/* RSS Random Key */
+
+	/* Transmit */
+
+	Tctl		= 0x00000400,	/* Control */
+	Tipg		= 0x00000410,	/* IPG */
+	Tdbal		= 0x00003800,	/* Tdesc Base Address Low */
+	Tdbah		= 0x00003804,	/* Tdesc Base Address High */
+	Tdlen		= 0x00003808,	/* Descriptor Length */
+	Tdh		= 0x00003810,	/* Descriptor Head */
+	Tdt		= 0x00003818,	/* Descriptor Tail */
+	Tidv		= 0x00003820,	/* Interrupt Delay Value */
+	Txdctl		= 0x00003828,	/* Descriptor Control */
+	Tadv		= 0x0000382C,	/* Interrupt Absolute Delay Timer */
+	Tarc0		= 0x00003840,	/* Arbitration Counter Queue 0 */
+	Tdbal1		= 0x00003900,	/* Descriptor Base Low Queue 1 */
+	Tdbah1		= 0x00003904,	/* Descriptor Base High Queue 1 */
+	Tdlen1		= 0x00003908,	/* Descriptor Length Queue 1 */
+	Tdh1		= 0x00003910,	/* Descriptor Head Queue 1 */
+	Tdt1		= 0x00003918,	/* Descriptor Tail Queue 1 */
+	Txdctl1		= 0x00003928,	/* Descriptor Control 1 */
+	Tarc1		= 0x00003940,	/* Arbitration Counter Queue 1 */
+
+	/* Statistics */
+
+	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,
+
+};
+
+enum {					/* Ctrl */
+	GIOmd		= (1<<2),	/* BIO master disable */
+	Lrst		= (1<<3),	/* link reset */
+	Slu		= (1<<6),	/* Set Link Up */
+	SspeedMASK	= (3<<8),	/* Speed Selection */
+	SspeedSHIFT	= 8,
+	Sspeed10	= 0x00000000,	/* 10Mb/s */
+	Sspeed100	= 0x00000100,	/* 100Mb/s */
+	Sspeed1000	= 0x00000200,	/* 1000Mb/s */
+	Frcspd		= (1<<11),	/* Force Speed */
+	Frcdplx		= (1<<12),	/* Force Duplex */
+	SwdpinsloMASK	= 0x003C0000,	/* Software Defined Pins - lo nibble */
+	SwdpinsloSHIFT	= 18,
+	SwdpioloMASK	= 0x03C00000,	/* Software Defined Pins - I or O */
+	SwdpioloSHIFT	= 22,
+	Devrst		= (1<<26),	/* Device Reset */
+	Rfce		= (1<<27),	/* Receive Flow Control Enable */
+	Tfce		= (1<<28),	/* Transmit Flow Control Enable */
+	Vme		= (1<<30),	/* VLAN Mode Enable */
+	Phy_rst		= (1<<31),	/* Phy Reset */
+};
+
+enum {					/* Status */
+	Lu		= (1<<1),	/* Link Up */
+	Lanid		= (3<<2),	/* mask for Lan ID.
+	Txoff		= (1<<4),	/* Transmission Paused */
+	Tbimode		= (1<<5),	/* TBI Mode Indication */
+	SpeedMASK	= 0x000000C0,
+	Speed10		= 0x00000000,	/* 10Mb/s */
+	Speed100	= 0x00000040,	/* 100Mb/s */
+	Speed1000	= 0x00000080,	/* 1000Mb/s */
+	Phyra		= (1<<10),	/* PHY Reset Asserted */
+	GIOme		= (1<<19),	/* GIO Master Enable Status */
+};
+
+enum {					/* Ctrl and Status */
+	Fd		= 0x00000001,	/* Full-Duplex */
+	AsdvMASK	= 0x00000300,
+	Asdv10		= 0x00000000,	/* 10Mb/s */
+	Asdv100		= 0x00000100,	/* 100Mb/s */
+	Asdv1000	= 0x00000200,	/* 1000Mb/s */
+};
+
+enum {					/* Eec */
+	Sk		= (1<<0),	/* Clock input to the EEPROM */
+	Cs		= (1<<1),	/* Chip Select */
+	Di		= (1<<2),	/* Data Input to the EEPROM */
+	Do		= (1<<3),	/* Data Output from the EEPROM */
+	Areq		= (1<<6),	/* EEPROM Access Request */
+	Agnt		= (1<<7),	/* EEPROM Access Grant */
+};
+
+enum {					/* Eerd */
+	ee_start	= (1<<0),	/* Start Read */
+	ee_done		= (1<<1),	/* Read done */
+	ee_addr		= (0xfff8<<2),	/* Read address [15:2] */
+	ee_data		= (0xffff<<16),	/* Read Data; Data returned from eeprom/nvm */
+};
+
+enum {					/* Ctrlext */
+	Asdchk		= (1<<12),	/* ASD Check */
+	Eerst		= (1<<13),	/* EEPROM Reset */
+	Spdbyps		= (1<<15),	/* Speed Select Bypass */
+};
+
+enum {					/* EEPROM content offsets */
+	Ea		= 0x00,		/* Ethernet Address */
+	Cf		= 0x03,		/* Compatibility Field */
+	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,
+};
+
+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 */
+	Bsize8192	= 0x00020000, 	/* Bsex = 1 */
+	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 {					/* Receive Delay Timer Ring */
+	DelayMASK	= 0x0000FFFF,	/* delay timer in 1.024nS increments */
+	DelaySHIFT	= 0,
+	Fpd		= 0x80000000,	/* Flush partial Descriptor Block */
+};
+
+typedef struct Rd {			/* Receive Descriptor */
+	uint	addr[2];
+	ushort	length;
+	ushort	checksum;
+	uchar	status;
+	uchar	errors;
+	ushort	special;
+} Rd;
+
+enum {					/* Rd 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 {					/* Rd 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 Td Td;
+struct Td {			/* Transmit Descriptor */
+	uint	addr[2];	/* Data */
+	uint	control;
+	uint	status;
+};
+
+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 {
+	Nrd		= 256,		/* multiple of 8 */
+	Ntd		= 64,		/* multiple of 8 */
+	Nrb		= 1024,		/* private receive buffers per Ctlr */
+	Rbsz		= 8192,
+};
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+	int	port;
+	Pcidev*	pcidev;
+	Ctlr*	next;
+	int	active;
+	int	started;
+	int	id;
+	int	cls;
+	ushort	eeprom[0x40];
+
+	QLock	alock;			/* attach */
+	void*	alloc;			/* receive/transmit descriptors */
+	int	nrd;
+	int	ntd;
+	int	nrb;			/* how many this Ctlr has in the pool */
+
+	int*	nic;
+	Lock	imlock;
+	int	im;			/* interrupt mask */
+
+	Rendez	lrendez;
+	int	lim;
+
+	int	link;
+
+	QLock	slock;
+	uint	statistics[Nstatistics];
+	uint	lsleep;
+	uint	lintr;
+	uint	rsleep;
+	uint	rintr;
+	uint	txdw;
+	uint	tintr;
+	uint	ixsm;
+	uint	ipcs;
+	uint	tcpcs;
+
+	uchar	ra[Eaddrlen];		/* receive address */
+	ulong	mta[128];		/* multicast table array */
+
+	Rendez	rrendez;
+	int	rim;
+	int	rdfree;
+	Rd*	rdba;			/* receive descriptor base address */
+	Block**	rb;			/* receive buffers */
+	int	rdh;			/* receive descriptor head */
+	int	rdt;			/* receive descriptor tail */
+	int	rdtr;			/* receive delay timer ring value */
+	int	radv;			/* receive interrupt absolute delay timer */
+
+	Lock	tlock;
+	int	tbusy;
+	int	tdfree;
+	Td*	tdba;			/* transmit descriptor base address */
+	Block**	tb;			/* transmit buffers */
+	int	tdh;			/* transmit descriptor head */
+	int	tdt;			/* transmit descriptor tail */
+
+	int	txcw;
+	int	fcrtl;
+	int	fcrth;
+};
+
+enum{
+	Easize	= 6,
+	Maxmac	= 16,
+};
+
+#define csr32r(c, r)	(*((c)->nic+((r)/4)))
+#define csr32w(c, r, v)	(*((c)->nic+((r)/4)) = (v))
+
+static Ctlr* i82563ctlrhead;
+static Ctlr* i82563ctlrtail;
+
+static Lock i82563rblock;		/* free receive Blocks */
+static Block* i82563rbpool;
+
+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 long
+i82563ifstat(Ether* edev, void* a, long n, ulong offset)
+{
+	Ctlr *ctlr;
+	char *p, *s;
+	int i, l, r;
+	uvlong tuvl, ruvl;
+
+	ctlr = edev->ctlr;
+	qlock(&ctlr->slock);
+	p = malloc(2*READSTR);
+	l = 0;
+	for(i = 0; i < Nstatistics; i++){
+		r = csr32r(ctlr, Statistics+i*4);
+		if((s = statistics[i]) == nil)
+			continue;
+		switch(i){
+		case Gorcl:
+		case Gotcl:
+		case Torl:
+		case Totl:
+			ruvl = r;
+			ruvl += ((uvlong)csr32r(ctlr, Statistics+(i+1)*4))<<32;
+			tuvl = ruvl;
+			tuvl += ctlr->statistics[i];
+			tuvl += ((uvlong)ctlr->statistics[i+1])<<32;
+			if(tuvl == 0)
+				continue;
+			ctlr->statistics[i] = tuvl;
+			ctlr->statistics[i+1] = tuvl>>32;
+			l += snprint(p+l, 2*READSTR-l, "%s: %llud %llud\n",
+				s, tuvl, ruvl);
+			i++;
+			break;
+
+		default:
+			ctlr->statistics[i] += r;
+			if(ctlr->statistics[i] == 0)
+				continue;
+			l += snprint(p+l, 2*READSTR-l, "%s: %ud %ud\n",
+				s, ctlr->statistics[i], r);
+			break;
+		}
+	}
+
+	l += snprint(p+l, 2*READSTR-l, "lintr: %ud %ud\n",
+		ctlr->lintr, ctlr->lsleep);
+	l += snprint(p+l, 2*READSTR-l, "rintr: %ud %ud\n",
+		ctlr->rintr, ctlr->rsleep);
+	l += snprint(p+l, 2*READSTR-l, "tintr: %ud %ud\n",
+		ctlr->tintr, ctlr->txdw);
+	l += snprint(p+l, 2*READSTR-l, "ixcs: %ud %ud %ud\n",
+		ctlr->ixsm, ctlr->ipcs, ctlr->tcpcs);
+	l += snprint(p+l, 2*READSTR-l, "rdtr: %ud\n", ctlr->rdtr);
+	l += snprint(p+l, 2*READSTR-l, "radv: %ud\n", ctlr->radv);
+	l += snprint(p+l, 2*READSTR-l, "Ctrlext: %08x\n", csr32r(ctlr, Ctrlext));
+
+	l += snprint(p+l, 2*READSTR-l, "eeprom:");
+	for(i = 0; i < 0x40; i++){
+		if(i && ((i & 0x07) == 0))
+			l += snprint(p+l, 2*READSTR-l, "\n       ");
+		l += snprint(p+l, 2*READSTR-l, " %4.4uX", ctlr->eeprom[i]);
+	}
+	snprint(p+l, 2*READSTR-l, "\n");
+	n = readstr(offset, a, n, p);
+	free(p);
+	qunlock(&ctlr->slock);
+
+	return n;
+}
+
+enum {
+	CMrdtr,
+	CMradv,
+};
+
+static Cmdtab i82563ctlmsg[] = {
+	CMrdtr,	"rdtr",	2,
+	CMradv,	"radv",	2,
+};
+
+static long
+i82563ctl(Ether* edev, void* buf, long n)
+{
+	int v;
+	char *p;
+	Ctlr *ctlr;
+	Cmdbuf *cb;
+	Cmdtab *ct;
+
+	if((ctlr = edev->ctlr) == nil)
+		error(Enonexist);
+
+	cb = parsecmd(buf, n);
+	if(waserror()){
+		free(cb);
+		nexterror();
+	}
+
+	ct = lookupcmd(cb, i82563ctlmsg, nelem(i82563ctlmsg));
+	switch(ct->index){
+	case CMrdtr:
+		v = strtol(cb->f[1], &p, 0);
+		if(v < 0 || p == cb->f[1] || v > 0xFFFF)
+			error(Ebadarg);
+		ctlr->rdtr = v;
+		csr32w(ctlr, Rdtr, Fpd|v);
+		break;
+	case CMradv:
+		v = strtol(cb->f[1], &p, 0);
+		if(v < 0 || p == cb->f[1] || v > 0xFFFF)
+			error(Ebadarg);
+		ctlr->radv = v;
+		csr32w(ctlr, Radv, v);
+	}
+	free(cb);
+	poperror();
+
+	return n;
+}
+
+static void
+i82563promiscuous(void* arg, int on)
+{
+	int rctl;
+	Ctlr *ctlr;
+	Ether *edev;
+
+	edev = arg;
+	ctlr = edev->ctlr;
+
+	rctl = csr32r(ctlr, Rctl);
+	rctl &= ~MoMASK;
+	if(on)
+		rctl |= Upe|Mpe;
+	else
+		rctl &= ~(Upe|Mpe);
+	csr32w(ctlr, Rctl, rctl);
+}
+
+static void
+i82563multicast(void* arg, uchar* addr, int on)
+{
+	int bit, x;
+	Ctlr *ctlr;
+	Ether *edev;
+
+	edev = arg;
+	ctlr = edev->ctlr;
+
+	x = addr[5]>>1;
+	bit = ((addr[5] & 1)<<4)|(addr[4]>>4);
+	if(on)
+		ctlr->mta[x] |= 1<<bit;
+	else
+		ctlr->mta[x] &= ~(1<<bit);
+
+	csr32w(ctlr, Mta+x*4, ctlr->mta[x]);
+}
+
+static Block*
+i82563rballoc(void)
+{
+	Block *bp;
+
+	ilock(&i82563rblock);
+	if((bp = i82563rbpool) != nil){
+		i82563rbpool = bp->next;
+		bp->next = nil;
+	}
+	iunlock(&i82563rblock);
+
+	return bp;
+}
+
+static void
+i82563rbfree(Block* bp)
+{
+	bp->rp = bp->lim - Rbsz;
+	bp->wp = bp->rp;
+
+	ilock(&i82563rblock);
+	bp->next = i82563rbpool;
+	i82563rbpool = bp;
+	iunlock(&i82563rblock);
+}
+
+static void
+i82563im(Ctlr* ctlr, int im)
+{
+	ilock(&ctlr->imlock);
+	ctlr->im |= im;
+	csr32w(ctlr, Ims, ctlr->im);
+	iunlock(&ctlr->imlock);
+}
+
+static void
+i82563txinit(Ctlr* ctlr)
+{
+	int i, r;
+	Block *bp;
+
+	csr32w(ctlr, Tctl, (0x0F<<CtSHIFT)|Psp|(66<<ColdSHIFT));
+	csr32w(ctlr, Tipg, (6<<20)|(8<<10)|8);
+	csr32w(ctlr, Tdbal, PCIWADDR(ctlr->tdba));
+	csr32w(ctlr, Tdbah, 0);
+	csr32w(ctlr, Tdlen, ctlr->ntd*sizeof(Td));
+	ctlr->tdh = PREV(0, ctlr->ntd);
+	csr32w(ctlr, Tdh, 0);
+	ctlr->tdt = 0;
+	csr32w(ctlr, Tdt, 0);
+	for(i = 0; i < ctlr->ntd; i++){
+		if((bp = ctlr->tb[i]) != nil){
+			ctlr->tb[i] = nil;
+			freeb(bp);
+		}
+		memset(&ctlr->tdba[i], 0, sizeof(Td));
+	}
+	ctlr->tdfree = ctlr->ntd;
+	csr32w(ctlr, Tidv, 128);
+	r = csr32r(ctlr, Txdctl);
+	r &= ~WthreshMASK;
+	r |= Gran|(4<<WthreshSHIFT);
+	csr32w(ctlr, Tadv, 64);
+	csr32w(ctlr, Txdctl, r);
+	r = csr32r(ctlr, Tctl);
+	r |= Ten;
+	csr32w(ctlr, Tctl, r);
+}
+
+static void
+i82563transmit(Ether* edev)
+{
+	Td *td;
+	Block *bp;
+	Ctlr *ctlr;
+	int tdh, tdt, ctdh;
+
+	ctlr = edev->ctlr;
+
+	ilock(&ctlr->tlock);
+
+	/*
+	 * Free any completed packets
+	 */
+	tdh = ctlr->tdh;
+	ctdh = csr32r(ctlr, Tdh);
+	while(NEXT(tdh, ctlr->ntd) != ctdh){
+		if((bp = ctlr->tb[tdh]) != nil){
+			ctlr->tb[tdh] = nil;
+			freeb(bp);
+		}
+		memset(&ctlr->tdba[tdh], 0, sizeof(Td));
+		tdh = NEXT(tdh, ctlr->ntd);
+	}
+	ctlr->tdh = tdh;
+
+	/*
+	 * Try to fill the ring back up.
+	 */
+	tdt = ctlr->tdt;
+	while(NEXT(tdt, ctlr->ntd) != tdh){
+		if((bp = qget(edev->oq)) == nil)
+			break;
+		td = &ctlr->tdba[tdt];
+		td->addr[0] = PCIWADDR(bp->rp);
+		td->control = ((BLEN(bp) & LenMASK)<<LenSHIFT);
+		td->control |= Ifcs|Teop|DtypeDD;
+		ctlr->tb[tdt] = bp;
+		tdt = NEXT(tdt, ctlr->ntd);
+		ctlr->tdt = tdt;
+		if(NEXT(tdt, ctlr->ntd) == tdh){
+			td->control |= Rs;
+			ctlr->txdw++;
+			i82563im(ctlr, Txdw);
+			break;
+		}
+	}
+	csr32w(ctlr, Tdt, tdt);
+	iunlock(&ctlr->tlock);
+}
+
+static void
+i82563replenish(Ctlr* ctlr)
+{
+	Rd *rd;
+	int rdt;
+	Block *bp;
+
+	rdt = ctlr->rdt;
+	while(NEXT(rdt, ctlr->nrd) != ctlr->rdh){
+		rd = &ctlr->rdba[rdt];
+		if(ctlr->rb[rdt] == nil){
+			bp = i82563rballoc();
+			if(bp == nil){
+				iprint("no available buffers\n");
+				break;
+			}
+			ctlr->rb[rdt] = bp;
+			rd->addr[0] = PCIWADDR(bp->rp);
+			rd->addr[1] = 0;
+		}
+		rd->status = 0;
+		rdt = NEXT(rdt, ctlr->nrd);
+		ctlr->rdfree++;
+	}
+	ctlr->rdt = rdt;
+	csr32w(ctlr, Rdt, rdt);
+}
+
+static void
+i82563rxinit(Ctlr* ctlr)
+{
+	int i;
+	Block *bp;
+
+//	csr32w(ctlr, Rctl, Dpf|Bsize2048|Bam|RdtmsHALF);
+//	csr32w(ctlr, Rctl, Lpe|Dpf|Bsize16384|Bam|RdtmsHALF|Bsex|Secrc);
+	csr32w(ctlr, Rctl, Lpe|Dpf|Bsize8192|Bam|RdtmsHALF|Bsex|Secrc);
+
+	csr32w(ctlr, Rdbal, PCIWADDR(ctlr->rdba));
+	csr32w(ctlr, Rdbah, 0);
+	csr32w(ctlr, Rdlen, ctlr->nrd*sizeof(Rd));
+	ctlr->rdh = 0;
+	csr32w(ctlr, Rdh, 0);
+	ctlr->rdt = 0;
+	csr32w(ctlr, Rdt, 0);
+	ctlr->rdtr = 0;
+	ctlr->radv = 0;
+	csr32w(ctlr, Rdtr, Fpd|0);
+	csr32w(ctlr, Radv, 0);
+
+	for(i = 0; i < ctlr->nrd; i++){
+		if((bp = ctlr->rb[i]) != nil){
+			ctlr->rb[i] = nil;
+			freeb(bp);
+		}
+	}
+	i82563replenish(ctlr);
+	csr32w(ctlr, Radv, 64);
+//	csr32w(ctlr, Rxdctl, (8<<WthreshSHIFT)|(8<<HthreshSHIFT)|4);
+//	csr32w(ctlr, Rxdctl, (0<<WthreshSHIFT)|(0<<HthreshSHIFT)|0);
+	csr32w(ctlr, Rxdctl, (1<<16)|(1<<24));
+
+	/*
+	 * Enable checksum offload.
+	 */
+	csr32w(ctlr, Rxcsum, Tuofl|Ipofl|(ETHERHDRSIZE<<PcssSHIFT));
+}
+
+static void
+i82563rcv(Ether *edev)
+{
+	Rd *rd;
+	Block *bp;
+	int rdh;
+	Ctlr *ctlr;
+
+	ctlr = edev->ctlr;
+	rdh = ctlr->rdh;
+	for(;;){
+		rd = &ctlr->rdba[rdh];
+
+		if(!(rd->status & Rdd))
+			break;
+
+		/*
+		 * Accept eop packets with no errors.
+		 * With no errors and the Ixsm bit set,
+		 * the descriptor status Tpcs and Ipcs bits give
+		 * an indication of whether the checksums were
+		 * calculated and valid.
+		 */
+		if (bp = ctlr->rb[rdh]) {
+			if((rd->status & Reop) && rd->errors == 0){
+				bp->wp += rd->length;
+				bp->next = nil;
+				if(!(rd->status & Ixsm)){
+					ctlr->ixsm++;
+					if(rd->status & Ipcs){
+						/*
+						 * IP checksum calculated
+						 * (and valid as errors == 0).
+						 */
+						ctlr->ipcs++;
+						bp->flag |= Bipck;
+					}
+					if(rd->status & Tcpcs){
+						/*
+						 * TCP/UDP checksum calculated
+						 * (and valid as errors == 0).
+						 */
+						ctlr->tcpcs++;
+						bp->flag |= Btcpck|Budpck;
+					}
+					bp->checksum = rd->checksum;
+					bp->flag |= Bpktck;
+				}
+				etheriq(edev, bp, 1);
+			} else
+				freeb(bp);
+			ctlr->rb[rdh] = nil;
+		}
+		memset(rd, 0, sizeof(Rd));
+		ctlr->rdfree--;
+		ctlr->rdh = rdh = NEXT(rdh, ctlr->nrd);
+		coherence();
+		if(ctlr->rdfree < (ctlr->nrd/4)*3 || (ctlr->rim & Rxdmt0))
+			i82563replenish(ctlr);
+	}
+}
+
+static int
+i82563rim(void* ctlr)
+{
+	return ((Ctlr*)ctlr)->rim != 0;
+}
+
+static void
+i82563rproc(void* arg)
+{
+	Rd *rd;
+	Block *bp;
+	Ctlr *ctlr;
+	int r, rdh, rim;
+	Ether *edev;
+
+	edev = arg;
+	ctlr = edev->ctlr;
+
+	i82563rxinit(ctlr);
+	r = csr32r(ctlr, Rctl);
+	r |= Ren;
+	csr32w(ctlr, Rctl, r);
+
+	for(;;){
+		i82563im(ctlr, Rxt0|Rxo|Rxdmt0|Rxseq);
+		ctlr->rsleep++;
+		coherence();
+		sleep(&ctlr->rrendez, i82563rim, ctlr);
+
+		rdh = ctlr->rdh;
+		for(;;){
+			rd = &ctlr->rdba[rdh];
+			rim = ctlr->rim;
+			ctlr->rim = 0;
+			if(!(rd->status & Rdd))
+				break;
+
+			/*
+			 * Accept eop packets with no errors.
+			 * With no errors and the Ixsm bit set,
+			 * the descriptor status Tpcs and Ipcs bits give
+			 * an indication of whether the checksums were
+			 * calculated and valid.
+			 */
+			if (bp = ctlr->rb[rdh]) {
+				if((rd->status & Reop) && rd->errors == 0){
+					bp->wp += rd->length;
+					bp->next = nil;
+					if(!(rd->status & Ixsm)){
+						ctlr->ixsm++;
+						if(rd->status & Ipcs){
+							/*
+							 * IP checksum calculated
+							 * (and valid as errors == 0).
+							 */
+							ctlr->ipcs++;
+							bp->flag |= Bipck;
+						}
+						if(rd->status & Tcpcs){
+							/*
+							 * TCP/UDP checksum calculated
+							 * (and valid as errors == 0).
+							 */
+							ctlr->tcpcs++;
+							bp->flag |= Btcpck|Budpck;
+						}
+						bp->checksum = rd->checksum;
+						bp->flag |= Bpktck;
+					}
+					etheriq(edev, bp, 1);
+				} else
+					freeb(bp);
+				ctlr->rb[rdh] = nil;
+			}
+			memset(rd, 0, sizeof(Rd));
+			ctlr->rdfree--;
+			ctlr->rdh = rdh = NEXT(rdh, ctlr->nrd);
+			coherence();
+			if(ctlr->rdfree < (ctlr->nrd/4)*3 || (rim & Rxdmt0))
+				i82563replenish(ctlr);
+		}
+	}
+}
+
+static void
+i82563attach(Ether* edev)
+{
+	Block *bp, *fbp;
+	Ctlr *ctlr;
+	char name[KNAMELEN];
+
+	ctlr = edev->ctlr;
+	qlock(&ctlr->alock);
+	if(ctlr->alloc != nil){
+		qunlock(&ctlr->alock);
+		return;
+	}
+
+	ctlr->nrd = ROUND(Nrd, 8);
+	ctlr->ntd = ROUND(Ntd, 8);
+	ctlr->alloc = malloc(ctlr->nrd*sizeof(Rd)+ctlr->ntd*sizeof(Td) + 255);
+	if(ctlr->alloc == nil){
+		qunlock(&ctlr->alock);
+		return;
+	}
+	ctlr->rdba = (Rd*)ROUNDUP((ulong)ctlr->alloc, 256);
+	ctlr->tdba = (Td*)(ctlr->rdba+ctlr->nrd);
+
+	ctlr->rb = malloc(ctlr->nrd*sizeof(Block*));
+	ctlr->tb = malloc(ctlr->ntd*sizeof(Block*));
+
+	if(waserror()){
+		while(ctlr->nrb > 0){
+			bp = i82563rballoc();
+			bp->free = nil;
+			freeb(bp);
+			ctlr->nrb--;
+		}
+		free(ctlr->tb);
+		ctlr->tb = nil;
+		free(ctlr->rb);
+		ctlr->rb = nil;
+		free(ctlr->alloc);
+		ctlr->alloc = nil;
+		qunlock(&ctlr->alock);
+		nexterror();
+	}
+
+	fbp = nil;
+	for(ctlr->nrb = 0; ctlr->nrb < Nrb; ){
+		if((bp = allocb(Rbsz)) == nil)
+			break;
+		if (((ulong)bp->base ^ (ulong)bp->lim) & ~0xffff) {
+			bp->next = fbp;
+			fbp = bp;
+			continue;
+		}
+		bp->free = i82563rbfree;
+		freeb(bp);
+		ctlr->nrb++;
+	}
+	freeblist(fbp);
+
+	snprint(name, KNAMELEN, "#l%drproc", edev->ctlrno);
+	kproc(name, i82563rproc, edev);
+
+	i82563txinit(ctlr);
+
+	qunlock(&ctlr->alock);
+	poperror();
+}
+
+static void
+i82563interrupt(Ureg*, void* arg)
+{
+	Ctlr *ctlr;
+	Ether *edev;
+	int icr, im, txdw;
+
+	edev = arg;
+	ctlr = edev->ctlr;
+
+	ilock(&ctlr->imlock);
+	csr32w(ctlr, Imc, ~0);
+	im = ctlr->im;
+	txdw = 0;
+
+	while(icr = csr32r(ctlr, Icr) & ctlr->im){
+		if(icr & Lsc){
+			im &= ~Lsc;
+			ctlr->lim = icr & Lsc;
+			wakeup(&ctlr->lrendez);
+			ctlr->lintr++;
+		}
+		if(icr & (Rxt0|Rxo|Rxdmt0|Rxseq)){
+			ctlr->rim = icr & (Rxt0|Rxo|Rxdmt0|Rxseq);
+			im &= ~(Rxt0|Rxo|Rxdmt0|Rxseq);
+			wakeup(&ctlr->rrendez);
+//			i82563rcv(edev);
+			ctlr->rintr++;
+		}
+		if(icr & Txdw){
+			im &= ~Txdw;
+			txdw++;
+			ctlr->tintr++;
+		}
+	}
+
+	ctlr->im = im;
+	csr32w(ctlr, Ims, im);
+	iunlock(&ctlr->imlock);
+
+	if(txdw)
+		i82563transmit(edev);
+}
+
+static int
+i82563detach(Ctlr* ctlr)
+{
+	int r, timeo;
+
+	/*
+	 * 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);
+	delay(1);
+	for(timeo = 0; timeo < 1000; timeo++){
+		if(!(csr32r(ctlr, Ctrl) & Devrst))
+			break;
+		delay(1);
+	}
+	if(csr32r(ctlr, Ctrl) & Devrst)
+		return -1;
+	r = csr32r(ctlr, Ctrlext);
+	csr32w(ctlr, Ctrlext, r|Eerst);
+	delay(1);
+	for(timeo = 0; timeo < 1000; timeo++){
+		if(!(csr32r(ctlr, Ctrlext) & Eerst))
+			break;
+		delay(1);
+	}
+	if(csr32r(ctlr, Ctrlext) & Eerst)
+		return -1;
+
+	csr32w(ctlr, Imc, ~0);
+	delay(1);
+	for(timeo = 0; timeo < 1000; timeo++){
+		if(!csr32r(ctlr, Icr))
+			break;
+		delay(1);
+	}
+	if(csr32r(ctlr, Icr))
+		return -1;
+
+	return 0;
+}
+
+static void
+i82563shutdown(Ether* ether)
+{
+	i82563detach(ether->ctlr);
+}
+
+static ushort
+eeread(Ctlr* ctlr, int adr)
+{
+	csr32w(ctlr, Eerd, ee_start | adr << 2);
+	while ((csr32r(ctlr, Eerd) & ee_done) == 0)
+		;
+	return csr32r(ctlr, Eerd) >> 16;
+}
+
+static int
+eeload(Ctlr* ctlr)
+{
+	ushort sum;
+	int data, adr;
+
+	sum = 0;
+	for (adr = 0; adr < 0x40; adr++) {
+		data = eeread(ctlr, adr);
+		ctlr->eeprom[adr] = data;
+		sum += data;
+	}
+	return sum;
+}
+
+/*
+ * kind of unnecessary;
+ * but just in case they add 4 or 16 macs to the same ctlr.
+ */
+static uchar*
+etheradd(uchar *u, uint n)
+{
+	int i;
+	uint j;
+
+	for(i = 5; n != 0 && i >= 0; i--){
+		j = n+u[i];
+		u[i] = j;
+		n = j>>8;
+	}
+	return u;
+}
+
+typedef struct {
+	uchar	ea[Easize];
+	int	n;
+} Basetab;
+
+static Basetab btab[Maxmac];
+static int nbase;
+
+int
+nthether(uchar *ea)
+{
+	int i;
+
+	for(i = 0; i < nelem(btab); i++)
+		if(btab[i].n == 0 || memcmp(btab[i].ea, ea, Easize) == 0) {
+			memmove(btab[i].ea, ea, Easize);
+			return btab[i].n++;
+		}
+	return -1;
+}
+
+static int
+i82563reset(Ctlr* ctlr)
+{
+	int i, r;
+
+	if(i82563detach(ctlr))
+		return -1;
+	r = eeload(ctlr);
+	if (r != 0 && r != 0xBABA){
+		print("i82563: bad EEPROM checksum - 0x%4.4uX\n", r);
+		return -1;
+	}
+
+	for(i = Ea; i < Eaddrlen/2; i++){
+		ctlr->ra[2*i] = ctlr->eeprom[i];
+		ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8;
+	}
+	etheradd(ctlr->ra, nthether(ctlr->ra));
+	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);
+	}
+	memset(ctlr->mta, 0, sizeof(ctlr->mta));
+	for(i = 0; i < 128; i++)
+		csr32w(ctlr, Mta+i*4, 0);
+	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);
+	return 0;
+}
+
+static void
+i82563pci(void)
+{
+	int cls;
+	Pcidev *p;
+	Ctlr *ctlr;
+	ulong io;
+	void *mem;
+
+	p = nil;
+	while(p = pcimatch(p, 0, 0)){
+		if(p->ccrb != Pcibcnet || p->ccru != 0)
+			continue;
+		if (p->vid != 0x8086 || p->did != 0x1096)
+			continue;
+
+		io = p->mem[0].bar & ~0x0F;
+		mem = vmap(io, p->mem[0].size);
+		if(mem == nil){
+			print("i82563: can't map %8.8luX\n", p->mem[0].bar);
+			continue;
+		}
+		cls = pcicfgr8(p, PciCLS);
+		switch(cls){
+			default:
+				print("i82563: unexpected CLS - %d\n", cls*4);
+				break;
+			case 0x00:
+			case 0xFF:
+				print("i82563: unusable CLS\n");
+				continue;
+			case 0x08:
+			case 0x10:
+				break;
+		}
+		ctlr = malloc(sizeof(Ctlr));
+		ctlr->port = io;
+		ctlr->pcidev = p;
+		ctlr->id = (p->did<<16)|p->vid;
+		ctlr->cls = cls*4;
+		ctlr->nic = mem;
+
+		if(i82563reset(ctlr)){
+			free(ctlr);
+			continue;
+		}
+		pcisetbme(p);
+
+		if(i82563ctlrhead != nil)
+			i82563ctlrtail->next = ctlr;
+		else
+			i82563ctlrhead = ctlr;
+		i82563ctlrtail = ctlr;
+	}
+}
+
+static int
+i82563pnp(Ether* edev)
+{
+	Ctlr *ctlr;
+
+	if(i82563ctlrhead == nil)
+		i82563pci();
+
+	/*
+	 * Any adapter matches if no edev->port is supplied,
+	 * otherwise the ports must match.
+	 */
+	for(ctlr = i82563ctlrhead; ctlr != nil; ctlr = ctlr->next)
+		if(ctlr->active)
+			continue;
+		else 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;
+	edev->maxmtu = Rbsz;
+	memmove(edev->ea, ctlr->ra, Eaddrlen);
+
+	/*
+	 * Linkage to the generic ethernet driver.
+	 */
+	edev->attach = i82563attach;
+	edev->transmit = i82563transmit;
+	edev->interrupt = i82563interrupt;
+	edev->ifstat = i82563ifstat;
+	edev->ctl = i82563ctl;
+
+	edev->arg = edev;
+	edev->promiscuous = i82563promiscuous;
+	edev->shutdown = i82563shutdown;
+	edev->multicast = i82563multicast;
+
+	return 0;
+}
+
+void
+ether82563link(void)
+{
+	addethercard("i82563", i82563pnp);
+}

+ 0 - 1
sys/src/9/port/devcap.c

@@ -5,7 +5,6 @@
 #include	"fns.h"
 #include	"../port/error.h"
 
-#include	"netif.h"
 #include	<libsec.h>
 
 enum

+ 5 - 3
sys/src/boot/pc/ether.c

@@ -14,6 +14,7 @@ extern int ether2114xreset(Ether*);
 extern int elnk3reset(Ether*);
 extern int i82557reset(Ether*);
 extern int igbepnp(Ether *);
+extern int i82563pnp(Ether *);
 extern int elnk3reset(Ether*);
 extern int ether589reset(Ether*);
 extern int ne2000reset(Ether*);
@@ -25,7 +26,7 @@ extern int rtl8169pnp(Ether*);
 extern int ether83815reset(Ether*);
 extern int rhinepnp(Ether*);
 extern int ga620pnp(Ether*);
-//extern int dp83820pnp(Ether*);
+extern int dp83820pnp(Ether*);
 
 struct {
 	char	*type;
@@ -36,6 +37,7 @@ struct {
 	{ "2114x", ether2114xreset, 0, },
 	{ "i82557", i82557reset, 0, },
 	{ "igbe",  igbepnp, 0, },
+	{ "i82563",i82563pnp, 0, },
 	{ "elnk3", elnk3reset, 0, },
 	{ "3C509", elnk3reset, 0, },
 	{ "3C575", elnk3reset, 0, },
@@ -51,8 +53,8 @@ struct {
 	{ "83815", ether83815reset, 0, },
 	{ "rhine", rhinepnp, 0, },
 	{ "GA620", ga620pnp, 0, },
-//	{ "83820",   dp83820pnp, 0, },
-//	{ "dp83820", dp83820pnp, 0, },
+	{ "83820",   dp83820pnp, 0, },
+	{ "dp83820", dp83820pnp, 0, },
 
 	{ 0, }
 };

+ 948 - 0
sys/src/boot/pc/ether82563.c

@@ -0,0 +1,948 @@
+/*
+ * bootstrap driver for
+ * Intel 82563 Gigabit Ethernet Controller
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.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),
+};
+
+/*
+ * these are in the order they appear in the manual, not numeric order.
+ * It was too hard to find them in the book. Ref 21489, rev 2.6
+ */
+
+enum {
+	/* General */
+
+	Ctrl		= 0x00000000,	/* Device Control */
+	Status		= 0x00000008,	/* Device Status */
+	Eec		= 0x00000010,	/* EEPROM/Flash Control/Data */
+	Eerd		= 0x00000014,	/* EEPROM Read */
+	Ctrlext		= 0x00000018,	/* Extended Device Control */
+	Fla		= 0x0000001c,	/* Flash Access */
+	Mdic		= 0x00000020,	/* MDI Control */
+	Seresctl	= 0x00000024,	/* Serdes ana */
+	Fcal		= 0x00000028,	/* Flow Control Address Low */
+	Fcah		= 0x0000002C,	/* Flow Control Address High */
+	Fct		= 0x00000030,	/* Flow Control Type */
+	Kumctrlsta	= 0x00000034,	/* Kumeran Controll and Status Register */
+	Vet		= 0x00000038,	/* VLAN EtherType */
+	Fcttv		= 0x00000170,	/* Flow Control Transmit Timer Value */
+	Txcw		= 0x00000178,	/* Transmit Configuration Word */
+	Rxcw		= 0x00000180,	/* Receive Configuration Word */
+	Ledctl		= 0x00000E00,	/* LED control */
+	Pba		= 0x00001000,	/* Packet Buffer Allocation */
+
+	/* Interrupt */
+
+	Icr		= 0x000000C0,	/* Interrupt Cause Read */
+	Ics		= 0x000000C8,	/* Interrupt Cause Set */
+	Ims		= 0x000000D0,	/* Interrupt Mask Set/Read */
+	Imc		= 0x000000D8,	/* Interrupt mask Clear */
+	Iam		= 0x000000E0,	/* Interrupt acknowledge Auto Mask */
+
+	/* Receive */
+
+	Rctl		= 0x00000100,	/* Receive Control */
+	Ert		= 0x00002008,	/* Early Receive Threshold (573[EVL] only) */
+	Fcrtl		= 0x00002160,	/* Flow Control RX Threshold Low */
+	Fcrth		= 0x00002168,	/* Flow Control Rx Threshold High */
+	Psrctl		= 0x00002170,	/* Packet Split Receive Control */
+	Rdbal		= 0x00002800,	/* Rdesc Base Address Low Queue 0 */
+	Rdbah		= 0x00002804,	/* Rdesc Base Address High Queue 0 */
+	Rdlen		= 0x00002808,	/* Receive Descriptor Length Queue 0 */
+	Rdh		= 0x00002810,	/* Receive Descriptor Head Queue 0 */
+	Rdt		= 0x00002818,	/* Receive Descriptor Tail Queue 0 */
+	Rdtr		= 0x00002820,	/* Receive Descriptor Timer Ring */
+	Rxdctl		= 0x00002828,	/* Receive Descriptor Control */
+	Radv		= 0x0000282C,	/* Receive Interrupt Absolute Delay Timer */
+	Rdbal1		= 0x00002900,	/* Rdesc Base Address Low Queue 1 */
+	Rdbah1		= 0x00002804,	/* Rdesc Base Address High Queue 1 */
+	Rdlen1		= 0x00002908,	/* Receive Descriptor Length Queue 1 */
+	Rdh1		= 0x00002910,	/* Receive Descriptor Head Queue 1 */
+	Rdt1		= 0x00002918,	/* Receive Descriptor Tail Queue 1 */
+	Rxdctl1		= 0x00002928,	/* Receive Descriptor Control Queue 1 */
+	Rsrpd		= 0x00002c00,	/* Receive Small Packet Detect */
+	Raid		= 0x00002c08,	/* Receive ACK interrupt delay */
+	Cpuvec		= 0x00002c10,	/* CPU Vector */
+	Rxcsum		= 0x00005000,	/* Receive Checksum Control */
+	Rfctl		= 0x00005008,	/* Receive Filter Control */
+	Mta		= 0x00005200,	/* Multicast Table Array */
+	Ral		= 0x00005400,	/* Receive Address Low */
+	Rah		= 0x00005404,	/* Receive Address High */
+	Vfta		= 0x00005600,	/* VLAN Filter Table Array */
+	Mrqc		= 0x00005818,	/* Multiple Receive Queues Command */
+	Rssim		= 0x00005864,	/* RSS Interrupt Mask */
+	Rssir		= 0x00005868,	/* RSS Interrupt Request */
+	Reta		= 0x00005c00,	/* Redirection Table */
+	Rssrk		= 0x00005c80,	/* RSS Random Key */
+
+	/* Transmit */
+
+	Tctl		= 0x00000400,	/* Transmit Control */
+	Tipg		= 0x00000410,	/* Transmit IPG */
+	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 */
+	Tarc0		= 0x00003840,	/* Transmit Arbitration Counter Queue 0 */
+	Tdbal1		= 0x00003900,	/* Transmit Descriptor Base Low Queue 1 */
+	Tdbah1		= 0x00003904,	/* Transmit Descriptor Base High Queue 1 */
+	Tdlen1		= 0x00003908,	/* Transmit Descriptor Length Queue 1 */
+	Tdh1		= 0x00003910,	/* Transmit Descriptor Head Queue 1 */
+	Tdt1		= 0x00003918,	/* Transmit Descriptor Tail Queue 1 */
+	Txdctl1		= 0x00003928,	/* Transmit Descriptor Control 1 */
+	Tarc1		= 0x00003940,	/* Transmit Arbitration Counter Queue 1 */
+
+	/* Statistics */
+
+	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,
+
+};
+
+enum {					/* Ctrl */
+	GIOmd		= (1<<2),	/* BIO master disable */
+	Lrst		= (1<<3),	/* link reset */
+	Slu		= (1<<6),	/* Set Link Up */
+	SspeedMASK	= (3<<8),	/* Speed Selection */
+	SspeedSHIFT	= 8,
+	Sspeed10	= 0x00000000,	/* 10Mb/s */
+	Sspeed100	= 0x00000100,	/* 100Mb/s */
+	Sspeed1000	= 0x00000200,	/* 1000Mb/s */
+	Frcspd		= (1<<11),	/* Force Speed */
+	Frcdplx		= (1<<12),	/* Force Duplex */
+	SwdpinsloMASK	= 0x003C0000,	/* Software Defined Pins - lo nibble */
+	SwdpinsloSHIFT	= 18,
+	SwdpioloMASK	= 0x03C00000,	/* Software Defined Pins - I or O */
+	SwdpioloSHIFT	= 22,
+	Devrst		= (1<<26),	/* Device Reset */
+	Rfce		= (1<<27),	/* Receive Flow Control Enable */
+	Tfce		= (1<<28),	/* Transmit Flow Control Enable */
+	Vme		= (1<<30),	/* VLAN Mode Enable */
+	Phy_rst		= (1<<31),	/* Phy Reset */
+};
+
+enum {					/* Status */
+	Lu		= (1<<1),	/* Link Up */
+	Lanid		= (3<<2),	/* mask for Lan ID.
+	Txoff		= (1<<4),	/* Transmission Paused */
+	Tbimode		= (1<<5),	/* TBI Mode Indication */
+	SpeedMASK	= 0x000000C0,
+	Speed10		= 0x00000000,	/* 10Mb/s */
+	Speed100	= 0x00000040,	/* 100Mb/s */
+	Speed1000	= 0x00000080,	/* 1000Mb/s */
+	Phyra		= (1<<10),	/* PHY Reset Asserted */
+	GIOme		= (1<<19),	/* GIO Master Enable Status */
+};
+
+enum {					/* Ctrl and Status */
+	Fd		= 0x00000001,	/* Full-Duplex */
+	AsdvMASK	= 0x00000300,
+	Asdv10		= 0x00000000,	/* 10Mb/s */
+	Asdv100		= 0x00000100,	/* 100Mb/s */
+	Asdv1000	= 0x00000200,	/* 1000Mb/s */
+};
+
+enum {					/* Eec */
+	Sk		= (1<<0),	/* Clock input to the EEPROM */
+	Cs		= (1<<1),	/* Chip Select */
+	Di		= (1<<2),	/* Data Input to the EEPROM */
+	Do		= (1<<3),	/* Data Output from the EEPROM */
+	Areq		= (1<<6),	/* EEPROM Access Request */
+	Agnt		= (1<<7),	/* EEPROM Access Grant */
+};
+
+enum {					/* Eerd */
+	ee_start	= (1<<0),	/* Start Read */
+	ee_done		= (1<<1),	/* Read done */
+	ee_addr		= (0xfff8<<2),	/* Read address [15:2] */
+	ee_data		= (0xffff<<16),	/* Read Data; Data returned from eeprom/nvm */
+};
+
+enum {					/* Ctrlext */
+	Asdchk		= (1<<12),	/* ASD Check */
+	Eerst		= (1<<13),	/* EEPROM Reset */
+	Spdbyps		= (1<<15),	/* Speed Select Bypass */
+};
+
+enum {					/* EEPROM content offsets */
+	Ea		= 0x00,		/* Ethernet Address */
+	Cf		= 0x03,		/* Compatibility Field */
+	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,
+};
+
+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 */
+};
+
+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;
+struct Ctlr {
+	int	port;
+	Pcidev*	pcidev;
+	Ctlr*	next;
+	int	active;
+	int	cls;
+	ushort	eeprom[0x40];
+
+	int*	nic;
+	Lock	imlock;
+	int	im;			/* interrupt mask */
+
+	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	txcw;
+	int	fcrtl;
+	int	fcrth;
+
+	/* bootstrap goo */
+	Block*	bqhead;	/* transmission queue */
+	Block*	bqtail;
+};
+
+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
+i82563im(Ctlr* ctlr, int im)
+{
+	ilock(&ctlr->imlock);
+	ctlr->im |= im;
+	csr32w(ctlr, Ims, ctlr->im);
+	iunlock(&ctlr->imlock);
+}
+
+static void
+i82563attach(Ether* edev)
+{
+	int ctl;
+	Ctlr *ctlr;
+
+	ctlr = edev->ctlr;
+	i82563im(ctlr, 0);
+	ctl = csr32r(ctlr, Rctl)|Ren;
+	csr32w(ctlr, Rctl, ctl);
+	ctl = csr32r(ctlr, Tctl)|Ten;
+	csr32w(ctlr, Tctl, ctl);
+}
+
+
+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);
+	i82563im(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
+i82563transmit(Ether* edev)
+{
+	Block *bp;
+	Ctlr *ctlr;
+	Tdesc *tdesc;
+	RingBuf *tb;
+	int tdh;
+
+	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;
+		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 */
+	while((tb = &edev->tb[edev->ti])->owner == Interface){
+		bp = fromringbuf(edev);
+
+		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
+i82563replenish(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
+i82563interrupt(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)){
+		if(icr & (Rxseq|Lsc)){
+		}
+
+		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;
+				bp->wp += rdesc->length;
+				toringbuf(edev, bp);
+				freeb(bp);
+			} else if ((rdesc->status & Reop) && rdesc->errors)
+				print("i82563: input packet error 0x%ux\n",
+					rdesc->errors);
+			rdesc->status = 0;
+			rdh = NEXT(rdh, Nrdesc);
+		}
+		ctlr->rdh = rdh;
+		if(icr & Rxdmt0)
+			i82563replenish(ctlr);
+		if(icr & Txdw){
+			im &= ~Txdw;
+			txdw++;
+		}
+	}
+	ctlr->im = im;
+	csr32w(ctlr, Ims, im);
+	iunlock(&ctlr->imlock);
+	if(txdw)
+		i82563transmit(edev);
+}
+
+static void
+i82563init(Ether* edev)
+{
+	int csr, i, r;
+	Ctlr *ctlr;
+
+	ctlr = edev->ctlr;
+	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);
+	}
+	for(i = 0; i < 128; i++)
+		csr32w(ctlr, Mta+i*4, 0);
+	csr32w(ctlr, Rctl, 0);
+	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));
+	ctlr->rdh = 0;
+	csr32w(ctlr, Rdh, ctlr->rdh);
+	ctlr->rdt = 0;
+	csr32w(ctlr, Rdt, ctlr->rdt);
+	ctlr->rb = malloc(sizeof(Block*)*Nrdesc);
+	i82563replenish(ctlr);
+	csr32w(ctlr, Rdtr, 0);
+	csr32w(ctlr, Rctl, Dpf|Bsize2048|Bam);
+	i82563im(ctlr, Rxt0|Rxo|Rxdmt0|Rxseq);
+
+	csr32w(ctlr, Tctl, (0x0F<<CtSHIFT)|Psp|(0x3f<<ColdSHIFT));	/* Fd */
+	csr32w(ctlr, Tipg, (7<<20)|(8<<10)|9);
+	csr32w(ctlr, Tidv, 1);
+	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));
+	ctlr->tdh = 0;
+	csr32w(ctlr, Tdh, ctlr->tdh);
+	ctlr->tdt = 0;
+	csr32w(ctlr, Tdt, ctlr->tdt);
+	ctlr->tb = malloc(sizeof(Block*)*Ntdesc);
+
+	r = (4<<WthreshSHIFT)|(4<<HthreshSHIFT)|(8<<PthreshSHIFT);
+	csr32w(ctlr, Txdctl, r);
+	r = csr32r(ctlr, Tctl);
+	r |= Ten;
+	csr32w(ctlr, Tctl, r);
+}
+
+
+static ushort
+eeread(Ctlr* ctlr, int adr)
+{
+	csr32w(ctlr, Eerd, ee_start | adr << 2);
+	while ((csr32r(ctlr, Eerd) & ee_done) == 0)
+		;
+	return csr32r(ctlr, Eerd) >> 16;
+}
+
+static int
+eeload(Ctlr* ctlr)
+{
+	ushort sum;
+	int data, adr;
+
+	sum = 0;
+	for (adr = 0; adr < 0x40; adr++) {
+		data = eeread(ctlr, adr);
+		ctlr->eeprom[adr] = data;
+		sum += data;
+	}
+	return sum;
+}
+
+
+static void
+detach(Ctlr *ctlr)
+{
+	csr32w(ctlr, Imc, ~0);
+	csr32w(ctlr, Rctl, 0);
+	csr32w(ctlr, Tctl, 0);
+
+	delay(10);
+
+	csr32w(ctlr, Ctrl, Devrst);
+	/* apparently needed on multi-GHz processors to avoid infinite loops */
+	delay(1);
+	while(csr32r(ctlr, Ctrl) & Devrst)
+		;
+
+	csr32w(ctlr, Ctrlext, Eerst | csr32r(ctlr, Ctrlext));
+	delay(1);
+	while(csr32r(ctlr, Ctrlext) & Eerst)
+		;
+
+	csr32w(ctlr, Imc, ~0);
+	delay(1);
+	while(csr32r(ctlr, Icr))
+		;
+}
+
+static void
+i82563detach(Ether *edev)
+{
+	detach(edev->ctlr);
+}
+
+static void
+i82563shutdown(Ether* ether)
+{
+	i82563detach(ether);
+}
+
+static int
+i82563reset(Ctlr* ctlr)
+{
+	int i, r;
+
+	detach(ctlr);
+
+	r = eeload(ctlr);
+	if (r != 0 && r != 0xBABA){
+		print("i82563: bad EEPROM checksum - 0x%4.4uX\n", r);
+		return -1;
+	}
+
+	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);
+	}
+
+	memset(ctlr->mta, 0, sizeof(ctlr->mta));
+	for(i = 0; i < 128; i++)
+		csr32w(ctlr, Mta+i*4, 0);
+
+	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);
+	return 0;
+}
+
+static void
+i82563pci(void)
+{
+	int port, cls;
+	Pcidev *p;
+	Ctlr *ctlr;
+	static int first = 1;
+
+	if (first)
+		first = 0;
+	else
+		return;
+
+	p = nil;
+	while(p = pcimatch(p, 0, 0)){
+		if(p->ccrb != 0x02 || p->ccru != 0)
+			continue;
+		if (p->did != 0x1096)
+			continue;
+		if (p->vid != 0x8086)
+			continue;
+
+		port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
+		if(port == 0){
+			print("i82563: can't map %d @ 0x%8.8luX\n",
+				p->mem[0].size, p->mem[0].bar);
+			continue;
+		}
+
+		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("i82563: unexpected CLS - %d bytes\n",
+				cls*sizeof(long));
+			break;
+		case 0x00:
+		case 0xFF:
+			/* alphapc 164lx returns 0 */
+			print("i82563: 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->cls = cls*4;
+		ctlr->nic = KADDR(ctlr->port);
+		if(i82563reset(ctlr)){
+			free(ctlr);
+			continue;
+		}
+		pcisetbme(p);
+
+		if(ctlrhead != nil)
+			ctlrtail->next = ctlr;
+		else
+			ctlrhead = ctlr;
+		ctlrtail = ctlr;
+	}
+}
+
+int
+i82563pnp(Ether* edev)
+{
+	int i;
+	Ctlr *ctlr;
+	uchar ea[Eaddrlen];
+
+	if(ctlrhead == nil)
+		i82563pci();
+
+	/*
+	 * 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;
+		}
+	}
+	i82563init(edev);
+
+	/*
+	 * Linkage to the generic ethernet driver.
+	 */
+	edev->attach = i82563attach;
+	edev->transmit = i82563transmit;
+	edev->interrupt = i82563interrupt;
+	edev->detach = i82563detach;
+
+	return 0;
+}

+ 1221 - 0
sys/src/boot/pc/etherdp83820.c

@@ -0,0 +1,1221 @@
+/*
+ * boot driver for
+ * National Semiconductor DP83820
+ * 10/100/1000 Mb/s Ethernet Network Interface Controller
+ * (Gig-NIC).
+ * Driver assumes little-endian and 32-bit host throughout.
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+#include "ethermii.h"
+
+#define iprint print
+#define waserror()	(0)
+#define poperror()
+
+enum {					/* Registers */
+	Cr		= 0x00,		/* Command */
+	Cfg		= 0x04,		/* Configuration and Media Status */
+	Mear		= 0x08,		/* MII/EEPROM Access */
+	Ptscr		= 0x0C,		/* PCI Test Control */
+	Isr		= 0x10,		/* Interrupt Status */
+	Imr		= 0x14,		/* Interrupt Mask */
+	Ier		= 0x18,		/* Interrupt Enable */
+	Ihr		= 0x1C,		/* Interrupt Holdoff */
+	Txdp		= 0x20,		/* Transmit Descriptor Pointer */
+	Txdphi		= 0x24,		/* Transmit Descriptor Pointer Hi */
+	Txcfg		= 0x28,		/* Transmit Configuration */
+	Gpior		= 0x2C,		/* General Purpose I/O Control */
+	Rxdp		= 0x30,		/* Receive Descriptor Pointer */
+	Rxdphi		= 0x34,		/* Receive Descriptor Pointer Hi */
+	Rxcfg		= 0x38,		/* Receive Configuration */
+	Pqcr		= 0x3C,		/* Priority Queueing Control */
+	Wcsr		= 0x40,		/* Wake on LAN Control/Status */
+	Pcr		= 0x44,		/* Pause Control/Status */
+	Rfcr		= 0x48,		/* Receive Filter/Match Control */
+	Rfdr		= 0x4C,		/* Receive Filter/Match Data */
+	Brar		= 0x50,		/* Boot ROM Address */
+	Brdr		= 0x54,		/* Boot ROM Data */
+	Srr		= 0x58,		/* Silicon Revision */
+	Mibc		= 0x5C,		/* MIB Control */
+	Mibd		= 0x60,		/* MIB Data */
+	Txdp1		= 0xA0,		/* Txdp Priority 1 */
+	Txdp2		= 0xA4,		/* Txdp Priority 2 */
+	Txdp3		= 0xA8,		/* Txdp Priority 3 */
+	Rxdp1		= 0xB0,		/* Rxdp Priority 1 */
+	Rxdp2		= 0xB4,		/* Rxdp Priority 2 */
+	Rxdp3		= 0xB8,		/* Rxdp Priority 3 */
+	Vrcr		= 0xBC,		/* VLAN/IP Receive Control */
+	Vtcr		= 0xC0,		/* VLAN/IP Transmit Control */
+	Vdr		= 0xC4,		/* VLAN Data */
+	Ccsr		= 0xCC,		/* Clockrun Control/Status */
+	Tbicr		= 0xE0,		/* TBI Control */
+	Tbisr		= 0xE4,		/* TBI Status */
+	Tanar		= 0xE8,		/* TBI ANAR */
+	Tanlpar		= 0xEC,		/* TBI ANLPAR */
+	Taner		= 0xF0,		/* TBI ANER */
+	Tesr		= 0xF4,		/* TBI ESR */
+};
+
+enum {					/* Cr */
+	Txe		= 0x00000001,	/* Transmit Enable */
+	Txd		= 0x00000002,	/* Transmit Disable */
+	Rxe		= 0x00000004,	/* Receiver Enable */
+	Rxd		= 0x00000008,	/* Receiver Disable */
+	Txr		= 0x00000010,	/* Transmitter Reset */
+	Rxr		= 0x00000020,	/* Receiver Reset */
+	Swien		= 0x00000080,	/* Software Interrupt Enable */
+	Rst		= 0x00000100,	/* Reset */
+	TxpriSHFT	= 9,		/* Tx Priority Queue Select */
+	TxpriMASK	= 0x00001E00,
+	RxpriSHFT	= 13,		/* Rx Priority Queue Select */
+	RxpriMASK	= 0x0001E000,
+};
+
+enum {					/* Configuration and Media Status */
+	Bem		= 0x00000001,	/* Big Endian Mode */
+	Ext125		= 0x00000002,	/* External 125MHz reference Select */
+	Bromdis		= 0x00000004,	/* Disable Boot ROM interface */
+	Pesel		= 0x00000008,	/* Parity Error Detection Action */
+	Exd		= 0x00000010,	/* Excessive Deferral Abort */
+	Pow		= 0x00000020,	/* Program Out of Window Timer */
+	Sb		= 0x00000040,	/* Single Back-off */
+	Reqalg		= 0x00000080,	/* PCI Bus Request Algorithm */
+	Extstsen	= 0x00000100,	/* Extended Status Enable */
+	Phydis		= 0x00000200,	/* Disable PHY */
+	Phyrst		= 0x00000400,	/* Reset PHY */
+	M64addren	= 0x00000800,	/* Master 64-bit Addressing Enable */
+	Data64en	= 0x00001000,	/* 64-bit Data Enable */
+	Pci64det	= 0x00002000,	/* PCI 64-bit Bus Detected */
+	T64addren	= 0x00004000,	/* Target 64-bit Addressing Enable */
+	Mwidis		= 0x00008000,	/* MWI Disable */
+	Mrmdis		= 0x00010000,	/* MRM Disable */
+	Tmrtest		= 0x00020000,	/* Timer Test Mode */
+	Spdstsien	= 0x00040000,	/* PHY Spdsts Interrupt Enable */
+	Lnkstsien	= 0x00080000,	/* PHY Lnksts Interrupt Enable */
+	Dupstsien	= 0x00100000,	/* PHY Dupsts Interrupt Enable */
+	Mode1000	= 0x00400000,	/* 1000Mb/s Mode Control */
+	Tbien		= 0x01000000,	/* Ten-Bit Interface Enable */
+	Dupsts		= 0x10000000,	/* Full Duplex Status */
+	Spdsts100	= 0x20000000,	/* SPEED100 Input Pin Status */
+	Spdsts1000	= 0x40000000,	/* SPEED1000 Input Pin Status */
+	Lnksts		= 0x80000000,	/* Link Status */
+};
+
+enum {					/* MII/EEPROM Access */
+	Eedi		= 0x00000001,	/* EEPROM Data In */
+	Eedo		= 0x00000002,	/* EEPROM Data Out */
+	Eeclk		= 0x00000004,	/* EEPROM Serial Clock */
+	Eesel		= 0x00000008,	/* EEPROM Chip Select */
+	Mdio		= 0x00000010,	/* MII Management Data */
+	Mddir		= 0x00000020,	/* MII Management Direction */
+	Mdc		= 0x00000040,	/* MII Management Clock */
+};
+
+enum {					/* Interrupts */
+	Rxok		= 0x00000001,	/* Rx OK */
+	Rxdesc		= 0x00000002,	/* Rx Descriptor */
+	Rxerr		= 0x00000004,	/* Rx Packet Error */
+	Rxearly		= 0x00000008,	/* Rx Early Threshold */
+	Rxidle		= 0x00000010,	/* Rx Idle */
+	Rxorn		= 0x00000020,	/* Rx Overrun */
+	Txok		= 0x00000040,	/* Tx Packet OK */
+	Txdesc		= 0x00000080,	/* Tx Descriptor */
+	Txerr		= 0x00000100,	/* Tx Packet Error */
+	Txidle		= 0x00000200,	/* Tx Idle */
+	Txurn		= 0x00000400,	/* Tx Underrun */
+	Mib		= 0x00000800,	/* MIB Service */
+	Swi		= 0x00001000,	/* Software Interrupt */
+	Pme		= 0x00002000,	/* Power Management Event */
+	Phy		= 0x00004000,	/* PHY Interrupt */
+	Hibint		= 0x00008000,	/* High Bits Interrupt Set */
+	Rxsovr		= 0x00010000,	/* Rx Status FIFO Overrun */
+	Rtabt		= 0x00020000,	/* Received Target Abort */
+	Rmabt		= 0x00040000,	/* Received Master Abort */
+	Sserr		= 0x00080000,	/* Signalled System Error */
+	Dperr		= 0x00100000,	/* Detected Parity Error */
+	Rxrcmp		= 0x00200000,	/* Receive Reset Complete */
+	Txrcmp		= 0x00400000,	/* Transmit Reset Complete */
+	Rxdesc0		= 0x00800000,	/* Rx Descriptor for Priority Queue 0 */
+	Rxdesc1		= 0x01000000,	/* Rx Descriptor for Priority Queue 1 */
+	Rxdesc2		= 0x02000000,	/* Rx Descriptor for Priority Queue 2 */
+	Rxdesc3		= 0x04000000,	/* Rx Descriptor for Priority Queue 3 */
+	Txdesc0		= 0x08000000,	/* Tx Descriptor for Priority Queue 0 */
+	Txdesc1		= 0x10000000,	/* Tx Descriptor for Priority Queue 1 */
+	Txdesc2		= 0x20000000,	/* Tx Descriptor for Priority Queue 2 */
+	Txdesc3		= 0x40000000,	/* Tx Descriptor for Priority Queue 3 */
+};
+
+enum {					/* Interrupt Enable */
+	Ien		= 0x00000001,	/* Interrupt Enable */
+};
+
+enum {					/* Interrupt Holdoff */
+	IhSHFT		= 0,		/* Interrupt Holdoff */
+	IhMASK		= 0x000000FF,
+	Ihctl		= 0x00000100,	/* Interrupt Holdoff Control */
+};
+
+enum {					/* Transmit Configuration */
+	TxdrthSHFT	= 0,		/* Tx Drain Threshold */
+	TxdrthMASK	= 0x000000FF,
+	FlthSHFT	= 16,		/* Tx Fill Threshold */
+	FlthMASK	= 0x0000FF00,
+	Brstdis		= 0x00080000,	/* 1000Mb/s Burst Disable */
+	MxdmaSHFT	= 20,		/* Max Size per Tx DMA Burst */
+	MxdmaMASK	= 0x00700000,
+	Ecretryen	= 0x00800000,	/* Excessive Collision Retry Enable */
+	Atp		= 0x10000000,	/* Automatic Transmit Padding */
+	Mlb		= 0x20000000,	/* MAC Loopback */
+	Hbi		= 0x40000000,	/* Heartbeat Ignore */
+	Csi		= 0x80000000,	/* Carrier Sense Ignore */
+};
+
+enum {					/* Receive Configuration */
+	RxdrthSHFT	= 1,		/* Rx Drain Threshold */
+	RxdrthMASK	= 0x0000003E,
+	Airl		= 0x04000000,	/* Accept In-Range Length Errored */
+	Alp		= 0x08000000,	/* Accept Long Packets */
+	Rxfd		= 0x10000000,	/* Receive Full Duplex */
+	Stripcrc	= 0x20000000,	/* Strip CRC */
+	Arp		= 0x40000000,	/* Accept Runt Packets */
+	Aep		= 0x80000000,	/* Accept Errored Packets */
+};
+
+enum {					/* Priority Queueing Control */
+	Txpqen		= 0x00000001,	/* Transmit Priority Queuing Enable */
+	Txfairen	= 0x00000002,	/* Transmit Fairness Enable */
+	RxpqenSHFT	= 2,		/* Receive Priority Queue Enable */
+	RxpqenMASK	= 0x0000000C,
+};
+
+enum {					/* Pause Control/Status */
+	PscntSHFT	= 0,		/* Pause Counter Value */
+	PscntMASK	= 0x0000FFFF,
+	Pstx		= 0x00020000,	/* Transmit Pause Frame */
+	PsffloSHFT	= 18,		/* Rx Data FIFO Lo Threshold */
+	PsffloMASK	= 0x000C0000,
+	PsffhiSHFT	= 20,		/* Rx Data FIFO Hi Threshold */
+	PsffhiMASK	= 0x00300000,
+	PsstloSHFT	= 22,		/* Rx Stat FIFO Hi Threshold */
+	PsstloMASK	= 0x00C00000,
+	PssthiSHFT	= 24,		/* Rx Stat FIFO Hi Threshold */
+	PssthiMASK	= 0x03000000,
+	Psrcvd		= 0x08000000,	/* Pause Frame Received */
+	Psact		= 0x10000000,	/* Pause Active */
+	Psda		= 0x20000000,	/* Pause on Destination Address */
+	Psmcast		= 0x40000000,	/* Pause on Multicast */
+	Psen		= 0x80000000,	/* Pause Enable */
+};
+
+enum {					/* Receive Filter/Match Control */
+	RfaddrSHFT	= 0,		/* Extended Register Address */
+	RfaddrMASK	= 0x000003FF,
+	Ulm		= 0x00080000,	/* U/L bit mask */
+	Uhen		= 0x00100000,	/* Unicast Hash Enable */
+	Mhen		= 0x00200000,	/* Multicast Hash Enable */
+	Aarp		= 0x00400000,	/* Accept ARP Packets */
+	ApatSHFT	= 23,		/* Accept on Pattern Match */
+	ApatMASK	= 0x07800000,
+	Apm		= 0x08000000,	/* Accept on Perfect Match */
+	Aau		= 0x10000000,	/* Accept All Unicast */
+	Aam		= 0x20000000,	/* Accept All Multicast */
+	Aab		= 0x40000000,	/* Accept All Broadcast */
+	Rfen		= 0x80000000,	/* Rx Filter Enable */
+};
+
+enum {					/* Receive Filter/Match Data */
+	RfdataSHFT	= 0,		/* Receive Filter Data */
+	RfdataMASK	= 0x0000FFFF,
+	BmaskSHFT	= 16,		/* Byte Mask */
+	BmaskMASK	= 0x00030000,
+};
+
+enum {					/* MIB Control */
+	Wrn		= 0x00000001,	/* Warning Test Indicator */
+	Frz		= 0x00000002,	/* Freeze All Counters */
+	Aclr		= 0x00000004,	/* Clear All Counters */
+	Mibs		= 0x00000008,	/* MIB Counter Strobe */
+};
+
+enum {					/* MIB Data */
+	Nmibd		= 11,		/* Number of MIB Data Registers */
+};
+
+enum {					/* VLAN/IP Receive Control */
+	Vtden		= 0x00000001,	/* VLAN Tag Detection Enable */
+	Vtren		= 0x00000002,	/* VLAN Tag Removal Enable */
+	Dvtf		= 0x00000004,	/* Discard VLAN Tagged Frames */
+	Dutf		= 0x00000008,	/* Discard Untagged Frames */
+	Ipen		= 0x00000010,	/* IP Checksum Enable */
+	Ripe		= 0x00000020,	/* Reject IP Checksum Errors */
+	Rtcpe		= 0x00000040,	/* Reject TCP Checksum Errors */
+	Rudpe		= 0x00000080,	/* Reject UDP Checksum Errors */
+};
+
+enum {					/* VLAN/IP Transmit Control */
+	Vgti		= 0x00000001,	/* VLAN Global Tag Insertion */
+	Vppti		= 0x00000002,	/* VLAN Per-Packet Tag Insertion */
+	Gchk		= 0x00000004,	/* Global Checksum Generation */
+	Ppchk		= 0x00000008,	/* Per-Packet Checksum Generation */
+};
+
+enum {					/* VLAN Data */
+	VtypeSHFT	= 0,		/* VLAN Type Field */
+	VtypeMASK	= 0x0000FFFF,
+	VtciSHFT	= 16,		/* VLAN Tag Control Information */
+	VtciMASK	= 0xFFFF0000,
+};
+
+enum {					/* Clockrun Control/Status */
+	Clkrunen	= 0x00000001,	/* CLKRUN Enable */
+	Pmeen		= 0x00000100,	/* PME Enable */
+	Pmests		= 0x00008000,	/* PME Status */
+};
+
+typedef struct {
+	u32int	link;			/* Link to the next descriptor */
+	u32int	bufptr;			/* pointer to data Buffer */
+	int	cmdsts;			/* Command/Status */
+	int	extsts;			/* optional Extended Status */
+
+	Block*	bp;			/* Block containing bufptr */
+	u32int	unused;			/* pad to 64-bit */
+} Desc;
+
+enum {					/* Common cmdsts bits */
+	SizeMASK	= 0x0000FFFF,	/* Descriptor Byte Count */
+	SizeSHFT	= 0,
+	Ok		= 0x08000000,	/* Packet OK */
+	Crc		= 0x10000000,	/* Suppress/Include CRC */
+	Intr		= 0x20000000,	/* Interrupt on ownership transfer */
+	More		= 0x40000000,	/* not last descriptor in a packet */
+	Own		= 0x80000000,	/* Descriptor Ownership */
+};
+
+enum {					/* Transmit cmdsts bits */
+	CcntMASK	= 0x000F0000,	/* Collision Count */
+	CcntSHFT	= 16,
+	Ec		= 0x00100000,	/* Excessive Collisions */
+	Owc		= 0x00200000,	/* Out of Window Collision */
+	Ed		= 0x00400000,	/* Excessive Deferral */
+	Td		= 0x00800000,	/* Transmit Deferred */
+	Crs		= 0x01000000,	/* Carrier Sense Lost */
+	Tfu		= 0x02000000,	/* Transmit FIFO Underrun */
+	Txa		= 0x04000000,	/* Transmit Abort */
+};
+
+enum {					/* Receive cmdsts bits */
+	Irl		= 0x00010000,	/* In-Range Length Error */
+	Lbp		= 0x00020000,	/* Loopback Packet */
+	Fae		= 0x00040000,	/* Frame Alignment Error */
+	Crce		= 0x00080000,	/* CRC Error */
+	Ise		= 0x00100000,	/* Invalid Symbol Error */
+	Runt		= 0x00200000,	/* Runt Packet Received */
+	Long		= 0x00400000,	/* Too Long Packet Received */
+	DestMASK	= 0x01800000,	/* Destination Class */
+	DestSHFT	= 23,
+	Rxo		= 0x02000000,	/* Receive Overrun */
+	Rxa		= 0x04000000,	/* Receive Aborted */
+};
+
+enum {					/* extsts bits */
+	EvtciMASK	= 0x0000FFFF,	/* VLAN Tag Control Information */
+	EvtciSHFT	= 0,
+	Vpkt		= 0x00010000,	/* VLAN Packet */
+	Ippkt		= 0x00020000,	/* IP Packet */
+	Iperr		= 0x00040000,	/* IP Checksum Error */
+	Tcppkt		= 0x00080000,	/* TCP Packet */
+	Tcperr		= 0x00100000,	/* TCP Checksum Error */
+	Udppkt		= 0x00200000,	/* UDP Packet */
+	Udperr		= 0x00400000,	/* UDP Checksum Error */
+};
+
+enum {
+	Nrd		= 32,		/* was 256 */
+	Nrbf		= 4*Nrd,
+	Rbsz		= ROUNDUP(sizeof(Etherpkt)+8, 8),
+	Ntd		= 8,		/* was 128 */
+};
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+	int	port;
+	Pcidev*	pcidev;
+	Ctlr*	next;
+	int	active;
+	int	id;
+
+	int	eepromsz;		/* address size in bits */
+	ushort*	eeprom;
+
+	int*	nic;
+	int	cfg;
+	int	imr;
+
+	Lock	alock;			/* attach */
+	Lock	ilock;			/* init */
+	void*	alloc;			/* base of per-Ctlr allocated data */
+
+	Mii*	mii;
+
+	Lock	rdlock;			/* receive */
+	Desc*	rd;
+	int	nrd;
+	int	nrb;
+	int	rdx;
+	int	rxcfg;
+
+	Lock	tlock;			/* transmit */
+	Desc*	td;
+	int	ntd;
+	int	tdh;
+	int	tdt;
+	int	ntq;
+	int	txcfg;
+
+	int	rxidle;
+
+	uint	mibd[Nmibd];
+
+	int	ec;
+	int	owc;
+	int	ed;
+	int	crs;
+	int	tfu;
+	int	txa;
+};
+
+#define csr32r(c, r)	(*((c)->nic+((r)/4)))
+#define csr32w(c, r, v)	(*((c)->nic+((r)/4)) = (v))
+
+static Ctlr* dp83820ctlrhead;
+static Ctlr* dp83820ctlrtail;
+
+static Lock dp83820rblock;		/* free receive Blocks */
+static Block* dp83820rbpool;
+
+static char* dp83820mibs[Nmibd] = {
+	"RXErroredPkts",
+	"RXFCSErrors",
+	"RXMsdPktErrors",
+	"RXFAErrors",
+	"RXSymbolErrors",
+	"RXFrameToLong",
+	"RXIRLErrors",
+	"RXBadOpcodes",
+	"RXPauseFrames",
+	"TXPauseFrames",
+	"TXSQEErrors",
+};
+
+static int
+mdior(Ctlr* ctlr, int n)
+{
+	int data, i, mear, r;
+
+	mear = csr32r(ctlr, Mear);
+	r = ~(Mdc|Mddir) & mear;
+	data = 0;
+	for(i = n-1; i >= 0; i--){
+		if(csr32r(ctlr, Mear) & Mdio)
+			data |= (1<<i);
+		csr32w(ctlr, Mear, Mdc|r);
+		csr32w(ctlr, Mear, r);
+	}
+	csr32w(ctlr, Mear, mear);
+
+	return data;
+}
+
+static void
+mdiow(Ctlr* ctlr, int bits, int n)
+{
+	int i, mear, r;
+
+	mear = csr32r(ctlr, Mear);
+	r = Mddir|(~Mdc & mear);
+	for(i = n-1; i >= 0; i--){
+		if(bits & (1<<i))
+			r |= Mdio;
+		else
+			r &= ~Mdio;
+		csr32w(ctlr, Mear, r);
+		csr32w(ctlr, Mear, Mdc|r);
+	}
+	csr32w(ctlr, Mear, mear);
+}
+
+static int
+dp83820miimir(Mii* mii, int pa, int ra)
+{
+	int data;
+	Ctlr *ctlr;
+
+	ctlr = mii->ctlr;
+
+	/*
+	 * MII Management Interface Read.
+	 *
+	 * Preamble;
+	 * ST+OP+PA+RA;
+	 * LT + 16 data bits.
+	 */
+	mdiow(ctlr, 0xFFFFFFFF, 32);
+	mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);
+	data = mdior(ctlr, 18);
+
+	if(data & 0x10000)
+		return -1;
+
+	return data & 0xFFFF;
+}
+
+static int
+dp83820miimiw(Mii* mii, int pa, int ra, int data)
+{
+	Ctlr *ctlr;
+
+	ctlr = mii->ctlr;
+
+	/*
+	 * MII Management Interface Write.
+	 *
+	 * Preamble;
+	 * ST+OP+PA+RA+LT + 16 data bits;
+	 * Z.
+	 */
+	mdiow(ctlr, 0xFFFFFFFF, 32);
+	data &= 0xFFFF;
+	data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);
+	mdiow(ctlr, data, 32);
+
+	return 0;
+}
+
+static Block *
+dp83820rballoc(Desc* desc)
+{
+	Block *bp;
+
+	if(desc->bp == nil){
+		ilock(&dp83820rblock);
+		if((bp = dp83820rbpool) == nil){
+			iunlock(&dp83820rblock);
+			desc->bp = nil;
+			desc->cmdsts = Own;
+			return nil;
+		}
+		dp83820rbpool = bp->next;
+		bp->next = nil;
+		iunlock(&dp83820rblock);
+	
+		desc->bufptr = PCIWADDR(bp->rp);
+		desc->bp = bp;
+	}
+	else{
+		bp = desc->bp;
+		bp->rp = bp->lim - Rbsz;
+		bp->wp = bp->rp;
+	}
+
+	coherence();
+	desc->cmdsts = Intr|Rbsz;
+
+	return bp;
+}
+
+static void
+dp83820rbfree(Block *bp)
+{
+	bp->rp = bp->lim - Rbsz;
+	bp->wp = bp->rp;
+
+	ilock(&dp83820rblock);
+	bp->next = dp83820rbpool;
+	dp83820rbpool = bp;
+	iunlock(&dp83820rblock);
+}
+
+static void
+dp83820halt(Ctlr* ctlr)
+{
+	int i, timeo;
+
+	ilock(&ctlr->ilock);
+	csr32w(ctlr, Imr, 0);
+	csr32w(ctlr, Ier, 0);
+	csr32w(ctlr, Cr, Rxd|Txd);
+	for(timeo = 0; timeo < 1000; timeo++){
+		if(!(csr32r(ctlr, Cr) & (Rxe|Txe)))
+			break;
+		microdelay(1);
+	}
+	csr32w(ctlr, Mibc, Frz);
+	iunlock(&ctlr->ilock);
+
+	if(ctlr->rd != nil){
+		for(i = 0; i < ctlr->nrd; i++){
+			if(ctlr->rd[i].bp == nil)
+				continue;
+			freeb(ctlr->rd[i].bp);
+			ctlr->rd[i].bp = nil;
+		}
+	}
+	if(ctlr->td != nil){
+		for(i = 0; i < ctlr->ntd; i++){
+			if(ctlr->td[i].bp == nil)
+				continue;
+			freeb(ctlr->td[i].bp);
+			ctlr->td[i].bp = nil;
+		}
+	}
+}
+
+static void
+dp83820cfg(Ctlr* ctlr)
+{
+	int cfg;
+
+	/*
+	 * Don't know how to deal with a TBI yet.
+	 */
+	if(ctlr->mii == nil)
+		return;
+
+	/*
+	 * The polarity of these bits is at the mercy
+	 * of the board designer.
+	 * The correct answer for all speed and duplex questions
+	 * should be to query the phy.
+	 */
+	cfg = csr32r(ctlr, Cfg);
+	if(!(cfg & Dupsts)){
+		ctlr->rxcfg |= Rxfd;
+		ctlr->txcfg |= Csi|Hbi;
+		iprint("83820: full duplex, ");
+	}
+	else{
+		ctlr->rxcfg &= ~Rxfd;
+		ctlr->txcfg &= ~(Csi|Hbi);
+		iprint("83820: half duplex, ");
+	}
+	csr32w(ctlr, Rxcfg, ctlr->rxcfg);
+	csr32w(ctlr, Txcfg, ctlr->txcfg);
+
+	switch(cfg & (Spdsts1000|Spdsts100)){
+	case Spdsts1000:		/* 100Mbps */
+	default:			/* 10Mbps */
+		ctlr->cfg &= ~Mode1000;
+		if((cfg & (Spdsts1000|Spdsts100)) == Spdsts1000)
+			iprint("100Mb/s\n");
+		else
+			iprint("10Mb/s\n");
+		break;
+	case Spdsts100:			/* 1Gbps */
+		ctlr->cfg |= Mode1000;
+		iprint("1Gb/s\n");
+		break;
+	}
+	csr32w(ctlr, Cfg, ctlr->cfg);
+}
+
+static void
+dp83820init(Ether* edev)
+{
+	int i;
+	Ctlr *ctlr;
+	Desc *desc;
+	uchar *alloc;
+
+	ctlr = edev->ctlr;
+
+	dp83820halt(ctlr);
+
+	/*
+	 * Receiver
+	 */
+	alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 8);
+	ctlr->rd = (Desc*)alloc;
+	alloc += ctlr->nrd*sizeof(Desc);
+	memset(ctlr->rd, 0, ctlr->nrd*sizeof(Desc));
+	ctlr->rdx = 0;
+	for(i = 0; i < ctlr->nrd; i++){
+		desc = &ctlr->rd[i];
+		desc->link = PCIWADDR(&ctlr->rd[NEXT(i, ctlr->nrd)]);
+		if(dp83820rballoc(desc) == nil)
+			continue;
+	}
+	csr32w(ctlr, Rxdphi, 0);
+	csr32w(ctlr, Rxdp, PCIWADDR(ctlr->rd));
+
+	for(i = 0; i < Eaddrlen; i += 2){
+		csr32w(ctlr, Rfcr, i);
+		csr32w(ctlr, Rfdr, (edev->ea[i+1]<<8)|edev->ea[i]);
+	}
+	csr32w(ctlr, Rfcr, Rfen|Aab|Aam|Apm);
+
+	ctlr->rxcfg = Stripcrc|(((2*(ETHERMINTU+4))/8)<<RxdrthSHFT);
+	ctlr->imr |= Rxorn|Rxidle|Rxearly|Rxdesc|Rxok;
+
+	/*
+	 * Transmitter.
+	 */
+	ctlr->td = (Desc*)alloc;
+	memset(ctlr->td, 0, ctlr->ntd*sizeof(Desc));
+	ctlr->tdh = ctlr->tdt = ctlr->ntq = 0;
+	for(i = 0; i < ctlr->ntd; i++){
+		desc = &ctlr->td[i];
+		desc->link = PCIWADDR(&ctlr->td[NEXT(i, ctlr->ntd)]);
+	}
+	csr32w(ctlr, Txdphi, 0);
+	csr32w(ctlr, Txdp, PCIWADDR(ctlr->td));
+
+	ctlr->txcfg = Atp|(((2*(ETHERMINTU+4))/32)<<FlthSHFT)|((4096/32)<<TxdrthSHFT);
+	ctlr->imr |= Txurn|Txidle|Txdesc|Txok;
+
+	ilock(&ctlr->ilock);
+
+	dp83820cfg(ctlr);
+
+	csr32w(ctlr, Mibc, Aclr);
+	ctlr->imr |= Mib;
+
+	csr32w(ctlr, Imr, ctlr->imr);
+
+	/* try coalescing adjacent interrupts; use hold-off interval of 100µs */
+	csr32w(ctlr, Ihr, Ihctl|(1<<IhSHFT));
+
+	csr32w(ctlr, Ier, Ien);
+	csr32w(ctlr, Cr, Rxe|Txe);
+
+	iunlock(&ctlr->ilock);
+}
+
+static void
+dp83820attach(Ether* edev)
+{
+	Block *bp;
+	Ctlr *ctlr;
+
+	ctlr = edev->ctlr;
+	lock(&ctlr->alock);
+	if(ctlr->alloc != nil){
+		unlock(&ctlr->alock);
+		return;
+	}
+
+	if(waserror()){
+err:
+		if(ctlr->mii != nil){
+			free(ctlr->mii);
+			ctlr->mii = nil;
+		}
+		if(ctlr->alloc != nil){
+			free(ctlr->alloc);
+			ctlr->alloc = nil;
+		}
+		unlock(&ctlr->alock);
+		return;
+	}
+
+	if(!(ctlr->cfg & Tbien)){
+		if((ctlr->mii = malloc(sizeof(Mii))) == nil)
+			goto err;
+		ctlr->mii->ctlr = ctlr;
+		ctlr->mii->mir = dp83820miimir;
+		ctlr->mii->miw = dp83820miimiw;
+		if(mii(ctlr->mii, ~0) == 0)
+			goto err;
+		ctlr->cfg |= Dupstsien|Lnkstsien|Spdstsien;
+		ctlr->imr |= Phy;
+	}
+
+	ctlr->nrd = Nrd;
+	ctlr->nrb = Nrbf;
+	ctlr->ntd = Ntd;
+	ctlr->alloc = mallocz((ctlr->nrd+ctlr->ntd)*sizeof(Desc) + 7, 0);
+	if(ctlr->alloc == nil)
+		goto err;
+
+	/*
+	 * the Bill Paul bsd drivers claim that receive buffers must be aligned
+	 * on 8-byte boundaries.
+	 */
+	for(ctlr->nrb = 0; ctlr->nrb < Nrbf; ctlr->nrb++){
+		if((bp = allocb(Rbsz+8-1)) == nil)
+			break;
+		bp->rp += 8 - (uintptr)bp->rp % 8;
+		bp->wp = bp->rp;
+//		bp->free = dp83820rbfree;	/* TODO: fix */
+		dp83820rbfree(bp);
+	}
+
+	dp83820init(edev);
+
+	unlock(&ctlr->alock);
+	poperror();
+}
+
+/*
+ *  free a list of blocks
+ */
+static void
+freeblist(Block *b)
+{
+	Block *next;
+
+	for(; b != 0; b = next){
+		next = b->next;
+		b->next = 0;
+		freeb(b);
+	}
+}
+
+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 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
+dp83820transmit(Ether* edev)
+{
+	Block *bp;
+	Ctlr *ctlr;
+	Desc *desc;
+	RingBuf *tb;
+	int cmdsts, r, x;
+
+	ctlr = edev->ctlr;
+
+	ilock(&ctlr->tlock);
+
+	bp = nil;
+	for(x = ctlr->tdh; ctlr->ntq; x = NEXT(x, ctlr->ntd)){
+		desc = &ctlr->td[x];
+		if((cmdsts = desc->cmdsts) & Own)
+			break;
+		if(!(cmdsts & Ok)){
+			if(cmdsts & Ec)
+				ctlr->ec++;
+			if(cmdsts & Owc)
+				ctlr->owc++;
+			if(cmdsts & Ed)
+				ctlr->ed++;
+			if(cmdsts & Crs)
+				ctlr->crs++;
+			if(cmdsts & Tfu)
+				ctlr->tfu++;
+			if(cmdsts & Txa)
+				ctlr->txa++;
+		}
+		desc->bp->next = bp;
+		bp = desc->bp;
+		desc->bp = nil;
+
+		ctlr->ntq--;
+	}
+	ctlr->tdh = x;
+	if(bp != nil)
+		freeblist(bp);
+
+	x = ctlr->tdt;
+//	tb = &edev->tb[edev->ti];
+	while(ctlr->ntq < ctlr->ntd - 1 /* && tb->owner == Interface */ ){
+		bp = fromringbuf(edev);
+		if (bp == nil)
+			break;
+
+		/* transmit packet from bp */
+		desc = &ctlr->td[x];
+		desc->bufptr = PCIWADDR(bp->rp);
+		desc->bp = bp;
+		ctlr->ntq++;
+		coherence();
+		desc->cmdsts = Own|Intr|BLEN(bp);	/* kick transmitter */
+//print("t");
+		tb = &edev->tb[edev->ti];
+		tb->owner = Host;		/* give descriptor back */
+		edev->ti = NEXT(edev->ti, edev->ntb);
+
+		x = NEXT(x, ctlr->ntd);
+	}
+	if(x != ctlr->tdt){
+		ctlr->tdt = x;
+		r = csr32r(ctlr, Cr);
+		csr32w(ctlr, Cr, Txe|r);
+	}
+
+	iunlock(&ctlr->tlock);
+}
+
+static void
+dp83820interrupt(Ureg*, void* arg)
+{
+	Block *bp;
+	Ctlr *ctlr;
+	Desc *desc;
+	Ether *edev;
+	int cmdsts, i, isr, r, x;
+
+	edev = arg;
+	ctlr = edev->ctlr;
+
+	for(isr = csr32r(ctlr, Isr); isr & ctlr->imr; isr = csr32r(ctlr, Isr)){
+		if(isr & (Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok)){
+			x = ctlr->rdx;
+			desc = &ctlr->rd[x];
+			while((cmdsts = desc->cmdsts) & Own){
+				if((cmdsts & Ok) && desc->bp != nil){
+					/* receive a packet into desc->bp */
+					bp = desc->bp;
+					desc->bp = nil;
+					// bp->rp = desc->bufptr;
+					bp->wp += cmdsts & SizeMASK;
+
+					toringbuf(edev, bp);
+//print("r");
+				}
+				dp83820rballoc(desc);
+
+				x = NEXT(x, ctlr->nrd);
+				desc = &ctlr->rd[x];
+			}
+			ctlr->rdx = x;
+
+			if(isr & Rxidle){
+				r = csr32r(ctlr, Cr);
+				csr32w(ctlr, Cr, Rxe|r);
+				ctlr->rxidle++;
+			}
+
+			isr &= ~(Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok);
+		}
+
+		if(isr & Txurn){
+			x = (ctlr->txcfg & TxdrthMASK)>>TxdrthSHFT;
+			r = (ctlr->txcfg & FlthMASK)>>FlthSHFT;
+			if(x < ((TxdrthMASK)>>TxdrthSHFT)
+			&& x < (2048/32 - r)){
+				ctlr->txcfg &= ~TxdrthMASK;
+				x++;
+				ctlr->txcfg |= x<<TxdrthSHFT;
+				csr32w(ctlr, Txcfg, ctlr->txcfg);
+			}
+		}
+
+		if(isr & (Txurn|Txidle|Txdesc|Txok)){
+			dp83820transmit(edev);
+			isr &= ~(Txurn|Txidle|Txdesc|Txok);
+		}
+
+		if(isr & Mib){
+			for(i = 0; i < Nmibd; i++){
+				r = csr32r(ctlr, Mibd+(i*sizeof(int)));
+				ctlr->mibd[i] += r & 0xFFFF;
+			}
+			isr &= ~Mib;
+		}
+
+		if((isr & Phy) && ctlr->mii != nil){
+			ctlr->mii->mir(ctlr->mii, 1, Bmsr);
+			print("phy: cfg %8.8uX bmsr %4.4uX\n",
+				csr32r(ctlr, Cfg),
+				ctlr->mii->mir(ctlr->mii, 1, Bmsr));
+			dp83820cfg(ctlr);
+			isr &= ~Phy;
+		}
+// TODO fix		if(isr)
+// TODO fix			iprint("dp83820: isr %8.8uX\n", isr);
+	}
+}
+
+static int
+dp83820detach(Ctlr* ctlr)
+{
+	/*
+	 * Soft reset the controller.
+	 */
+	csr32w(ctlr, Cr, Rst);
+	delay(1);
+	while(csr32r(ctlr, Cr) & Rst)
+		delay(1);
+	return 0;
+}
+
+static void
+dp83820shutdown(Ether* ether)
+{
+print("dp83820shutdown\n");
+	dp83820detach(ether->ctlr);
+}
+
+static int
+atc93c46r(Ctlr* ctlr, int address)
+{
+	int data, i, mear, r, size;
+
+	/*
+	 * Analog Technology, Inc. ATC93C46
+	 * or equivalent serial EEPROM.
+	 */
+	mear = csr32r(ctlr, Mear);
+	mear &= ~(Eesel|Eeclk|Eedo|Eedi);
+	r = Eesel|mear;
+
+reread:
+	csr32w(ctlr, Mear, r);
+	data = 0x06;
+	for(i = 3-1; i >= 0; i--){
+		if(data & (1<<i))
+			r |= Eedi;
+		else
+			r &= ~Eedi;
+		csr32w(ctlr, Mear, r);
+		csr32w(ctlr, Mear, Eeclk|r);
+		microdelay(1);
+		csr32w(ctlr, Mear, r);
+		microdelay(1);
+	}
+
+	/*
+	 * First time through must work out the EEPROM size.
+	 */
+	if((size = ctlr->eepromsz) == 0)
+		size = 8;
+
+	for(size = size-1; size >= 0; size--){
+		if(address & (1<<size))
+			r |= Eedi;
+		else
+			r &= ~Eedi;
+		csr32w(ctlr, Mear, r);
+		microdelay(1);
+		csr32w(ctlr, Mear, Eeclk|r);
+		microdelay(1);
+		csr32w(ctlr, Mear, r);
+		microdelay(1);
+		if(!(csr32r(ctlr, Mear) & Eedo))
+			break;
+	}
+	r &= ~Eedi;
+
+	data = 0;
+	for(i = 16-1; i >= 0; i--){
+		csr32w(ctlr, Mear, Eeclk|r);
+		microdelay(1);
+		if(csr32r(ctlr, Mear) & Eedo)
+			data |= (1<<i);
+		csr32w(ctlr, Mear, r);
+		microdelay(1);
+	}
+
+	csr32w(ctlr, Mear, mear);
+
+	if(ctlr->eepromsz == 0){
+		ctlr->eepromsz = 8-size;
+		ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
+		goto reread;
+	}
+
+	return data;
+}
+
+static int
+dp83820reset(Ctlr* ctlr)
+{
+	int i, r;
+	unsigned char sum;
+
+	/*
+	 * Soft reset the controller;
+	 * read the EEPROM to get the initial settings
+	 * of the Cfg and Gpior bits which should be cleared by
+	 * the reset.
+	 */
+	csr32w(ctlr, Cr, Rst);
+	delay(1);
+	while(csr32r(ctlr, Cr) & Rst)
+		delay(1);
+
+	atc93c46r(ctlr, 0);
+	if(ctlr->eeprom == nil) {
+		print("dp83820reset: no eeprom\n");
+		return -1;
+	}
+	sum = 0;
+	for(i = 0; i < 0x0E; i++){
+		r = atc93c46r(ctlr, i);
+		ctlr->eeprom[i] = r;
+		sum += r;
+		sum += r>>8;
+	}
+
+	if(sum != 0){
+		print("dp83820reset: bad EEPROM checksum\n");
+		return -1;
+	}
+
+#ifdef notdef
+	csr32w(ctlr, Gpior, ctlr->eeprom[4]);
+
+	cfg = Extstsen|Exd;
+	r = csr32r(ctlr, Cfg);
+	if(ctlr->eeprom[5] & 0x0001)
+		cfg |= Ext125;
+	if(ctlr->eeprom[5] & 0x0002)
+		cfg |= M64addren;
+	if((ctlr->eeprom[5] & 0x0004) && (r & Pci64det))
+		cfg |= Data64en;
+	if(ctlr->eeprom[5] & 0x0008)
+		cfg |= T64addren;
+	if(!(pcicfgr16(ctlr->pcidev, PciPCR) & 0x10))
+		cfg |= Mwidis;
+	if(ctlr->eeprom[5] & 0x0020)
+		cfg |= Mrmdis;
+	if(ctlr->eeprom[5] & 0x0080)
+		cfg |= Mode1000;
+	if(ctlr->eeprom[5] & 0x0200)
+		cfg |= Tbien|Mode1000;
+	/*
+	 * What about RO bits we might have destroyed with Rst?
+	 * What about Exd, Tmrtest, Extstsen, Pintctl?
+	 * Why does it think it has detected a 64-bit bus when
+	 * it hasn't?
+	 */
+#else
+	//r = csr32r(ctlr, Cfg);
+	//r &= ~(Mode1000|T64addren|Data64en|M64addren);
+	//csr32w(ctlr, Cfg, r);
+	//csr32w(ctlr, Cfg, 0x2000);
+#endif /* notdef */
+	ctlr->cfg = csr32r(ctlr, Cfg);
+print("cfg %8.8uX pcicfg %8.8uX\n", ctlr->cfg, pcicfgr32(ctlr->pcidev, PciPCR));
+	ctlr->cfg &= ~(T64addren|Data64en|M64addren);
+	csr32w(ctlr, Cfg, ctlr->cfg);
+	csr32w(ctlr, Mibc, Aclr|Frz);
+
+	return 0;
+}
+
+static void
+dp83820pci(void)
+{
+	int port;
+	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){
+		default:
+			continue;
+		case (0x0022<<16)|0x100B:	/* DP83820 (Gig-NIC) */
+			break;
+		}
+
+		port = upamalloc(p->mem[1].bar & ~0x0F, p->mem[1].size, 0);
+		if(port == 0){
+			print("dp83820: can't map %d @ 0x%8.8luX\n",
+				p->mem[1].size, p->mem[1].bar);
+			continue;
+		}
+
+		ctlr = malloc(sizeof(Ctlr));
+		ctlr->port = port;
+		ctlr->pcidev = p;
+		ctlr->id = p->did<<16 | p->vid;
+
+		ctlr->nic = KADDR(ctlr->port);
+		if(dp83820reset(ctlr)){
+			free(ctlr);
+			continue;
+		}
+		pcisetbme(p);
+
+		if(dp83820ctlrhead != nil)
+			dp83820ctlrtail->next = ctlr;
+		else
+			dp83820ctlrhead = ctlr;
+		dp83820ctlrtail = ctlr;
+	}
+}
+
+int
+dp83820pnp(Ether* edev)
+{
+	int i;
+	Ctlr *ctlr;
+	uchar ea[Eaddrlen];
+
+	if(dp83820ctlrhead == nil)
+		dp83820pci();
+
+	/*
+	 * Any adapter matches if no edev->port is supplied,
+	 * otherwise the ports must match.
+	 */
+	for(ctlr = dp83820ctlrhead; 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;
+
+	/*
+	 * 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[0x0C-i];
+			edev->ea[2*i+1] = ctlr->eeprom[0x0C-i]>>8;
+		}
+
+	edev->attach = dp83820attach;
+	edev->transmit = dp83820transmit;
+	edev->interrupt = dp83820interrupt;
+	edev->detach = dp83820shutdown;
+	return 0;
+}

+ 2 - 0
sys/src/boot/pc/mkfile

@@ -58,6 +58,7 @@ ETHER=\
 	ether8003.$O\
 	ether8139.$O\
 	ether8169.$O\
+	ether82563.$O\
 	ether82557.$O\
 	ether83815.$O\
 	ether8390.$O\
@@ -67,6 +68,7 @@ ETHER=\
 	etherigbe.$O\
 	ethermii.$O\
 	etherrhine.$O\
+	etherdp83820.$O\
 
 BCOM=\
 	bcom.$O\

+ 1 - 0
sys/src/fs/fs/mkfile

@@ -74,6 +74,7 @@ ETHER=\
 	ether8139.$O\
 	ether8169.$O\
 	ether82557.$O\
+	ether82563.$O\
 	ether83815.$O\
 	etherdp83820.$O\
 	etherelnk3.$O\

+ 1 - 0
sys/src/fs/fs64/mkfile

@@ -74,6 +74,7 @@ ETHER=\
 	ether8139.$O\
 	ether8169.$O\
 	ether82557.$O\
+	ether82563.$O\
 	ether83815.$O\
 	etherdp83820.$O\
 	etherelnk3.$O\

+ 1112 - 0
sys/src/fs/pc/ether82563.c

@@ -0,0 +1,1112 @@
+/*
+ * Intel 82563 Gigabit Ethernet Controller
+ */
+#include "all.h"
+#include "io.h"
+#include "../ip/ip.h"
+#include "etherif.h"
+#include "portfns.h"
+#include "mem.h"
+
+extern ulong upamalloc(ulong, int, int);
+
+#define PCIWADDR(x)	PADDR(x)+0
+#define	ROUND(s, sz)	(((s)+((sz)-1)) & ~((sz)-1))
+
+/*
+ * these are in the order they appear in the manual, not numeric order.
+ * It was too hard to find them in the book. Ref 21489, rev 2.6
+ */
+
+enum {
+	/* General */
+
+	Ctrl		= 0x00000000,	/* Device Control */
+	Status		= 0x00000008,	/* Device Status */
+	Eec		= 0x00000010,	/* EEPROM/Flash Control/Data */
+	Eerd		= 0x00000014,	/* EEPROM Read */
+	Ctrlext		= 0x00000018,	/* Extended Device Control */
+	Fla		= 0x0000001c,	/* Flash Access */
+	Mdic		= 0x00000020,	/* MDI Control */
+	Seresctl	= 0x00000024,	/* Serdes ana */
+	Fcal		= 0x00000028,	/* Flow Control Address Low */
+	Fcah		= 0x0000002C,	/* Flow Control Address High */
+	Fct		= 0x00000030,	/* Flow Control Type */
+	Kumctrlsta	= 0x00000034,	/* Kumeran Control and Status Register */
+	Vet		= 0x00000038,	/* VLAN EtherType */
+	Fcttv		= 0x00000170,	/* Flow Control Transmit Timer Value */
+	Txcw		= 0x00000178,	/* Transmit Configuration Word */
+	Rxcw		= 0x00000180,	/* Receive Configuration Word */
+	Ledctl		= 0x00000E00,	/* LED control */
+	Pba		= 0x00001000,	/* Packet Buffer Allocation */
+
+	/* Interrupt */
+
+	Icr		= 0x000000C0,	/* Interrupt Cause Read */
+	Ics		= 0x000000C8,	/* Interrupt Cause csr32w */
+	Ims		= 0x000000D0,	/* Interrupt Mask csr32w/Read */
+	Imc		= 0x000000D8,	/* Interrupt mask Clear */
+	Iam		= 0x000000E0,	/* Interrupt acknowledge Auto Mask */
+
+	/* Receive */
+
+	Rctl		= 0x00000100,	/* Control */
+	Ert		= 0x00002008,	/* Early Receive Threshold (573[EVL] only) */
+	Fcrtl		= 0x00002160,	/* Flow Control Rx Threshold Low */
+	Fcrth		= 0x00002168,	/* Flow Control Rx Threshold High */
+	Psrctl		= 0x00002170,	/* Packet Split Receive Control */
+	Rdbal		= 0x00002800,	/* Rdesc Base Address Low Queue 0 */
+	Rdbah		= 0x00002804,	/* Rdesc Base Address High Queue 0 */
+	Rdlen		= 0x00002808,	/* Descriptor Length Queue 0 */
+	Rdh		= 0x00002810,	/* Descriptor Head Queue 0 */
+	Rdt		= 0x00002818,	/* Descriptor Tail Queue 0 */
+	Rdtr		= 0x00002820,	/* Descriptor Timer Ring */
+	Rxdctl		= 0x00002828,	/* Descriptor Control */
+	Radv		= 0x0000282C,	/* Interrupt Absolute Delay Timer */
+	Rdbal1		= 0x00002900,	/* Rdesc Base Address Low Queue 1 */
+	Rdbah1		= 0x00002804,	/* Rdesc Base Address High Queue 1 */
+	Rdlen1		= 0x00002908,	/* Descriptor Length Queue 1 */
+	Rdh1		= 0x00002910,	/* Descriptor Head Queue 1 */
+	Rdt1		= 0x00002918,	/* Descriptor Tail Queue 1 */
+	Rxdctl1		= 0x00002928,	/* Descriptor Control Queue 1 */
+	Rsrpd		= 0x00002c00,	/* Small Packet Detect */
+	Raid		= 0x00002c08,	/* ACK interrupt delay */
+	Cpuvec		= 0x00002c10,	/* CPU Vector */
+	Rxcsum		= 0x00005000,	/* Checksum Control */
+	Rfctl		= 0x00005008,	/* Filter Control */
+	Mta		= 0x00005200,	/* Multicast Table Array */
+	Ral		= 0x00005400,	/* Address Low */
+	Rah		= 0x00005404,	/* Address High */
+	Vfta		= 0x00005600,	/* VLAN Filter Table Array */
+	Mrqc		= 0x00005818,	/* Multiple Receive Queues Command */
+	Rssim		= 0x00005864,	/* RSS Interrupt Mask */
+	Rssir		= 0x00005868,	/* RSS Interrupt Request */
+	Reta		= 0x00005c00,	/* Redirection Table */
+	Rssrk		= 0x00005c80,	/* RSS Random Key */
+
+	/* Transmit */
+
+	Tctl		= 0x00000400,	/* Control */
+	Tipg		= 0x00000410,	/* IPG */
+	Tdbal		= 0x00003800,	/* Tdesc Base Address Low */
+	Tdbah		= 0x00003804,	/* Tdesc Base Address High */
+	Tdlen		= 0x00003808,	/* Descriptor Length */
+	Tdh		= 0x00003810,	/* Descriptor Head */
+	Tdt		= 0x00003818,	/* Descriptor Tail */
+	Tidv		= 0x00003820,	/* Interrupt Delay Value */
+	Txdctl		= 0x00003828,	/* Descriptor Control */
+	Tadv		= 0x0000382C,	/* Interrupt Absolute Delay Timer */
+	Tarc0		= 0x00003840,	/* Arbitration Counter Queue 0 */
+	Tdbal1		= 0x00003900,	/* Descriptor Base Low Queue 1 */
+	Tdbah1		= 0x00003904,	/* Descriptor Base High Queue 1 */
+	Tdlen1		= 0x00003908,	/* Descriptor Length Queue 1 */
+	Tdh1		= 0x00003910,	/* Descriptor Head Queue 1 */
+	Tdt1		= 0x00003918,	/* Descriptor Tail Queue 1 */
+	Txdctl1		= 0x00003928,	/* Descriptor Control 1 */
+	Tarc1		= 0x00003940,	/* Arbitration Counter Queue 1 */
+
+	/* Statistics */
+
+	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,
+
+};
+
+enum {					/* Ctrl */
+	GIOmd		= (1<<2),	/* BIO master disable */
+	Lrst		= (1<<3),	/* link reset */
+	Slu		= (1<<6),	/* csr32w Link Up */
+	SspeedMASK	= (3<<8),	/* Speed Selection */
+	SspeedSHIFT	= 8,
+	Sspeed10	= 0x00000000,	/* 10Mb/s */
+	Sspeed100	= 0x00000100,	/* 100Mb/s */
+	Sspeed1000	= 0x00000200,	/* 1000Mb/s */
+	Frcspd		= (1<<11),	/* Force Speed */
+	Frcdplx		= (1<<12),	/* Force Duplex */
+	SwdpinsloMASK	= 0x003C0000,	/* Software Defined Pins - lo nibble */
+	SwdpinsloSHIFT	= 18,
+	SwdpioloMASK	= 0x03C00000,	/* Software Defined Pins - I or O */
+	SwdpioloSHIFT	= 22,
+	Devrst		= (1<<26),	/* Device Reset */
+	Rfce		= (1<<27),	/* Receive Flow Control Enable */
+	Tfce		= (1<<28),	/* Transmit Flow Control Enable */
+	Vme		= (1<<30),	/* VLAN Mode Enable */
+	Phy_rst		= (1<<31),	/* Phy Reset */
+};
+
+enum {					/* Status */
+	Lu		= (1<<1),	/* Link Up */
+	Lanid		= (3<<2),	/* mask for Lan ID.
+	Txoff		= (1<<4),	/* Transmission Paused */
+	Tbimode		= (1<<5),	/* TBI Mode Indication */
+	SpeedMASK	= 0x000000C0,
+	Speed10		= 0x00000000,	/* 10Mb/s */
+	Speed100	= 0x00000040,	/* 100Mb/s */
+	Speed1000	= 0x00000080,	/* 1000Mb/s */
+	Phyra		= (1<<10),	/* PHY Reset Asserted */
+	GIOme		= (1<<19),	/* GIO Master Enable Status */
+};
+
+enum {					/* Ctrl and Status */
+	Fd		= 0x00000001,	/* Full-Duplex */
+	AsdvMASK	= 0x00000300,
+	Asdv10		= 0x00000000,	/* 10Mb/s */
+	Asdv100		= 0x00000100,	/* 100Mb/s */
+	Asdv1000	= 0x00000200,	/* 1000Mb/s */
+};
+
+enum {					/* Eec */
+	Sk		= (1<<0),	/* Clock input to the EEPROM */
+	Cs		= (1<<1),	/* Chip Select */
+	Di		= (1<<2),	/* Data Input to the EEPROM */
+	Do		= (1<<3),	/* Data Output from the EEPROM */
+	Areq		= (1<<6),	/* EEPROM Access Request */
+	Agnt		= (1<<7),	/* EEPROM Access Grant */
+};
+
+enum {					/* Eerd */
+	ee_start	= (1<<0),	/* Start Read */
+	ee_done		= (1<<1),	/* Read done */
+	ee_addr		= (0xfff8<<2),	/* Read address [15:2] */
+	ee_data		= (0xffff<<16),	/* Read Data; Data returned from eeprom/nvm */
+};
+
+enum {					/* Ctrlext */
+	Asdchk		= (1<<12),	/* ASD Check */
+	Eerst		= (1<<13),	/* EEPROM Reset */
+	Spdbyps		= (1<<15),	/* Speed Select Bypass */
+};
+
+enum {					/* EEPROM content offsets */
+	Ea		= 0x00,		/* Ethernet Address */
+	Cf		= 0x03,		/* Compatibility Field */
+	xIcw1		= 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,
+};
+
+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 */
+	Bsize8192	= 0x00020000, 	/* Bsex = 1 */
+	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 {					/* Receive Delay Timer Ring */
+	DelayMASK	= 0x0000FFFF,	/* delay timer in 1.024nS increments */
+	DelaySHIFT	= 0,
+	Fpd		= 0x80000000,	/* Flush partial Descriptor Block */
+};
+
+typedef struct Rd {			/* Receive Descriptor */
+	uint	addr[2];
+	ushort	length;
+	ushort	checksum;
+	uchar	status;
+	uchar	errors;
+	ushort	special;
+} Rd;
+
+enum {					/* Rd 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 {					/* Rd 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 Td Td;
+struct Td {			/* Transmit Descriptor */
+	uint	addr[2];	/* Data */
+	uint	control;
+	uint	status;
+};
+
+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 {
+	Nrd		= 256,		/* multiple of 8 */
+	Ntd		= 64,		/* multiple of 8 */
+	Nrb		= 1024,		/* private receive buffers per Ctlr */
+	Rbsz		= ETHERMAXTU,
+};
+
+typedef struct{
+	int	port;
+	Pcidev*	pcidev;
+	int	active;
+	int	started;
+	int	id;
+	int	cls;
+	ushort	eeprom[0x40];
+
+	void*	alloc;			/* receive/transmit descriptors */
+	int	nrd;
+	int	ntd;
+	int	nrb;			/* how many this Ctlr has in the pool */
+
+	int*	nic;
+	int	im;			/* interrupt mask */
+
+	int	lrendez;
+	int	lim;
+
+	int	link;
+
+	uint	statistics[Nstatistics];
+	uint	lsleep;
+	uint	lintr;
+	uint	rsleep;
+	uint	rintr;
+	uint	txdw;
+	uint	tintr;
+	uint	ixsm;
+	uint	ipcs;
+	uint	tcpcs;
+
+	uchar	ra[Easize];		/* receive address */
+	ulong	mta[128];		/* multicast table array */
+
+	Rendez	txrendez;
+	Rendez	rxrendez;
+
+	Lock	imlock;
+	Lock	txlock;
+
+	int	rim;
+	int	rdfree;
+	Rd*	rdba;			/* receive descriptor base address */
+	Msgbuf	**rb;			/* receive buffers */
+	int	rdh;			/* receive descriptor head */
+	int	rdt;			/* receive descriptor tail */
+	int	rdtr;			/* receive delay timer ring value */
+	int	radv;			/* receive interrupt absolute delay timer */
+
+	int	tbusy;
+	int	tdfree;
+	Td*	tdba;			/* transmit descriptor base address */
+	Msgbuf	**tb;			/* transmit buffers */
+	int	tdh;			/* transmit descriptor head */
+	int	tdt;			/* transmit descriptor tail */
+
+	int	txcw;
+	int	fcrtl;
+	int	fcrth;
+
+	Queue	*reply;			/* alias of ifc->reply */
+	Filter	rate;
+	Filter	work;
+}Ctlr;
+
+enum{
+	Nether	= 8,
+};
+
+#define csr32r(c, r)	(*((c)->nic+((r)/4)))
+#define csr32w(c, r, v)	(*((c)->nic+((r)/4)) = (v))
+
+static Ctlr	ports[Nether];
+static int	nports;
+
+static Lock i82563rblock;		/* free receive Blocks */
+static Msgbuf *i82563rbpool;
+
+#ifdef notdef
+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
+i82563ifstat(Ctlr *c)
+{
+	char *s;
+	int i, r;
+	uvlong tuvl, ruvl;
+
+	for(i = 0; i < Nstatistics; i++){
+		r = csr32r(c, Statistics+i*4);
+		if((s = statistics[i]) == nil)
+			continue;
+		switch(i){
+		case Gorcl:
+		case Gotcl:
+		case Torl:
+		case Totl:
+			ruvl = r;
+			ruvl += ((uvlong)csr32r(c, Statistics+(i+1)*4))<<32;
+			tuvl = ruvl;
+			tuvl += c->statistics[i];
+			tuvl += ((uvlong)c->statistics[i+1])<<32;
+			if(tuvl == 0)
+				continue;
+			c->statistics[i] = tuvl;
+			c->statistics[i+1] = tuvl>>32;
+			print("%s: %llud %llud\n", s, tuvl, ruvl);
+			i++;
+			break;
+
+		default:
+			c->statistics[i] += r;
+			if(c->statistics[i] == 0)
+				continue;
+			print("%s: %ud %ud\n", s, c->statistics[i], r);
+			break;
+		}
+	}
+
+	print("lintr: %ud %ud\n", c->lintr, c->lsleep);
+	print("rintr: %ud %ud\n", c->rintr, c->rsleep);
+	print("tintr: %ud %ud\n", c->tintr, c->txdw);
+	print("ixcs: %ud %ud %ud\n", c->ixsm, c->ipcs, c->tcpcs);
+	print("rdtr: %ud\n", c->rdtr);
+	print("radv: %ud\n", c->radv);
+	print("Ctrlext: %08x\n", csr32r(c, Ctrlext));
+
+	print("eeprom:");
+	for(i = 0; i < 0x40; i++){
+		if(i && ((i & 0x07) == 0))
+			print("\n       ");
+		print(" %4.4uX", c->eeprom[i]);
+	}
+}
+#endif
+
+static Msgbuf*
+i82563rballoc(void)
+{
+	Msgbuf *m;
+
+	ilock(&i82563rblock);
+	if((m = i82563rbpool) != nil){
+		i82563rbpool = m->next;
+		m->next = nil;
+	}
+	iunlock(&i82563rblock);
+	m->flags &= ~FREE;
+	m->count = 0;
+	m->data = (uchar*)PGROUND((uintptr)m->xdata);
+	return m;
+}
+
+static void
+i82563rbfree(Msgbuf *m)
+{
+	m->flags |= FREE;
+	ilock(&i82563rblock);
+	m->next = i82563rbpool;
+	i82563rbpool = m;
+	iunlock(&i82563rblock);
+}
+
+static void
+i82563im(Ctlr* c, int im)
+{
+	ilock(&c->imlock);
+	c->im |= im;
+	csr32w(c, Ims, c->im);
+	iunlock(&c->imlock);
+}
+
+static void
+i82563txinit(Ctlr* c)
+{
+	int i, r;
+	Msgbuf *m;
+
+	csr32w(c, Tctl, 0x0F<<CtSHIFT | Psp | 66<<ColdSHIFT);
+	csr32w(c, Tipg, 6<<20 | 8<<10 | 8);
+	csr32w(c, Tdbal, PCIWADDR(c->tdba));
+	csr32w(c, Tdbah, 0);
+	csr32w(c, Tdlen, c->ntd*sizeof(Td));
+	c->tdh = PREV(0, c->ntd);
+	csr32w(c, Tdh, 0);
+	c->tdt = 0;
+	csr32w(c, Tdt, 0);
+	for(i = 0; i < c->ntd; i++){
+		if((m = c->tb[i]) != nil){
+			c->tb[i] = nil;
+			mbfree(m);
+		}
+		memset(&c->tdba[i], 0, sizeof(Td));
+	}
+	c->tdfree = c->ntd;
+	csr32w(c, Tidv, 128);
+	r = csr32r(c, Txdctl);
+	r &= ~WthreshMASK;
+	r |= Gran | 4<<WthreshSHIFT;
+	csr32w(c, Tadv, 64);
+	csr32w(c, Txdctl, r);
+	r = csr32r(c, Tctl);
+	r |= Ten;
+	csr32w(c, Tctl, r);
+}
+
+static int
+ret0(void*)
+{
+	return 0;
+}
+
+static void
+i82563transmit(Ether *e)
+{
+	int tdh, tdt, ctdh;
+	Ctlr *c;
+	Msgbuf *m;
+	Td *td;
+
+	c = e->ctlr;
+	ilock(&c->txlock);
+	/*
+	 * Free any completed packets
+	 */
+	tdh = c->tdh;
+	ctdh = csr32r(c, Tdh);
+	while(NEXT(tdh, c->ntd) != ctdh){
+		if((m = c->tb[tdh]) != nil){
+			c->tb[tdh] = nil;
+			mbfree(m);
+		}
+		memset(&c->tdba[tdh], 0, sizeof(Td));
+		tdh = NEXT(tdh, c->ntd);
+	}
+	c->tdh = tdh;
+
+	/*
+	 * Try to fill the ring back up.
+	 */
+	tdt = c->tdt;
+	while(NEXT(tdt, c->ntd) != tdh){
+		if((m = etheroq(e)) == nil)
+			break;
+		td = &c->tdba[tdt];
+		td->addr[0] = PCIWADDR(m->data);
+		td->control = (m->count & LenMASK) << LenSHIFT;
+		td->control |= Ifcs | Teop | DtypeDD;
+		c->tb[tdt] = m;
+		tdt = NEXT(tdt, c->ntd);
+		c->tdt = tdt;
+		if(NEXT(tdt, c->ntd) == tdh){
+			td->control |= Rs;
+			c->txdw++;
+			i82563im(c, Txdw);
+			break;
+		}
+	}
+	csr32w(c, Tdt, tdt);
+	iunlock(&c->txlock);
+}
+
+static void
+i82563replenish(Ctlr* c)
+{
+	int rdt;
+	Msgbuf *m;
+	Rd *rd;
+
+	rdt = c->rdt;
+	while(NEXT(rdt, c->nrd) != c->rdh){
+		rd = &c->rdba[rdt];
+		if(c->rb[rdt] == nil){
+			if((m = i82563rballoc()) == nil){
+				print("no available buffers\n");
+				break;
+			}
+			c->rb[rdt] = m;
+			rd->addr[0] = PCIWADDR(m->data);
+			rd->addr[1] = 0;
+		}
+		rd->status = 0;
+		rdt = NEXT(rdt, c->nrd);
+		c->rdfree++;
+	}
+	c->rdt = rdt;
+	csr32w(c, Rdt, rdt);
+}
+
+static void
+i82563rxinit(Ctlr* c)
+{
+	int i;
+	Msgbuf *m;
+
+//	csr32w(c, Rctl, Dpf | Bsize2048 | Bam | RdtmsHALF);
+//	csr32w(c, Rctl, Lpe| Dpf | Bsize16384 | Bam | RdtmsHALF | Bsex | Secrc);
+	csr32w(c, Rctl, Lpe| Dpf | Bsize8192  | Bam | RdtmsHALF | Bsex | Secrc);
+
+	csr32w(c, Rdbal, PCIWADDR(c->rdba));
+	csr32w(c, Rdbah, 0);
+	csr32w(c, Rdlen, c->nrd*sizeof(Rd));
+	c->rdh = 0;
+	csr32w(c, Rdh, 0);
+	c->rdt = 0;
+	csr32w(c, Rdt, 0);
+	c->rdtr = 0;
+	c->radv = 0;
+	csr32w(c, Rdtr, Fpd | 0);
+	csr32w(c, Radv, 0);
+
+	for(i = 0; i < c->nrd; i++){
+		if((m = c->rb[i]) != nil){
+			c->rb[i] = nil;
+			mbfree(m);
+		}
+	}
+	i82563replenish(c);
+	csr32w(c, Radv, 64);
+//	csr32w(c, Rxdctl, 8<<WthreshSHIFT | 8<<HthreshSHIFT | 4);
+//	csr32w(c, Rxdctl, 0<<WthreshSHIFT | 0<<HthreshSHIFT | 0);
+	csr32w(c, Rxdctl, 1<<16 | 1<<24);
+
+	/*
+	 * Enable checksum offload.
+	 */
+//#define ETHERHDRSIZE 14
+//	csr32w(c, Rxcsum, Tuofl | Ipofl | ETHERHDRSIZE<<PcssSHIFT);
+}
+
+static int
+rim0(void *rim)
+{
+	return *(int*)rim != 0;
+}
+
+static void
+i82563rxproc(void)
+{
+	int r, rdh, rim;
+	Ctlr *c;
+	Ether *e;
+	Msgbuf *m;
+	Rd *rd;
+
+	e = u->arg;
+	c = e->ctlr;
+	i82563rxinit(c);
+	r = csr32r(c, Rctl);
+	r |= Ren;
+	csr32w(c, Rctl, r);
+
+	for(;;){
+		i82563im(c, Rxt0|Rxo|Rxdmt0|Rxseq);
+		c->rsleep++;
+		coherence();
+		sleep(&c->rxrendez, rim0, &c->rim);
+
+		rdh = c->rdh;
+		for(;;){
+			rd = &c->rdba[rdh];
+			rim = c->rim;
+			c->rim = 0;
+			if(!(rd->status & Rdd))
+				break;
+
+			/*
+			 * Accept eop packets with no errors.
+			 * With no errors and the Ixsm bit set,
+			 * the descriptor status Tpcs and Ipcs bits give
+			 * an indication of whether the checksums were
+			 * calculated and valid.
+			 */
+			if (m = c->rb[rdh]) {
+				if((rd->status & Reop) && rd->errors == 0){
+					m->count = rd->length;
+					m->next = nil;
+					etheriq(e, m);
+				} else
+					mbfree(m);
+				c->rb[rdh] = nil;
+			}
+			memset(rd, 0, sizeof(Rd));
+			c->rdfree--;
+			c->rdh = rdh = NEXT(rdh, c->nrd);
+			coherence();
+			if(c->rdfree < (c->nrd/4)*3 || (rim&Rxdmt0))
+				i82563replenish(c);
+		}
+	}
+}
+
+static void
+i82563attach(Ether *e)
+{
+	char name[NAMELEN];
+	Ctlr *c;
+	Msgbuf *m;
+
+	c = e->ctlr;
+	c->nrd = ROUND(Nrd, 8);
+	c->ntd = ROUND(Ntd, 8);
+	c->alloc = ialloc(c->nrd*sizeof(Rd)+c->ntd*sizeof(Td) + 255, 0);
+	c->rdba = (Rd*)ROUNDUP((ulong)c->alloc, 256);
+	c->tdba = (Td*)(c->rdba+c->nrd);
+
+	c->rb = ialloc(c->nrd*sizeof m, 0);
+	c->tb = ialloc(c->ntd*sizeof m, 0);
+
+	for(c->nrb = 0; c->nrb < Nrb; c->nrb++){
+		m = mballoc(Rbsz+BY2PG, 0, Mbeth1);
+		m->free = i82563rbfree;
+		mbfree(m);
+	}
+	snprint(name, sizeof name, "82563rx%ld", c-ports);
+	userinit(i82563rxproc, e, name);
+	i82563txinit(c);
+}
+
+static void
+i82563interrupt(Ureg*, void* v)
+{
+	int icr, im, txdw;
+	Ether *e;
+	Ctlr *c;
+
+	e = v;
+	c = e->ctlr;
+
+	ilock(&c->imlock);
+	csr32w(c, Imc, ~0);
+	im = c->im;
+	txdw = 0;
+	while(icr = csr32r(c, Icr) & c->im){
+		if(icr & Lsc){
+			im &= ~Lsc;
+			c->lim = icr & Lsc;
+			c->lintr++;
+		}
+		if(icr & (Rxt0|Rxo|Rxdmt0|Rxseq)){
+			c->rim = icr & (Rxt0|Rxo|Rxdmt0|Rxseq);
+			im &= ~(Rxt0|Rxo|Rxdmt0|Rxseq);
+			wakeup(&c->rxrendez);
+			c->rintr++;
+		}
+		if(icr & Txdw){
+			im &= ~Txdw;
+			txdw++;
+			c->tintr++;
+		}
+	}
+	c->im = im;
+	csr32w(c, Ims, im);
+	iunlock(&c->imlock);
+	if(txdw)
+		i82563transmit(e);
+}
+
+static int
+i82563detach(Ctlr* c)
+{
+	int r, timeo;
+
+	/*
+	 * 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(c, Imc, ~0);
+	csr32w(c, Rctl, 0);
+	csr32w(c, Tctl, 0);
+
+	delay(10);
+
+	csr32w(c, Ctrl, Devrst);
+	delay(1);
+	for(timeo = 0; timeo < 1000; timeo++){
+		if(!(csr32r(c, Ctrl) & Devrst))
+			break;
+		delay(1);
+	}
+	if(csr32r(c, Ctrl) & Devrst)
+		return -1;
+	r = csr32r(c, Ctrlext);
+	csr32w(c, Ctrlext, r | Eerst);
+	delay(1);
+	for(timeo = 0; timeo < 1000; timeo++){
+		if(!(csr32r(c, Ctrlext) & Eerst))
+			break;
+		delay(1);
+	}
+	if(csr32r(c, Ctrlext) & Eerst)
+		return -1;
+
+	csr32w(c, Imc, ~0);
+	delay(1);
+	for(timeo = 0; timeo < 1000; timeo++){
+		if(!csr32r(c, Icr))
+			break;
+		delay(1);
+	}
+	if(csr32r(c, Icr))
+		return -1;
+
+	return 0;
+}
+
+static ushort
+eeread(Ctlr* c, int adr)
+{
+	csr32w(c, Eerd, ee_start | adr<<2);
+	while ((csr32r(c, Eerd) & ee_done) == 0)
+		;
+	return csr32r(c, Eerd) >> 16;
+}
+
+static int
+eeload(Ctlr* c)
+{
+	int data, adr;
+	ushort sum;
+
+	sum = 0;
+	for (adr = 0; adr < 0x40; adr++) {
+		data = eeread(c, adr);
+		c->eeprom[adr] = data;
+		sum += data;
+	}
+	return sum;
+}
+
+static uchar*
+etheradd(uchar *u, uint n)
+{
+	int i;
+	uint j;
+
+	for(i = 5; n != 0 && i >= 0; i--){
+		j = n + u[i];
+		u[i] = j;
+		n = j >> 8;
+	}
+	return u;
+}
+
+typedef struct {
+	uchar	ea[Easize];
+	int	n;
+} Basetab;
+
+static Basetab btab[Nether];
+static int nbase;
+
+int
+nthether(uchar *ea)
+{
+	int i;
+
+	for(i = 0; i < nelem(btab); i++)
+		if(btab[i].n == 0 || memcmp(btab[i].ea, ea, Easize) == 0) {
+			memmove(btab[i].ea, ea, Easize);
+			return btab[i].n++;
+		}
+	return -1;
+}
+
+static int
+reset(Ctlr *c)
+{
+	int i, r;
+
+	if(i82563detach(c))
+		return -1;
+	r = eeload(c);
+	if (r != 0 && r != 0xbaba){
+		print("i82563: bad EEPROM checksum - 0x%4.4ux\n", r);
+		return -1;
+	}
+
+	for(i = Ea; i < Easize/2; i++){
+		c->ra[2*i]   = c->eeprom[i];
+		c->ra[2*i+1] = c->eeprom[i] >> 8;
+	}
+	etheradd(c->ra, nthether(c->ra));
+	r = c->ra[3]<<24 | c->ra[2]<<16 | c->ra[1]<<8 | c->ra[0];
+	csr32w(c, Ral, r);
+	r = 0x80000000 | c->ra[5]<<8 | c->ra[4];
+	csr32w(c, Rah, r);
+	for(i = 1; i < 16; i++){
+		csr32w(c, Ral+i*8, 0);
+		csr32w(c, Rah+i*8, 0);
+	}
+	memset(c->mta, 0, sizeof c->mta);
+	for(i = 0; i < 128; i++)
+		csr32w(c, Mta+i*4, 0);
+	csr32w(c, Fcal, 0x00C28001);
+	csr32w(c, Fcah, 0x00000100);
+	csr32w(c, Fct,  0x00008808);
+	csr32w(c, Fcttv, 0x00000100);
+	csr32w(c, Fcrtl, c->fcrtl);
+	csr32w(c, Fcrth, c->fcrth);
+	return 0;
+}
+
+static void
+i82563init(Ether *)
+{
+	Ctlr *c;
+	Pcidev *p;
+
+	print("i82563init\n");
+	p = 0;
+	while(nports < nelem(ports) && (p = pcimatch(p, 0x8086, 0x1096))){
+		c = ports + nports;
+		memset(c, 0, sizeof *c);
+		c->pcidev = p;
+		c->id = p->did<<16 | p->vid;
+
+		c->port = p->mem[0].bar & ~0xf;
+		c->nic = (int*)upamalloc(c->port, p->mem[0].size, 0);
+		c->cls = pcicfgr8(p, PciCLS) << 2;
+		switch(c->cls){
+		default:
+			print("i82563: unexpected CLS - %d\n", c->cls);
+		case 0x08<<2:
+		case 0x10<<2:
+			break;
+		case 0x00<<2:
+		case 0xFF<<2:
+			print("i82563: unusable CLS\n");
+			continue;
+		}
+		if(reset(c))
+			continue;
+		pcisetbme(p);
+		print("82563 %d irq %d Ea %E\n", nports, p->intl,
+			ports[nports].ra);
+		nports++;
+	}
+}
+
+int
+i82563reset(Ether *e)
+{
+	int i;
+	static int once;
+
+	if(once++ == 0)
+		i82563init(e);
+	for(i = 0; i < nports; i++)
+		if (!ports[i].active &&
+		    (e->port == 0 || e->port == ports[i].port))
+			break;
+	if(i == nports)
+		return -1;
+	ports[i].active = 1;
+	e->ctlr = ports+i;
+	e->port = ports[i].port;
+	e->irq =  ports[i].pcidev->intl;
+	e->tbdf = ports[i].pcidev->tbdf;
+	e->mbps = 1000;
+	memmove(e->ea, ports[i].ra, Easize);
+	e->attach = i82563attach;
+	e->transmit = i82563transmit;
+	e->interrupt = i82563interrupt;
+
+	return 0;
+}

+ 2 - 0
sys/src/fs/pc/etherif.c

@@ -12,6 +12,7 @@ extern int ether21140reset(Ether*);
 extern int etherelnk3reset(Ether*);
 extern int etheri82557reset(Ether*);
 extern int igbepnp(Ether *);
+extern int i82563reset(Ether *);
 extern int dp83815reset(Ether*);
 extern int dp83820pnp(Ether*);
 extern int rtl8139pnp(Ether*);
@@ -32,6 +33,7 @@ static struct
 	{ "ga620",	etherga620reset, },
 	{ "i82557",	etheri82557reset, },
 	{ "igbe",	igbepnp, },
+	{ "i82563",	i82563reset, },
 	{ "rtl8139",	rtl8139pnp, },
 	{ "rtl8169",	rtl8169pnp, },
 	{ 0, },

+ 3 - 3
sys/src/fs/pc/sdata.c

@@ -31,7 +31,7 @@ enum {
 
 	/* old stuff carried forward */
 	NCtlr=		8,
-	NCtlrdrv=	2,		/* fixed by hardware */
+	NCtlrdrv=	2,		/* fixed by hardware for pata */
 	NDrive=		NCtlr*NCtlrdrv,
 	Maxxfer=	16*1024,	/* maximum transfer size/cmd */
 
@@ -2612,8 +2612,8 @@ ataxfer(Drive *dp, int inout, Devsize start, long bytes)
 		return -1;
 	}
 	if (unit->dev != sdevs[driveno/NCtlrdrv])
-		panic("ataxfer: sdunits[%d].dev=%p is wrong controller (want %p)",
-			driveno, unit->dev, sdevs + driveno/NCtlrdrv);
+		panic("ataxfer: sdunits[%d].dev=%#p is wrong controller (want %#p)",
+			driveno, unit->dev, sdevs[driveno/NCtlrdrv]);
 	if (unit->subno != driveno%NCtlrdrv)
 		panic("ataxfer: sdunits[%d].subno is %d, not %d",
 			driveno, unit->subno, driveno%NCtlrdrv);

+ 3 - 3
sys/src/fs/port/devsd.c

@@ -163,7 +163,7 @@ sdgetunit(SDev* sdev, int subno)
 	 * successfully accessed.
 	 */
 	qlock(&sdqlock);
-	index = sdev->index+subno;
+	index = sdev->index + subno;
 	unit = sdunit[index];
 	if(unit == nil){
 		if((unit = malloc(sizeof(SDunit))) == nil){
@@ -207,8 +207,8 @@ sdindex2unit(int index)
 	 * successfully accessed.
 	 */
 	for(sdev = sdlist; sdev != nil; sdev = sdev->next)
-		if(index >= sdev->index && index < sdev->index+sdev->nunit)
-			return sdgetunit(sdev, index-sdev->index);
+		if(index >= sdev->index && index < sdev->index + sdev->nunit)
+			return sdgetunit(sdev, index - sdev->index);
 	return nil;
 }
 

+ 121 - 0
sys/src/libmach/9.c

@@ -0,0 +1,121 @@
+/*
+ * PowerPC 64 definition
+ *	forsyth@vitanuova.com
+ */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "/power64/include/ureg.h"
+#include <mach.h>
+
+
+#define	REGOFF(x)	offsetof(struct Ureg, x)
+
+#define R31		REGOFF(r31)
+#define FP_REG(x)	(R31+4+8*(x))
+
+#define	REGSIZE		sizeof(struct Ureg)
+#define	FPREGSIZE	(8*33)	
+
+Reglist power64reglist[] = {
+	{"CAUSE",	REGOFF(cause),	RINT|RRDONLY,	'Y'},
+	{"TRAP",	REGOFF(cause),	RINT|RRDONLY,	'Y'},	/* alias for acid */
+	{"MSR",	REGOFF(msr),	RINT|RRDONLY,	'Y'},
+	{"PC",		REGOFF(pc),	RINT,		'Y'},
+	{"LR",		REGOFF(lr),	RINT,		'Y'},
+	{"CR",		REGOFF(cr),	RINT,		'X'},
+	{"XER",		REGOFF(xer),	RINT,		'Y'},
+	{"CTR",		REGOFF(ctr),	RINT,		'Y'},
+	{"PC",		REGOFF(pc),		RINT,		'Y'},
+	{"SP",		REGOFF(sp),		RINT,		'Y'},
+	{"R0",		REGOFF(r0),	RINT,		'Y'},
+	/* R1 is SP */
+	{"R2",		REGOFF(r2),	RINT,		'Y'},
+	{"R3",		REGOFF(r3),	RINT,		'Y'},
+	{"R4",		REGOFF(r4),	RINT,		'Y'},
+	{"R5",		REGOFF(r5),	RINT,		'Y'},
+	{"R6",		REGOFF(r6),	RINT,		'Y'},
+	{"R7",		REGOFF(r7),	RINT,		'Y'},
+	{"R8",		REGOFF(r8),	RINT,		'Y'},
+	{"R9",		REGOFF(r9),	RINT,		'Y'},
+	{"R10",		REGOFF(r10),	RINT,		'Y'},
+	{"R11",		REGOFF(r11),	RINT,		'Y'},
+	{"R12",		REGOFF(r12),	RINT,		'Y'},
+	{"R13",		REGOFF(r13),	RINT,		'Y'},
+	{"R14",		REGOFF(r14),	RINT,		'Y'},
+	{"R15",		REGOFF(r15),	RINT,		'Y'},
+	{"R16",		REGOFF(r16),	RINT,		'Y'},
+	{"R17",		REGOFF(r17),	RINT,		'Y'},
+	{"R18",		REGOFF(r18),	RINT,		'Y'},
+	{"R19",		REGOFF(r19),	RINT,		'Y'},
+	{"R20",		REGOFF(r20),	RINT,		'Y'},
+	{"R21",		REGOFF(r21),	RINT,		'Y'},
+	{"R22",		REGOFF(r22),	RINT,		'Y'},
+	{"R23",		REGOFF(r23),	RINT,		'Y'},
+	{"R24",		REGOFF(r24),	RINT,		'Y'},
+	{"R25",		REGOFF(r25),	RINT,		'Y'},
+	{"R26",		REGOFF(r26),	RINT,		'Y'},
+	{"R27",		REGOFF(r27),	RINT,		'Y'},
+	{"R28",		REGOFF(r28),	RINT,		'Y'},
+	{"R29",		REGOFF(r29),	RINT,		'Y'},
+	{"R30",		REGOFF(r30),	RINT,		'Y'},
+	{"R31",		REGOFF(r31),	RINT,		'Y'},
+	{"F0",		FP_REG(0),	RFLT,		'F'},
+	{"F1",		FP_REG(1),	RFLT,		'F'},
+	{"F2",		FP_REG(2),	RFLT,		'F'},
+	{"F3",		FP_REG(3),	RFLT,		'F'},
+	{"F4",		FP_REG(4),	RFLT,		'F'},
+	{"F5",		FP_REG(5),	RFLT,		'F'},
+	{"F6",		FP_REG(6),	RFLT,		'F'},
+	{"F7",		FP_REG(7),	RFLT,		'F'},
+	{"F8",		FP_REG(8),	RFLT,		'F'},
+	{"F9",		FP_REG(9),	RFLT,		'F'},
+	{"F10",		FP_REG(10),	RFLT,		'F'},
+	{"F11",		FP_REG(11),	RFLT,		'F'},
+	{"F12",		FP_REG(12),	RFLT,		'F'},
+	{"F13",		FP_REG(13),	RFLT,		'F'},
+	{"F14",		FP_REG(14),	RFLT,		'F'},
+	{"F15",		FP_REG(15),	RFLT,		'F'},
+	{"F16",		FP_REG(16),	RFLT,		'F'},
+	{"F17",		FP_REG(17),	RFLT,		'F'},
+	{"F18",		FP_REG(18),	RFLT,		'F'},
+	{"F19",		FP_REG(19),	RFLT,		'F'},
+	{"F20",		FP_REG(20),	RFLT,		'F'},
+	{"F21",		FP_REG(21),	RFLT,		'F'},
+	{"F22",		FP_REG(22),	RFLT,		'F'},
+	{"F23",		FP_REG(23),	RFLT,		'F'},
+	{"F24",		FP_REG(24),	RFLT,		'F'},
+	{"F25",		FP_REG(25),	RFLT,		'F'},
+	{"F26",		FP_REG(26),	RFLT,		'F'},
+	{"F27",		FP_REG(27),	RFLT,		'F'},
+	{"F28",		FP_REG(28),	RFLT,		'F'},
+	{"F29",		FP_REG(29),	RFLT,		'F'},
+	{"F30",		FP_REG(30),	RFLT,		'F'},
+	{"F31",		FP_REG(31),	RFLT,		'F'},
+	{"FPSCR",	FP_REG(32)+4,	RFLT,		'X'},
+	{  0 }
+};
+
+	/* the machine description */
+Mach mpower64 =
+{
+	"power64",
+	MPOWER64,		/* machine type */
+	power64reglist,	/* register set */
+	REGSIZE,	/* number of bytes in register set */
+	FPREGSIZE,	/* number of bytes in FP register set */
+	"PC",		/* name of PC */
+	"SP",		/* name of SP */
+	"LR",		/* name of link register */
+	"setSB",	/* static base register name */
+	0,		/* value */
+	0x1000,		/* page size */
+	0x80000000ULL,	/* kernel base */
+	0,		/* kernel text mask */
+	0x7FFFFFFFULL,	/* user stack top */
+	4,		/* quantization of pc */
+	8,		/* szaddr */
+	8,		/* szreg */
+	4,		/* szfloat */
+	8,		/* szdouble */
+};

+ 416 - 0
sys/src/libmach/9c/9.out.h

@@ -0,0 +1,416 @@
+/*
+ * powerpc 64
+ */
+#define	NSNAME	8
+#define	NSYM	50
+#define	NREG	32
+
+#define NOPROF	(1<<0)
+#define DUPOK	(1<<1)
+
+enum
+{
+	REGZERO		= 0,	/* set to zero */
+	REGSP		= 1,
+	REGSB		= 2,
+	REGRET		= 3,
+	REGARG		= 3,
+	REGMIN		= 7,	/* register variables allocated from here to REGMAX */
+	REGMAX		= 27,
+	REGEXT		= 30,	/* external registers allocated from here down */
+	REGTMP		= 31,	/* used by the linker */
+
+	FREGRET		= 0,
+	FREGMIN		= 17,	/* first register variable */
+	FREGEXT		= 26,	/* first external register */
+	FREGCVI		= 27, /* floating conversion constant */
+	FREGZERO	= 28,	/* both float and double */
+	FREGHALF	= 29,	/* double */
+	FREGONE		= 30,	/* double */
+	FREGTWO		= 31	/* double */
+/*
+ * GENERAL:
+ *
+ * compiler allocates R3 up as temps
+ * compiler allocates register variables R7-R27
+ * compiler allocates external registers R30 down
+ *
+ * compiler allocates register variables F17-F26
+ * compiler allocates external registers F26 down
+ */
+};
+
+enum	as
+{
+	AXXX	= 0,
+	AADD,
+	AADDCC,
+	AADDV,
+	AADDVCC,
+	AADDC,
+	AADDCCC,
+	AADDCV,
+	AADDCVCC,
+	AADDME,
+	AADDMECC,
+	AADDMEVCC,
+	AADDMEV,
+	AADDE,
+	AADDECC,
+	AADDEVCC,
+	AADDEV,
+	AADDZE,
+	AADDZECC,
+	AADDZEVCC,
+	AADDZEV,
+	AAND,
+	AANDCC,
+	AANDN,
+	AANDNCC,
+	ABC,
+	ABCL,
+	ABEQ,
+	ABGE,
+	ABGT,
+	ABL,
+	ABLE,
+	ABLT,
+	ABNE,
+	ABR,
+	ABVC,
+	ABVS,
+	ACMP,
+	ACMPU,
+	ACNTLZW,
+	ACNTLZWCC,
+	ACRAND,
+	ACRANDN,
+	ACREQV,
+	ACRNAND,
+	ACRNOR,
+	ACROR,
+	ACRORN,
+	ACRXOR,
+	ADIVW,
+	ADIVWCC,
+	ADIVWVCC,
+	ADIVWV,
+	ADIVWU,
+	ADIVWUCC,
+	ADIVWUVCC,
+	ADIVWUV,
+	AEQV,
+	AEQVCC,
+	AEXTSB,
+	AEXTSBCC,
+	AEXTSH,
+	AEXTSHCC,
+	AFABS,
+	AFABSCC,
+	AFADD,
+	AFADDCC,
+	AFADDS,
+	AFADDSCC,
+	AFCMPO,
+	AFCMPU,
+	AFCTIW,
+	AFCTIWCC,
+	AFCTIWZ,
+	AFCTIWZCC,
+	AFDIV,
+	AFDIVCC,
+	AFDIVS,
+	AFDIVSCC,
+	AFMADD,
+	AFMADDCC,
+	AFMADDS,
+	AFMADDSCC,
+	AFMOVD,
+	AFMOVDCC,
+	AFMOVDU,
+	AFMOVS,
+	AFMOVSU,
+	AFMSUB,
+	AFMSUBCC,
+	AFMSUBS,
+	AFMSUBSCC,
+	AFMUL,
+	AFMULCC,
+	AFMULS,
+	AFMULSCC,
+	AFNABS,
+	AFNABSCC,
+	AFNEG,
+	AFNEGCC,
+	AFNMADD,
+	AFNMADDCC,
+	AFNMADDS,
+	AFNMADDSCC,
+	AFNMSUB,
+	AFNMSUBCC,
+	AFNMSUBS,
+	AFNMSUBSCC,
+	AFRSP,
+	AFRSPCC,
+	AFSUB,
+	AFSUBCC,
+	AFSUBS,
+	AFSUBSCC,
+	AMOVMW,
+	ALSW,
+	ALWAR,
+	AMOVWBR,
+	AMOVB,
+	AMOVBU,
+	AMOVBZ,
+	AMOVBZU,
+	AMOVH,
+	AMOVHBR,
+	AMOVHU,
+	AMOVHZ,
+	AMOVHZU,
+	AMOVW,
+	AMOVWU,
+	AMOVFL,
+	AMOVCRFS,
+	AMTFSB0,
+	AMTFSB0CC,
+	AMTFSB1,
+	AMTFSB1CC,
+	AMULHW,
+	AMULHWCC,
+	AMULHWU,
+	AMULHWUCC,
+	AMULLW,
+	AMULLWCC,
+	AMULLWVCC,
+	AMULLWV,
+	ANAND,
+	ANANDCC,
+	ANEG,
+	ANEGCC,
+	ANEGVCC,
+	ANEGV,
+	ANOR,
+	ANORCC,
+	AOR,
+	AORCC,
+	AORN,
+	AORNCC,
+	AREM,
+	AREMCC,
+	AREMV,
+	AREMVCC,
+	AREMU,
+	AREMUCC,
+	AREMUV,
+	AREMUVCC,
+	ARFI,
+	ARLWMI,
+	ARLWMICC,
+	ARLWNM,
+	ARLWNMCC,
+	ASLW,
+	ASLWCC,
+	ASRW,
+	ASRAW,
+	ASRAWCC,
+	ASRWCC,
+	ASTSW,
+	ASTWCCC,
+	ASUB,
+	ASUBCC,
+	ASUBVCC,
+	ASUBC,
+	ASUBCCC,
+	ASUBCV,
+	ASUBCVCC,
+	ASUBME,
+	ASUBMECC,
+	ASUBMEVCC,
+	ASUBMEV,
+	ASUBV,
+	ASUBE,
+	ASUBECC,
+	ASUBEV,
+	ASUBEVCC,
+	ASUBZE,
+	ASUBZECC,
+	ASUBZEVCC,
+	ASUBZEV,
+	ASYNC,
+	AXOR,
+	AXORCC,
+
+	ADCBF,
+	ADCBI,
+	ADCBST,
+	ADCBT,
+	ADCBTST,
+	ADCBZ,
+	AECIWX,
+	AECOWX,
+	AEIEIO,
+	AICBI,
+	AISYNC,
+	APTESYNC,
+	ATLBIE,
+	ATLBIEL,
+	ATLBSYNC,
+	ATW,
+
+	ASYSCALL,
+	ADATA,
+	AGLOBL,
+	AGOK,
+	AHISTORY,
+	ANAME,
+	ANOP,
+	ARETURN,
+	ATEXT,
+	AWORD,
+	AEND,
+	ADYNT,
+	AINIT,
+	ASIGNAME,
+
+	ARFCI,
+
+	/* optional on 32-bit */
+	AFRES,
+	AFRESCC,
+	AFRSQRTE,
+	AFRSQRTECC,
+	AFSEL,
+	AFSELCC,
+	AFSQRT,
+	AFSQRTCC,
+	AFSQRTS,
+	AFSQRTSCC,
+
+	/* 64-bit */
+	
+	ACNTLZD,
+	ACNTLZDCC,
+	ACMPW,	/* CMP with L=0 */
+	ACMPWU,
+	ADIVD,
+	ADIVDCC,
+	ADIVDVCC,
+	ADIVDV,
+	ADIVDU,
+	ADIVDUCC,
+	ADIVDUVCC,
+	ADIVDUV,
+	AEXTSW,
+	AEXTSWCC,
+	/* AFCFIW; AFCFIWCC */
+	AFCFID,
+	AFCFIDCC,
+	AFCTID,
+	AFCTIDCC,
+	AFCTIDZ,
+	AFCTIDZCC,
+	ALDAR,
+	AMOVD,
+	AMOVDU,
+	AMOVWZ,
+	AMOVWZU,
+	AMULHD,
+	AMULHDCC,
+	AMULHDU,
+	AMULHDUCC,
+	AMULLD,
+	AMULLDCC,
+	AMULLDVCC,
+	AMULLDV,
+	ARFID,
+	ARLDMI,
+	ARLDMICC,
+	ARLDC,
+	ARLDCCC,
+	ARLDCR,
+	ARLDCRCC,
+	ARLDCL,
+	ARLDCLCC,
+	ASLBIA,
+	ASLBIE,
+	ASLBMFEE,
+	ASLBMFEV,
+	ASLBMTE,
+	ASLD,
+	ASLDCC,
+	ASRD,
+	ASRAD,
+	ASRADCC,
+	ASRDCC,
+	ASTDCCC,
+	ATD,
+
+	/* 64-bit pseudo operation */
+	ADWORD,
+	AREMD,
+	AREMDCC,
+	AREMDV,
+	AREMDVCC,
+	AREMDU,
+	AREMDUCC,
+	AREMDUV,
+	AREMDUVCC,
+
+	ALAST
+};
+
+/* type/name */
+enum
+{
+	D_GOK	= 0,
+	D_NONE,
+
+/* name */
+	D_EXTERN,
+	D_STATIC,
+	D_AUTO,
+	D_PARAM,
+
+/* type */
+	D_BRANCH,
+	D_OREG,
+	D_CONST,
+	D_FCONST,
+	D_SCONST,
+	D_REG,
+	D_FPSCR,
+	D_MSR,
+	D_FREG,
+	D_CREG,
+	D_SPR,
+	D_OPT,	/* branch/trap option */
+	D_FILE,
+	D_FILE1,
+	D_DCR,	/* device control register */
+	D_DCONST,
+
+/* reg names iff type is D_SPR */
+	D_XER	= 1,
+	D_LR	= 8,
+	D_CTR	= 9
+	/* and many supervisor level registers */
+};
+
+/*
+ * this is the ranlib header
+ */
+#define	SYMDEF	"__.SYMDEF"
+
+/*
+ * this is the simulated IEEE floating point
+ */
+typedef	struct	ieee	Ieee;
+struct	ieee
+{
+	long	l;	/* contains ls-man	0xffffffff */
+	long	h;	/* contains sign	0x80000000
+				    exp		0x7ff00000
+				    ms-man	0x000fffff */
+};

+ 156 - 0
sys/src/libmach/9obj.c

@@ -0,0 +1,156 @@
+/*
+ * 9obj.c - identify and parse a PowerPC-64 object file
+ *	forsyth@terzarima.net
+ */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <mach.h>
+#include "9c/9.out.h"
+#include "obj.h"
+
+typedef struct Addr	Addr;
+struct Addr
+{
+	char	type;
+	char	sym;
+	char	name;
+};
+static Addr addr(Biobuf*);
+static char type2char(int);
+static void skip(Biobuf*, int);
+
+int
+_is9(char *s)
+{
+	return  (s[0]&0377) == ANAME			/* ANAME */
+		&& (s[1]&0377) == ANAME>>8
+		&& s[2] == D_FILE			/* type */
+		&& s[3] == 1				/* sym */
+		&& s[4] == '<';				/* name of file */
+}
+
+int
+_read9(Biobuf *bp, Prog *p)
+{
+	int as, n, c;
+	Addr a;
+
+	as = Bgetc(bp);					/* as(low) */
+	if(as < 0)
+		return 0;
+	c = Bgetc(bp);					/* as(high) */
+	if(c < 0)
+		return 0;
+	as |= ((c & 0xff) << 8);
+	p->kind = aNone;
+	p->sig = 0;
+	if(as == ANAME || as == ASIGNAME){
+		if(as == ASIGNAME){
+			Bread(bp, &p->sig, 4);
+			p->sig = beswal(p->sig);
+		}
+		p->kind = aName;
+		p->type = type2char(Bgetc(bp));		/* type */
+		p->sym = Bgetc(bp);			/* sym */
+		n = 0;
+		for(;;) {
+			as = Bgetc(bp);
+			if(as < 0)
+				return 0;
+			n++;
+			if(as == 0)
+				break;
+		}
+		p->id = malloc(n);
+		if(p->id == 0)
+			return 0;
+		Bseek(bp, -n, 1);
+		if(Bread(bp, p->id, n) != n)
+			return 0;
+		return 1;
+	}
+	if(as == ATEXT)
+		p->kind = aText;
+	else if(as == AGLOBL)
+		p->kind = aData;
+	n = Bgetc(bp);					/* reg and flag */
+	skip(bp, 4);					/* lineno(4) */
+	a = addr(bp);
+	if(n & 0x40)
+		addr(bp);
+	addr(bp);
+	if(a.type != D_OREG || a.name != D_STATIC && a.name != D_EXTERN)
+		p->kind = aNone;
+	p->sym = a.sym;
+	return 1;
+}
+
+static Addr
+addr(Biobuf *bp)
+{
+	Addr a;
+	vlong off;
+	long l;
+
+	a.type = Bgetc(bp);				/* a.type */
+	skip(bp,1);					/* reg */
+	a.sym = Bgetc(bp);				/* sym index */
+	a.name = Bgetc(bp);				/* sym type */
+	switch(a.type){
+	default:
+	case D_NONE: case D_REG: case D_FREG: case D_CREG:
+	case D_FPSCR: case D_MSR:
+		break;
+	case D_SPR:
+	case D_OREG:
+	case D_CONST:
+	case D_BRANCH:
+	case D_DCONST:
+	case D_DCR:
+		l = Bgetc(bp);
+		l |= Bgetc(bp) << 8;
+		l |= Bgetc(bp) << 16;
+		l |= Bgetc(bp) << 24;
+		off = l;
+		if(a.type == D_DCONST){
+			l = Bgetc(bp);
+			l |= Bgetc(bp) << 8;
+			l |= Bgetc(bp) << 16;
+			l |= Bgetc(bp) << 24;
+			off = ((vlong)l << 32) | (off & 0xFFFFFFFF);
+			a.type = D_CONST;		/* perhaps */
+		}
+		if(off < 0)
+			off = -off;
+		if(a.sym && (a.name==D_PARAM || a.name==D_AUTO))
+			_offset(a.sym, off);
+		break;
+	case D_SCONST:
+		skip(bp, NSNAME);
+		break;
+	case D_FCONST:
+		skip(bp, 8);
+		break;
+	}
+	return a;
+}
+
+static char
+type2char(int t)
+{
+	switch(t){
+	case D_EXTERN:		return 'U';
+	case D_STATIC:		return 'b';
+	case D_AUTO:		return 'a';
+	case D_PARAM:		return 'p';
+	default:		return UNKNOWN;
+	}
+}
+
+static void
+skip(Biobuf *bp, int n)
+{
+	while (n-- > 0)
+		Bgetc(bp);
+}

+ 10 - 0
sys/src/libmach/executable.c

@@ -66,6 +66,7 @@ extern	Mach	mi386;
 extern	Mach	mamd64;
 extern	Mach	marm;
 extern	Mach	mpower;
+extern	Mach	mpower64;
 extern	Mach	malpha;
 
 ExecTable exectab[] =
@@ -196,6 +197,15 @@ ExecTable exectab[] =
 		sizeof(Exec),
 		beswal,
 		common },
+	{ T_MAGIC,			/* power64 9.out & boot image */
+		"power64 plan 9 executable",
+		"power64 plan 9 dlm",
+		FPOWER64,
+		1,
+		&mpower64,
+		sizeof(Exec)+8,
+		nil,
+		commonllp64 },
 	{ ELF_MAG,			/* any elf32 */
 		"elf executable",
 		nil,

+ 2 - 0
sys/src/libmach/mkfile

@@ -20,6 +20,7 @@ FILES=\
 	6\
 	7\
 	8\
+	9\
 	vdb\
 	kdb\
 	udb\
@@ -36,6 +37,7 @@ FILES=\
 	6obj\
 	7obj\
 	8obj\
+	9obj\
 	qobj\
 	vcodas\
 

+ 3 - 0
sys/src/libmach/obj.c

@@ -25,6 +25,7 @@ int	_is2(char*),		/* in [$OS].c */
 	_is6(char*),
 	_is7(char*),
 	_is8(char*),
+	_is9(char*),
 	_isk(char*),
 	_isq(char*),
 	_isv(char*),
@@ -34,6 +35,7 @@ int	_is2(char*),		/* in [$OS].c */
 	_read6(Biobuf*, Prog*),
 	_read7(Biobuf*, Prog*),
 	_read8(Biobuf*, Prog*),
+	_read9(Biobuf*, Prog*),
 	_readk(Biobuf*, Prog*),
 	_readq(Biobuf*, Prog*),
 	_readv(Biobuf*, Prog*),
@@ -60,6 +62,7 @@ static Obj	obj[] =
 	[ObjPower]	"power .q",	_isq, _readq,
 	[ObjMips]	"mips .v",	_isv, _readv,
 	[ObjSparc64]	"sparc64 .u",	_isu, _readu,
+	[ObjPower64]	"power64 .9",	_is9, _read9,
 	[Maxobjtype]	0, 0
 };
 

+ 216 - 115
sys/src/libmach/qdb.c

@@ -4,7 +4,8 @@
 #include <mach.h>
 
 /*
- * PowerPC-specific debugger interface
+ * PowerPC-specific debugger interface,
+ * including 64-bit modes
  *	forsyth@terzarima.net
  */
 
@@ -128,6 +129,8 @@ typedef struct {
 	uchar	lk;		/* bit 31 */
 	uchar	mb;		/* bits 21-25 */
 	uchar	me;		/* bits 26-30 */
+	uchar	xmbe;		/* bits 26,21-25: mb[5] || mb[0:4], also xme */
+	uchar	xsh;		/* bits 30,16-20: sh[5] || sh[0:4] */
 	uchar	nb;		/* bits 16-20 */
 	uchar	op;		/* bits 0-5 */
 	uchar	oe;		/* bit 21 */
@@ -143,11 +146,12 @@ typedef struct {
 	uchar	to;		/* bits 6-10 */
 	uchar	imm;		/* bits 16-19 */
 	ushort	xo;		/* bits 21-30, 22-30, 26-30, or 30 (beware) */
-	long	immediate;
+	uvlong	imm64;
 	long w0;
 	long w1;
 	uvlong	addr;		/* pc of instruction */
 	short	target;
+	short	m64;		/* 64-bit mode */
 	char	*curr;		/* current fill level in output buffer */
 	char	*end;		/* end of buffer */
 	int 	size;		/* number of longs in instr */
@@ -178,6 +182,7 @@ decode(uvlong pc, Instr *i)
 		werrstr("can't read instruction: %r");
 		return -1;
 	}
+	i->m64 = asstype == APOWER64;
 	i->aa = IB(w, 30);
 	i->crba = IBF(w, 11, 15);
 	i->crbb = IBF(w, 16, 20);
@@ -203,6 +208,7 @@ decode(uvlong pc, Instr *i)
 	i->lk = IB(w, 31);
 	i->mb = IBF(w, 21, 25);
 	i->me = IBF(w, 26, 30);
+	i->xmbe = (IB(w,26)<<5) | i->mb;
 	i->nb = IBF(w, 16, 20);
 	i->op = IBF(w, 0, 5);
 	i->oe = IB(w, 21);
@@ -211,13 +217,20 @@ decode(uvlong pc, Instr *i)
 	i->rc = IB(w, 31);
 	i->rs = IBF(w, 6, 10);	/* also rd */
 	i->sh = IBF(w, 16, 20);
+	i->xsh = (IB(w, 30)<<5) | i->sh;
 	i->spr = IBF(w, 11, 20);
 	i->to = IBF(w, 6, 10);
 	i->imm = IBF(w, 16, 19);
 	i->xo = IBF(w, 21, 30);		/* bits 21-30, 22-30, 26-30, or 30 (beware) */
-	i->immediate = i->simm;
+	if(i->op == 58){	/* class of 64-bit loads */
+		i->xo = i->simm & 3;
+		i->simm &= ~3;
+	}
+	i->imm64 = i->simm;
 	if(i->op == 15)
-		i->immediate <<= 16;
+		i->imm64 <<= 16;
+	else if(i->op == 25 || i->op == 27 || i->op == 29)
+		i->imm64 = (uvlong)(i->uimm<<16);
 	i->w0 = w;
 	i->target = -1;
 	i->addr = pc;
@@ -234,12 +247,15 @@ mkinstr(uvlong pc, Instr *i)
 		return -1;
 	/*
 	 * combine ADDIS/ORI (CAU/ORIL) into MOVW
+	 * also ORIS/ORIL for unsigned in 64-bit mode
 	 */
-	if (i->op == 15 && i->ra==0) {
+	if ((i->op == 15 || i->op == 25) && i->ra==0) {
 		if(decode(pc+4, &x) < 0)
 			return -1;
 		if (x.op == 24 && x.rs == x.ra && x.ra == i->rd) {
-			i->immediate |= (x.immediate & 0xFFFF);
+			i->imm64 |= (x.imm64 & 0xFFFF);
+			if(i->op != 15)
+				i->imm64 &= 0xFFFFFFFFUL;
 			i->w1 = x.w0;
 			i->target = x.rd;
 			i->size++;
@@ -257,7 +273,7 @@ plocal(Instr *i)
 
 	if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))
 		return -1;
-	offset = s.value - i->immediate;
+	offset = s.value - i->imm64;
 	if (offset > 0) {
 		if(getauto(&s, offset, CAUTO, &s)) {
 			bprint(i, "%s+%lld(SP)", s.name, s.value);
@@ -306,12 +322,12 @@ address(Instr *i)
 {
 	if (i->ra == REGSP && plocal(i) >= 0)
 		return;
-	if (i->ra == REGSB && mach->sb && pglobal(i, mach->sb+i->immediate, 0, "(SB)") >= 0)
+	if (i->ra == REGSB && mach->sb && pglobal(i, mach->sb+i->imm64, 0, "(SB)") >= 0)
 		return;
 	if(i->simm < 0)
 		bprint(i, "-%x(R%d)", -i->simm, i->ra);
 	else
-		bprint(i, "%lux(R%d)", i->immediate, i->ra);
+		bprint(i, "%llux(R%d)", i->imm64, i->ra);
 }
 
 static	char	*tcrbits[] = {"LT", "GT", "EQ", "VS"};
@@ -383,7 +399,7 @@ addis(Opcode *o, Instr *i)
 {
 	long v;
 
-	v = i->immediate;
+	v = i->imm64;
 	if (i->op==15 && i->ra == 0)
 		bprint(i, "MOVW\t$%lux,R%d", v, i->rd);
 	else if (i->op==15 && i->ra == REGSB) {
@@ -485,7 +501,8 @@ dcb(Opcode *o, Instr *i)
 static void
 lw(Opcode *o, Instr *i, char r)
 {
-	bprint(i, "%s\t", o->mnemonic);
+	format(o->mnemonic, i, 0);
+	bprint(i, "\t");
 	address(i);
 	bprint(i, ",%c%d", r, i->rd);
 }
@@ -512,7 +529,7 @@ sw(Opcode *o, Instr *i, char r)
 	m = o->mnemonic;
 	if (i->rs == REGSP) {
 		if (findsym(i->addr, CTEXT, &s) && findlocal(&s, FRAMENAME, &s)) {
-			offset = s.value-i->immediate;
+			offset = s.value-i->imm64;
 			if (offset > 0 && getauto(&s, offset, CAUTO, &s)) {
 				bprint(i, "%s\t%c%d,%s-%d(SP)", m, r, i->rd,
 					s.name, offset);
@@ -671,12 +688,16 @@ static	char	ldop[] = "%l,R%d";
 static	char	stop[] = "R%d,%l";
 static	char	fldop[] = "%l,F%d";
 static	char	fstop[] = "F%d,%l";
+static	char	rldc[] = "R%b,R%s,$%E,R%a";
 static	char	rlim[] = "R%b,R%s,$%z,R%a";
 static	char	rlimi[] = "$%k,R%s,$%z,R%a";
+static	char	rldi[] = "$%e,R%s,$%E,R%a";
 
 #define	OEM	IBF(~0,22,30)
 #define	FP4	IBF(~0,26,30)
 #define	ALL	(~0)
+#define	RLDC	0xF
+#define	RLDI	0xE
 /*
 notes:
 	10-26: crfD = rD>>2; rD&3 mbz
@@ -684,8 +705,6 @@ notes:
 */
 
 static Opcode opcodes[] = {
-	{31,	360,	OEM,	"ABS%V%C",	0,	ir2},	/* POWER */
-
 	{31,	266,	OEM,	"ADD%V%C",	add,	ir3},
 	{31,	 10,	OEM,	"ADDC%V%C",	add,	ir3},
 	{31,	138,	OEM,	"ADDE%V%C",	add,	ir3},
@@ -706,14 +725,13 @@ static Opcode opcodes[] = {
 	{19,	528,	ALL,	"BC%L",		branch,	"%d,%a,(CTR)"},
 	{19,	16,	ALL,	"BC%L",		branch,	"%d,%a,(LR)"},
 
-	{31,	531,	ALL,	"CLCS",		gen,	ir2},	/* POWER */
-
 	{31,	0,	ALL,	"CMP",		0,	icmp3},
 	{11,	0,	0,	"CMP",		0,	"R%a,%i,%D"},
 	{31,	32,	ALL,	"CMPU",		0,	icmp3},
 	{10,	0,	0,	"CMPU",		0,	"R%a,%I,%D"},
 
-	{31,	26,	ALL,	"CNTLZ%C",	gencc,	ir2},
+	{31,	58,	ALL,	"CNTLZD%C",	gencc,	ir2},	/* 64 */
+	{31,	26,	ALL,	"CNTLZ%W%C",	gencc,	ir2},
 
 	{19,	257,	ALL,	"CRAND",	gen,	cr3op},
 	{19,	129,	ALL,	"CRANDN",	gen,	cr3op},
@@ -733,14 +751,11 @@ static Opcode opcodes[] = {
 	{31,	454,	ALL,	"DCCCI",	dcb,	0},
 	{31,	966,	ALL,	"ICCCI",	dcb,	0},
 
-	{31,	331,	OEM,	"DIV%V%C",	qdiv,	ir3},	/* POWER */
-	{31,	363,	OEM,	"DIVS%V%C",	qdiv,	ir3},	/* POWER */
+	{31,	489,	OEM,	"DIVD%V%C",	qdiv,	ir3},	/* 64 */
+	{31,	457,	OEM,	"DIVDU%V%C",	qdiv,	ir3},	/* 64 */
 	{31,	491,	OEM,	"DIVW%V%C",	qdiv,	ir3},
 	{31,	459,	OEM,	"DIVWU%V%C",	qdiv,	ir3},
 
-	{31,	264,	OEM,	"DOZ%V%C",	gencc,	ir3r},	/* POWER */
-	{9,	0,	0,	"DOZ",		gen,	ir2i},	/* POWER */
-
 	{31,	310,	ALL,	"ECIWX",	ldx,	0},
 	{31,	438,	ALL,	"ECOWX",	stx,	0},
 	{31,	854,	ALL,	"EIEIO",	gen,	0},
@@ -749,12 +764,16 @@ static Opcode opcodes[] = {
 
 	{31,	954,	ALL,	"EXTSB%C",	gencc,	il2},
 	{31,	922,	ALL,	"EXTSH%C",	gencc,	il2},
+	{31,	986,	ALL,	"EXTSW%C",	gencc,	il2},	/* 64 */
 
 	{63,	264,	ALL,	"FABS%C",	gencc,	fp2},
 	{63,	21,	ALL,	"FADD%C",	gencc,	fp3},
 	{59,	21,	ALL,	"FADDS%C",	gencc,	fp3},
 	{63,	32,	ALL,	"FCMPO",	gen,	fpcmp},
 	{63,	0,	ALL,	"FCMPU",	gen,	fpcmp},
+	{63,	846,	ALL,	"FCFID%C",	gencc,	fp2},	/* 64 */
+	{63,	814,	ALL,	"FCTID%C",	gencc,	fp2},	/* 64 */
+	{63,	815,	ALL,	"FCTIDZ%C",	gencc,	fp2},	/* 64 */
 	{63,	14,	ALL,	"FCTIW%C",	gencc,	fp2},
 	{63,	15,	ALL,	"FCTIWZ%C",	gencc,	fp2},
 	{63,	18,	ALL,	"FDIV%C",	gencc,	fp3},
@@ -772,11 +791,16 @@ static Opcode opcodes[] = {
 	{59,	31,	FP4,	"FNMADDS%C",	gencc,	fp4},
 	{63,	30,	FP4,	"FNMSUB%C",	gencc,	fp4},
 	{59,	30,	FP4,	"FNMSUBS%C",	gencc,	fp4},
+	{59,	24,	ALL,	"FRES%C",	gencc,	fp2},	/* optional */
 	{63,	12,	ALL,	"FRSP%C",	gencc,	fp2},
+	{63,	26,	ALL,	"FRSQRTE%C",	gencc,	fp2},	/* optional */
+	{63,	23,	FP4,	"FSEL%CC",	gencc,	fp4},	/* optional */
+	{63,	22,	ALL,	"FSQRT%C",	gencc,	fp2},	/* optional */
+	{59,	22,	ALL,	"FSQRTS%C",	gencc,	fp2},	/* optional */
 	{63,	20,	FP4,	"FSUB%C",	gencc,	fp3},
 	{59,	20,	FP4,	"FSUBS%C",	gencc,	fp3},
 
-	{31,	982,	ALL,	"ICBI",		dcb,	0},
+	{31,	982,	ALL,	"ICBI",		dcb,	0},	/* optional */
 	{19,	150,	ALL,	"ISYNC",	gen,	0},
 
 	{34,	0,	0,	"MOVBZ",	load,	ldop},
@@ -801,18 +825,26 @@ static Opcode opcodes[] = {
 	{31,	311,	ALL,	"MOVHZU",	ldx,	0},
 	{31,	279,	ALL,	"MOVHZ",	ldx,	0},
 	{46,	0,	0,	"MOVMW",	load,	ldop},
-	{31,	277,	ALL,	"LSCBX%C",	ldx,	0},	/* POWER */
 	{31,	597,	ALL,	"LSW",		gen,	"(R%a),$%n,R%d"},
 	{31,	533,	ALL,	"LSW",		ldx,	0},
 	{31,	20,	ALL,	"LWAR",		ldx,	0},
+	{31,	84,	ALL,	"LWARD",	ldx,	0},	/* 64 */
+
+	{58,	0,	ALL,	"MOVD",		load,	ldop},	/* 64 */
+	{58,	1,	ALL,	"MOVDU",	load,	ldop},	/* 64 */
+	{31,	53,	ALL,	"MOVDU",	ldx,	0},	/* 64 */
+	{31,	21,	ALL,	"MOVD",		ldx,	0},	/* 64 */
+
 	{31,	534,	ALL,	"MOVWBR",	ldx,	0},
-	{32,	0,	0,	"MOVW",		load,	ldop},
-	{33,	0,	0,	"MOVWU",	load,	ldop},
-	{31,	55,	ALL,	"MOVWU",	ldx,	0},
-	{31,	23,	ALL,	"MOVW",		ldx,	0},
 
-	{31,	29,	ALL,	"MASKG%C",	gencc,	"R%s:R%b,R%d"},	/* POWER */
-	{31,	541,	ALL,	"MASKIR%C",	gencc,	"R%s,R%b,R%a"},	/* POWER */
+	{58,	2,	ALL,	"MOVW",		load,	ldop},	/* 64 (lwa) */
+	{31,	373,	ALL,	"MOVWU",	ldx,	0},	/* 64 */
+	{31,	341,	ALL,	"MOVW",		ldx,	0},	/* 64 */
+
+	{32,	0,	0,	"MOVW%Z",	load,	ldop},
+	{33,	0,	0,	"MOVW%ZU",	load,	ldop},
+	{31,	55,	ALL,	"MOVW%ZU",	ldx,	0},
+	{31,	23,	ALL,	"MOVW%Z",	ldx,	0},
 
 	{19,	0,	ALL,	"MOVFL",	gen,	"%S,%D"},
 	{63,	64,	ALL,	"MOVCRFS",	gen,	"%S,%D"},
@@ -832,18 +864,20 @@ static Opcode opcodes[] = {
 	{63,	711,	ALL,	"MOVFL%C",	gencc,	"F%b,%M,FPSCR"},	/* mtfsf */
 	{63,	134,	ALL,	"MOVFL%C",	gencc,	"%K,%D"},
 	{31,	146,	ALL,	"MOVW",		gen,	"R%s,MSR"},
+	{31,	178,	ALL,	"MOVD",		gen,	"R%s,MSR"},
 	{31,	467,	ALL,	"MOVW",		gen,	"R%s,%P"},
 	{31,	210,	ALL,	"MOVW",		gen,	"R%s,SEG(%a)"},
 	{31,	242,	ALL,	"MOVW",		gen,	"R%s,SEG(R%b)"},
 
-	{31,	107,	OEM,	"MUL%V%C",	gencc,	ir3},	/* POWER */
-	{31,	75,	ALL,	"MULHW%C",	gencc,	ir3},	/* POWER */
-	{31,	11,	ALL,	"MULHWU%C",	gencc,	ir3},	/* POWER */
+	{31,	73,	ALL,	"MULHD%C",	gencc,	ir3},
+	{31,	9,	ALL,	"MULHDU%C",	gencc,	ir3},
+	{31,	233,	OEM,	"MULLD%V%C",	gencc,	ir3},
 
+	{31,	75,	ALL,	"MULHW%C",	gencc,	ir3},
+	{31,	11,	ALL,	"MULHWU%C",	gencc,	ir3},
 	{31,	235,	OEM,	"MULLW%V%C",	gencc,	ir3},
-	{7,	0,	0,	"MULLW",	qdiv,	"%i,R%a,R%d"},
 
-	{31,	488,	OEM,	"NABS%V%C",	neg,	ir2},	/* POWER */
+	{7,	0,	0,	"MULLW",	qdiv,	"%i,R%a,R%d"},
 
 	{31,	476,	ALL,	"NAND%C",	gencc,	il3},
 	{31,	104,	OEM,	"NEG%V%C",	neg,	ir2},
@@ -856,38 +890,28 @@ static Opcode opcodes[] = {
 	{19,	50,	ALL,	"RFI",		gen,	0},
 	{19,	51,	ALL,	"RFCI",		gen,	0},
 
-	{22,	0,	0,	"RLMI%C",	gencc,	rlim},	/* POWER */
+	{30,	8,	RLDC,	"RLDCL%C",	gencc,	rldc},	/* 64 */
+	{30,	9,	RLDC,	"RLDCR%C",	gencc,	rldc},	/* 64 */
+	{30,	0,	RLDI,	"RLDCL%C",	gencc,	rldi},	/* 64 */
+	{30,	1<<1, RLDI,	"RLDCR%C",	gencc,	rldi},	/* 64 */
+	{30,	2<<1, RLDI,	"RLDC%C",	gencc,	rldi},	/* 64 */
+	{30,	3<<1, RLDI,	"RLDMI%C",	gencc,	rldi},	/* 64 */
+
 	{20,	0,	0,	"RLWMI%C",	gencc,	rlimi},
 	{21,	0,	0,	"RLWNM%C",	gencc,	rlimi},
 	{23,	0,	0,	"RLWNM%C",	gencc,	rlim},
 
-	{31,	537,	ALL,	"RRIB%C",	gencc,	il3},	/* POWER */
-
 	{17,	1,	ALL,	"SYSCALL",	gen,	0},
 
-	{31,	153,	ALL,	"SLE%C",	shift,	il3},	/* POWER */
-	{31,	217,	ALL,	"SLEQ%C",	shift,	il3},	/* POWER */
-	{31,	184,	ALL,	"SLQ%C",	shifti,	il3s},	/* POWER */
-	{31,	248,	ALL,	"SLLQ%C",	shifti,	il3s},	/* POWER */
-	{31,	216,	ALL,	"SLLQ%C",	shift,	il3},	/* POWER */
-	{31,	152,	ALL,	"SLQ%C",	shift,	il3},	/* POWER */
-
+	{31,	27,	ALL,	"SLD%C",	shift,	il3},	/* 64 */
 	{31,	24,	ALL,	"SLW%C",	shift,	il3},
 
-	{31,	920,	ALL,	"SRAQ%C",	shift,	il3},	/* POWER */
-	{31,	952,	ALL,	"SRAQ%C",	shifti,	il3s},	/* POWER */
-
+	{31,	794,	ALL,	"SRAD%C",	shift,	il3},	/* 64 */
+	{31,	413,	ALL,	"SRAD%C",	shifti,	il3s},	/* 64 */
 	{31,	792,	ALL,	"SRAW%C",	shift,	il3},
 	{31,	824,	ALL,	"SRAW%C",	shifti,	il3s},
 
-	{31,	665,	ALL,	"SRE%C",	shift,	il3},	/* POWER */
-	{31,	921,	ALL,	"SREA%C",	shift,	il3},	/* POWER */
-	{31,	729,	ALL,	"SREQ%C",	shift,	il3},	/* POWER */
-	{31,	696,	ALL,	"SRQ%C",	shifti,	il3s},	/* POWER */
-	{31,	760,	ALL,	"SRLQ%C",	shifti,	il3s},	/* POWER */
-	{31,	728,	ALL,	"SRLQ%C",	shift,	il3},	/* POWER */
-	{31,	664,	ALL,	"SRQ%C",	shift,	il3},	/* POWER */
-
+	{31,	539,	ALL,	"SRD%C",	shift,	il3},	/* 64 */
 	{31,	536,	ALL,	"SRW%C",	shift,	il3},
 
 	{38,	0,	0,	"MOVB",		store,	stop},
@@ -913,10 +937,22 @@ static Opcode opcodes[] = {
 	{36,	0,	0,	"MOVW",		store,	stop},
 	{31,	662,	ALL,	"MOVWBR",	stx,	0},
 	{31,	150,	ALL,	"STWCCC",	stx,	0},
+	{31,	214,	ALL,	"STDCCC",	stx,	0},	/* 64 */
 	{37,	0,	0,	"MOVWU",	store,	stop},
 	{31,	183,	ALL,	"MOVWU",	stx,	0},
 	{31,	151,	ALL,	"MOVW",		stx,	0},
 
+	{62,	0,	0,	"MOVD%U",	store,	stop},	/* 64 */
+	{31,	149,	ALL,	"MOVD",		stx,	0,},	/* 64 */
+	{31,	181,	ALL,	"MOVDU",	stx,	0},	/* 64 */
+
+	{31,	498,	ALL,	"SLBIA",	gen,	0},	/* 64 */
+	{31,	434,	ALL,	"SLBIE",	gen,	"R%b"},	/* 64 */
+	{31,	466,	ALL,	"SLBIEX",	gen,	"R%b"},	/* 64 */
+	{31,	915,	ALL,	"SLBMFEE",	gen,	"R%b,R%d"},	/* 64 */
+	{31,	851,	ALL,	"SLBMFEV",	gen,	"R%b,R%d"},	/* 64 */
+	{31,	402,	ALL,	"SLBMTE",	gen,	"R%s,R%b"},	/* 64 */
+
 	{31,	40,	OEM,	"SUB%V%C",	sub,	ir3},
 	{31,	8,	OEM,	"SUBC%V%C",	sub,	ir3},
 	{31,	136,	OEM,	"SUBE%V%C",	sub,	ir3},
@@ -924,11 +960,15 @@ static Opcode opcodes[] = {
 	{31,	232,	OEM,	"SUBME%V%C",	sub,	ir2},
 	{31,	200,	OEM,	"SUBZE%V%C",	sub,	ir2},
 
-	{31,	598,	ALL,	"SYNC",		gen,	0},
-	{31,	370,	ALL,	"TLBIA",	gen,	0},
-	{31,	306,	ALL,	"TLBIE",	gen,	"R%b"},
-	{31,	1010,	ALL,	"TLBLI",	gen,	"R%b"},
-	{31,	978,	ALL,	"TLBLD",	gen,	"R%b"},
+	{31,	598,	ALL,	"SYNC",		gen,	0},	/* TO DO: there's a parameter buried in there */
+	{2,	0,	0,	"TD",		gen,	"%d,R%a,%i"},	/* 64 */
+	{31,	370,	ALL,	"TLBIA",	gen,	0},	/* optional */
+	{31,	306,	ALL,	"TLBIE",	gen,	"R%b"},	/* optional */
+	{31,	274,	ALL,	"TLBIEL",	gen,	"R%b"},	/* optional */
+	{31,	1010,	ALL,	"TLBLI",	gen,	"R%b"},	/* optional */
+	{31,	978,	ALL,	"TLBLD",	gen,	"R%b"},	/* optional */
+	{31,	566,	ALL,	"TLBSYNC",	gen,	0},	/* optional */
+	{31,	68,	ALL,	"TD",		gen,	"%d,R%a,R%b"},	/* 64 */
 	{31,	4,	ALL,	"TW",		gen,	"%d,R%a,R%b"},
 	{3,	0,	0,	"TW",		gen,	"%d,R%a,%i"},
 
@@ -995,11 +1035,31 @@ static	Spr	sprname[] = {
 	{0,0},
 };
 
+static int
+shmask(uvlong *m)
+{
+	int i;
+
+	for(i=0; i<63; i++)
+		if(*m & ((uvlong)1<<i))
+			break;
+	if(i > 63)
+		return 0;
+	if(*m & ~((uvlong)1<<i)){	/* more than one bit: do multiples of bytes */
+		i = (i/8)*8;
+		if(i == 0)
+			return 0;
+	}
+	*m >>= i;
+	return i;
+}
+
 static void
 format(char *mnemonic, Instr *i, char *f)
 {
 	int n, s;
 	ulong mask;
+	uvlong vmask;
 
 	if (mnemonic)
 		format(0, i, mnemonic);
@@ -1013,15 +1073,6 @@ format(char *mnemonic, Instr *i, char *f)
 			continue;
 		}
 		switch (*++f) {
-		case 'V':
-			if(i->oe)
-				bprint(i, "V");
-			break;
-
-		case 'C':
-			if(i->rc)
-				bprint(i, "CC");
-			break;
 
 		case 'a':
 			bprint(i, "%d", i->ra);
@@ -1040,13 +1091,9 @@ format(char *mnemonic, Instr *i, char *f)
 			bprint(i, "%d", i->rd);
 			break;
 
-		case 'S':
-			if(i->ra & 3)
-				bprint(i, "CR(INVAL:%d)", i->ra);
-			else if(i->op == 63)
-				bprint(i, "FPSCR(%d)", i->crfs);
-			else
-				bprint(i, "CR(%d)", i->crfs);
+		case 'C':
+			if(i->rc)
+				bprint(i, "CC");
 			break;
 
 		case 'D':
@@ -1058,11 +1105,29 @@ format(char *mnemonic, Instr *i, char *f)
 				bprint(i, "CR(%d)", i->crfd);
 			break;
 
-		case 'l':
-			if(i->simm < 0)
-				bprint(i, "-%x(R%d)", -i->simm, i->ra);
+		case 'e':
+			bprint(i, "%d", i->xsh);
+			break;
+
+		case 'E':
+			switch(IBF(i->w0,27,30)){	/* low bit is top bit of shift in rldiX cases */
+			case 8:	i->mb = i->xmbe; i->me = 63; break;	/* rldcl */
+			case 9:	i->mb = 0; i->me = i->xmbe; break;	/* rldcr */
+			case 4: case 5:
+					i->mb = i->xmbe; i->me = 63-i->xsh; break;	/* rldic */
+			case 0: case 1:
+					i->mb = i->xmbe; i->me = 63; break;	/* rldicl */
+			case 2: case 3:
+					i->mb = 0; i->me = i->xmbe; break;	/* rldicr */
+			case 6: case 7:
+					i->mb = i->xmbe; i->me = 63-i->xsh; break;	/* rldimi */
+			}
+			vmask = (~(uvlong)0>>i->mb) & (~(uvlong)0<<(63-i->me));
+			s = shmask(&vmask);
+			if(s)
+				bprint(i, "(%llux<<%d)", vmask, s);
 			else
-				bprint(i, "%x(R%d)", i->simm, i->ra);
+				bprint(i, "%llux", vmask);
 			break;
 
 		case 'i':
@@ -1073,8 +1138,50 @@ format(char *mnemonic, Instr *i, char *f)
 			bprint(i, "$%ux", i->uimm);
 			break;
 
-		case 'w':
-			bprint(i, "[%lux]", i->w0);
+		case 'j':
+			if(i->aa)
+				pglobal(i, i->li, 1, "(SB)");
+			else
+				pglobal(i, i->addr+i->li, 1, "");
+			break;
+
+		case 'J':
+			if(i->aa)
+				pglobal(i, i->bd, 1, "(SB)");
+			else
+				pglobal(i, i->addr+i->bd, 1, "");
+			break;
+
+		case 'k':
+			bprint(i, "%d", i->sh);
+			break;
+
+		case 'K':
+			bprint(i, "$%x", i->imm);
+			break;
+
+		case 'L':
+			if(i->lk)
+				bprint(i, "L");
+			break;
+
+		case 'l':
+			if(i->simm < 0)
+				bprint(i, "-%x(R%d)", -i->simm, i->ra);
+			else
+				bprint(i, "%x(R%d)", i->simm, i->ra);
+			break;
+
+		case 'm':
+			bprint(i, "%ux", i->crm);
+			break;
+
+		case 'M':
+			bprint(i, "%ux", i->fm);
+			break;
+
+		case 'n':
+			bprint(i, "%d", i->nb==0? 32: i->nb);	/* eg, pg 10-103 */
 			break;
 
 		case 'P':
@@ -1096,51 +1203,45 @@ format(char *mnemonic, Instr *i, char *f)
 			bprint(i, "%d", n);
 			break;
 
-		case 'n':
-			bprint(i, "%d", i->nb==0? 32: i->nb);	/* eg, pg 10-103 */
-			break;
-
-		case 'm':
-			bprint(i, "%ux", i->crm);
-			break;
-
-		case 'M':
-			bprint(i, "%ux", i->fm);
+		case 'S':
+			if(i->ra & 3)
+				bprint(i, "CR(INVAL:%d)", i->ra);
+			else if(i->op == 63)
+				bprint(i, "FPSCR(%d)", i->crfs);
+			else
+				bprint(i, "CR(%d)", i->crfs);
 			break;
 
-		case 'z':
-			if(i->mb <= i->me)
-				mask = ((ulong)~0L>>i->mb) & (~0L<<(31-i->me));
-			else
-				mask = ~(((ulong)~0L>>(i->me+1)) & (~0L<<(31-(i->mb-1))));
-			bprint(i, "%lux", mask);
+		case 'U':
+			if(i->rc)
+				bprint(i, "U");
 			break;
 
-		case 'k':
-			bprint(i, "%d", i->sh);
+		case 'V':
+			if(i->oe)
+				bprint(i, "V");
 			break;
 
-		case 'K':
-			bprint(i, "$%x", i->imm);
+		case 'w':
+			bprint(i, "[%lux]", i->w0);
 			break;
 
-		case 'L':
-			if(i->lk)
-				bprint(i, "L");
+		case 'W':
+			if(i->m64)
+				bprint(i, "W");
 			break;
 
-		case 'j':
-			if(i->aa)
-				pglobal(i, i->li, 1, "(SB)");
-			else
-				pglobal(i, i->addr+i->li, 1, "");
+		case 'Z':
+			if(i->m64)
+				bprint(i, "Z");
 			break;
 
-		case 'J':
-			if(i->aa)
-				pglobal(i, i->bd, 1, "(SB)");
+		case 'z':
+			if(i->mb <= i->me)
+				mask = ((ulong)~0L>>i->mb) & (~0L<<(31-i->me));
 			else
-				pglobal(i, i->addr+i->bd, 1, "");
+				mask = ~(((ulong)~0L>>(i->me+1)) & (~0L<<(31-(i->mb-1))));
+			bprint(i, "%lux", mask);
 			break;
 
 		case '\0':

+ 7 - 1
sys/src/libmach/setmach.c

@@ -17,7 +17,7 @@ struct machtab
 };
 
 extern	Mach		mmips, msparc, m68020, mi386, mamd64,
-			marm, mmips2be, mmips2le, mpower, malpha, msparc64;
+			marm, mmips2be, mmips2le, mpower, mpower64, malpha, msparc64;
 extern	Machdata	mipsmach, sparcmach, m68020mach, i386mach,
 			armmach, mipsmach2le, powermach, alphamach, sparc64mach;
 
@@ -106,6 +106,12 @@ Machtab	machines[] =
 		APOWER,
 		&mpower,
 		&powermach,	},
+	{	"power64",			/*PowerPC*/
+		FPOWER64,
+		FPOWER64B,
+		APOWER64,
+		&mpower64,
+		&powermach,	},
 	{	"alpha",			/*Alpha*/
 		FALPHA,
 		FALPHAB,