Browse Source

Plan 9 from Bell Labs 2003-12-30

David du Colombier 21 years ago
parent
commit
0f777da348
53 changed files with 1188 additions and 479 deletions
  1. 59 59
      dist/replica/plan9.db
  2. 59 0
      dist/replica/plan9.log
  3. 1 0
      sys/include/venti.h
  4. 6 0
      sys/man/1/rio
  5. 10 4
      sys/man/8/fossilcons
  6. 1 1
      sys/src/9/bitsy/mkfile
  7. 2 2
      sys/src/9/pc/etherrhine.c
  8. 0 19
      sys/src/9/pc/l.s
  9. 3 3
      sys/src/9/pc/main.c
  10. 21 5
      sys/src/9/pc/trap.c
  11. 4 4
      sys/src/9/port/chan.c
  12. 11 0
      sys/src/9/port/devcons.c
  13. 0 1
      sys/src/9/port/edf.c
  14. 2 2
      sys/src/9/port/pgrp.c
  15. 0 1
      sys/src/9/port/portclock.c
  16. 3 8
      sys/src/9/port/portdat.h
  17. 1 19
      sys/src/9/ppc/l.s
  18. 151 131
      sys/src/9/ppc/m8260.c
  19. 49 44
      sys/src/9/ppc/main.c
  20. 4 5
      sys/src/9/ppc/mem.h
  21. 15 13
      sys/src/9/ppc/msaturn.c
  22. 3 2
      sys/src/9/ppc/saturntimer.c
  23. 43 29
      sys/src/9/ppc/trap.c
  24. 1 0
      sys/src/cmd/acme/look.c
  25. 151 8
      sys/src/cmd/acme/text.c
  26. 1 0
      sys/src/cmd/disk/mkext.c
  27. 6 1
      sys/src/cmd/fortune.c
  28. 4 0
      sys/src/cmd/fossil/9dir.c
  29. 7 3
      sys/src/cmd/fossil/9p.c
  30. 2 2
      sys/src/cmd/fossil/9proc.c
  31. 14 3
      sys/src/cmd/fossil/archive.c
  32. 25 57
      sys/src/cmd/fossil/cache.c
  33. 7 1
      sys/src/cmd/fossil/disk.c
  34. 1 0
      sys/src/cmd/fossil/error.c
  35. 1 0
      sys/src/cmd/fossil/error.h
  36. 132 6
      sys/src/cmd/fossil/file.c
  37. 22 2
      sys/src/cmd/fossil/flfmt.c
  38. 2 0
      sys/src/cmd/fossil/fns.h
  39. 11 1
      sys/src/cmd/fossil/fossil.c
  40. 1 1
      sys/src/cmd/fossil/fs.c
  41. 2 0
      sys/src/cmd/fossil/fs.h
  42. 11 0
      sys/src/cmd/fossil/mkfile
  43. 63 4
      sys/src/cmd/fossil/source.c
  44. 15 1
      sys/src/cmd/ip/httpd/httpd.c
  45. 7 2
      sys/src/cmd/ip/ppp/compress.c
  46. 2 0
      sys/src/cmd/ip/ppp/ppp.c
  47. 1 0
      sys/src/cmd/ip/ppp/ppp.h
  48. 22 5
      sys/src/cmd/paqfs/mkpaqfs.c
  49. 63 12
      sys/src/cmd/paqfs/paqfs.c
  50. 5 3
      sys/src/cmd/paqfs/paqfs.h
  51. 157 12
      sys/src/cmd/rio/wind.c
  52. 2 2
      sys/src/cmd/usb/audio/controls.c
  53. 2 1
      sys/src/cmd/usb/mkfile

+ 59 - 59
dist/replica/plan9.db

@@ -202,16 +202,16 @@
 386/bin/diff - 775 sys sys 1064598122 82019
 386/bin/disk - 20000000775 sys sys 984788664 0
 386/bin/disk/dump9660 - 775 sys sys 1064598123 151282
-386/bin/disk/exsort - 775 sys sys 1064598123 58541
+386/bin/disk/exsort - 775 sys sys 1072729312 58501
 386/bin/disk/fdisk - 775 sys sys 1064598124 106639
-386/bin/disk/format - 775 sys sys 1064598125 91621
+386/bin/disk/format - 775 sys sys 1072729312 91581
 386/bin/disk/kfs - 775 sys sys 1068717499 249427
-386/bin/disk/kfscmd - 775 sys sys 1064598127 38451
+386/bin/disk/kfscmd - 775 sys sys 1072729312 38425
 386/bin/disk/ksync - 775 sys sys 1020319074 302
-386/bin/disk/mbr - 775 sys sys 1064598127 73194
+386/bin/disk/mbr - 775 sys sys 1072729313 73154
 386/bin/disk/mk9660 - 775 sys sys 1020319074 144
 386/bin/disk/mkext - 775 sys sys 1071245301 77957
-386/bin/disk/mkfs - 775 sys sys 1064598129 87215
+386/bin/disk/mkfs - 775 sys sys 1072729313 87175
 386/bin/disk/mksacfs - 775 sys sys 1020319074 71451
 386/bin/disk/prep - 775 sys sys 1069592365 99123
 386/bin/disk/sacfs - 775 sys sys 1020319075 79882
@@ -306,7 +306,7 @@
 386/bin/md5sum - 775 sys sys 1064598252 59465
 386/bin/mk - 775 sys sys 1064598253 143638
 386/bin/mkdir - 775 sys sys 1064598253 57591
-386/bin/mkpaqfs - 775 sys sys 1064598254 93244
+386/bin/mkpaqfs - 775 sys sys 1072729575 94045
 386/bin/mkstate - 775 sys sys 1064598255 61927
 386/bin/mntgen - 775 sys sys 1064598256 136777
 386/bin/mount - 775 sys sys 1064598256 71496
@@ -334,7 +334,7 @@
 386/bin/ns - 775 sys sys 1064598273 63582
 386/bin/p - 775 sys sys 1064598274 63537
 386/bin/page - 775 sys sys 1071245340 216518
-386/bin/paqfs - 775 sys sys 1064598276 107830
+386/bin/paqfs - 775 sys sys 1072729576 109516
 386/bin/passwd - 775 sys sys 1069592374 80215
 386/bin/pbd - 775 sys sys 1038443175 4663
 386/bin/pcc - 775 sys sys 1064598277 66117
@@ -367,7 +367,7 @@
 386/bin/replica/setupdirs - 775 sys sys 1020319083 44
 386/bin/replica/updatedb - 775 sys sys 1068558250 95126
 386/bin/resample - 775 sys sys 1064598294 120124
-386/bin/rio - 775 sys sys 1071245344 303330
+386/bin/rio - 775 sys sys 1072729027 312035
 386/bin/rm - 775 sys sys 1064598298 59786
 386/bin/rtstats - 775 sys sys 1071245345 177818
 386/bin/rx - 775 sys sys 1071245345 80158
@@ -3417,7 +3417,7 @@ sys/include/sunrpc.h - 664 sys sys 1046367129 7219
 sys/include/thread.h - 664 sys sys 1045504289 3562
 sys/include/tos.h - 664 sys sys 1067718947 562
 sys/include/trace.h - 664 sys sys 1068393680 585
-sys/include/venti.h - 664 sys sys 1045504293 6956
+sys/include/venti.h - 664 sys sys 1072705708 7049
 sys/lib - 20000000775 sys sys 1018580948 0
 sys/lib/acid - 20000000775 sys sys 1016926088 0
 sys/lib/acid/386 - 664 sys sys 1032058272 2588
@@ -4680,7 +4680,7 @@ sys/man/1/pwd - 664 sys sys 957920008 930
 sys/man/1/rc - 664 sys sys 953844589 19457
 sys/man/1/replica - 664 sys sys 1021927495 6619
 sys/man/1/resample - 664 sys sys 1015024740 1083
-sys/man/1/rio - 664 sys sys 1015024740 14087
+sys/man/1/rio - 664 sys sys 1072729053 14321
 sys/man/1/rm - 664 sys sys 944959673 515
 sys/man/1/rtstats - 664 sys sys 1018897631 2108
 sys/man/1/rwd - 664 sys sys 1042469992 2958
@@ -5021,7 +5021,7 @@ sys/man/8/cpurc - 664 sys sys 971455510 1275
 sys/man/8/cron - 664 sys sys 1063858596 1867
 sys/man/8/dhcpd - 664 sys sys 1032654987 5237
 sys/man/8/drawterm - 664 sys sys 958419689 2458
-sys/man/8/fossilcons - 664 sys sys 1069884636 15073
+sys/man/8/fossilcons - 664 sys sys 1072705694 15161
 sys/man/8/fs - 664 sys sys 1055701170 15029
 sys/man/8/fsconfig - 664 sys sys 1045501600 8142
 sys/man/8/httpd - 664 sys sys 1065640802 6426
@@ -5158,7 +5158,7 @@ sys/src/9/bitsy/l.s - 664 sys sys 1055700934 18211
 sys/src/9/bitsy/main.c - 664 sys sys 1067722593 9083
 sys/src/9/bitsy/map - 664 sys sys 1017695515 236
 sys/src/9/bitsy/mem.h - 664 sys sys 1055700932 8049
-sys/src/9/bitsy/mkfile - 664 sys sys 1071671673 2466
+sys/src/9/bitsy/mkfile - 664 sys sys 1072705544 2452
 sys/src/9/bitsy/mmu.c - 664 sys sys 1055700931 11228
 sys/src/9/bitsy/mouse.c - 664 sys sys 1017695516 962
 sys/src/9/bitsy/paqfiles - 20000000775 sys sys 1020011250 0
@@ -5302,7 +5302,7 @@ sys/src/9/pc/etherif.h - 664 sys sys 1045063564 961
 sys/src/9/pc/etherigbe.c - 664 sys sys 1071245461 42444
 sys/src/9/pc/ethermii.c - 664 sys sys 1039803177 4555
 sys/src/9/pc/ethermii.h - 664 sys sys 1039895684 3259
-sys/src/9/pc/etherrhine.c - 664 sys sys 1068244865 13437
+sys/src/9/pc/etherrhine.c - 664 sys sys 1072704797 13438
 sys/src/9/pc/ethersink.c - 664 sys sys 1048644103 1076
 sys/src/9/pc/ethersmc.c - 664 sys sys 1071245461 15103
 sys/src/9/pc/etherwavelan.c - 664 sys sys 1026847642 3722
@@ -5315,8 +5315,8 @@ sys/src/9/pc/init9.c - 664 sys sys 1040002518 94
 sys/src/9/pc/initcode.s - 664 sys sys 1015014519 282
 sys/src/9/pc/io.h - 664 sys sys 1067722633 7991
 sys/src/9/pc/kbd.c - 664 sys sys 1071726245 9135
-sys/src/9/pc/l.s - 664 sys sys 1071514801 23314
-sys/src/9/pc/main.c - 664 sys sys 1067722634 14685
+sys/src/9/pc/l.s - 664 sys sys 1072704796 22700
+sys/src/9/pc/main.c - 664 sys sys 1072704797 14685
 sys/src/9/pc/mem.h - 664 sys sys 1018553448 4573
 sys/src/9/pc/memory.c - 664 sys sys 1071245460 13028
 sys/src/9/pc/mkfile - 664 sys sys 1067810339 3219
@@ -5351,7 +5351,7 @@ sys/src/9/pc/sd53c8xx.n - 664 sys sys 1032059019 12455
 sys/src/9/pc/sdata.c - 664 sys sys 1071615236 50538
 sys/src/9/pc/sdmylex.c - 664 sys sys 1071245460 27812
 sys/src/9/pc/sdscsi.c - 664 sys sys 1055689892 7406
-sys/src/9/pc/trap.c - 664 sys sys 1068237910 20045
+sys/src/9/pc/trap.c - 664 sys sys 1072704797 20506
 sys/src/9/pc/uarti8250.c - 664 sys sys 1067722686 13859
 sys/src/9/pc/uartpci.c - 664 sys sys 1015014524 2709
 sys/src/9/pc/usb.h - 664 sys sys 1063857246 3566
@@ -5388,14 +5388,14 @@ sys/src/9/port/alloc.c - 664 sys sys 1067722763 5329
 sys/src/9/port/allocb.c - 664 sys sys 1067722759 3200
 sys/src/9/port/auth.c - 664 sys sys 1055688251 2308
 sys/src/9/port/cache.c - 664 sys sys 1055688274 9241
-sys/src/9/port/chan.c - 664 sys sys 1067722721 29156
+sys/src/9/port/chan.c - 664 sys sys 1072704672 29140
 sys/src/9/port/cis.c - 664 sys sys 1055688285 8082
 sys/src/9/port/debugalloc.c - 664 sys sys 1014931171 10402
 sys/src/9/port/dev.c - 664 sys sys 1067722718 8348
 sys/src/9/port/devaudio.c - 664 sys sys 1067722761 21130
 sys/src/9/port/devbridge.c - 664 sys sys 1055688301 24308
 sys/src/9/port/devcap.c - 664 sys sys 1048644215 4113
-sys/src/9/port/devcons.c - 664 sys sys 1067722767 22064
+sys/src/9/port/devcons.c - 664 sys sys 1072704673 22374
 sys/src/9/port/devdraw.c - 664 sys sys 1039753332 41987
 sys/src/9/port/devdup.c - 664 sys sys 1014931172 2332
 sys/src/9/port/devenv.c - 664 sys sys 1048644225 6992
@@ -5419,7 +5419,7 @@ sys/src/9/port/devssl.c - 664 sys sys 1045063590 26100
 sys/src/9/port/devtinyfs.c - 664 sys sys 1015278339 15347
 sys/src/9/port/devtls.c - 664 sys sys 1066737478 45222
 sys/src/9/port/devuart.c - 664 sys sys 1067722718 11683
-sys/src/9/port/edf.c - 664 sys sys 1068393229 12343
+sys/src/9/port/edf.c - 664 sys sys 1072704672 12331
 sys/src/9/port/edf.h - 664 sys sys 1067722760 1124
 sys/src/9/port/error.h - 664 sys sys 1055700517 2630
 sys/src/9/port/fault.c - 664 sys sys 1067722722 6628
@@ -5446,9 +5446,9 @@ sys/src/9/port/netif.h - 664 sys sys 1066514947 2975
 sys/src/9/port/nulledf.c - 664 sys sys 1037669300 821
 sys/src/9/port/page.c - 664 sys sys 1055688510 8107
 sys/src/9/port/parse.c - 664 sys sys 1014931177 2026
-sys/src/9/port/pgrp.c - 664 sys sys 1067722718 3944
-sys/src/9/port/portclock.c - 664 sys sys 1068135508 4305
-sys/src/9/port/portdat.h - 664 sys sys 1071247312 22639
+sys/src/9/port/pgrp.c - 664 sys sys 1072704671 3940
+sys/src/9/port/portclock.c - 664 sys sys 1072704672 4294
+sys/src/9/port/portdat.h - 664 sys sys 1072704671 22700
 sys/src/9/port/portfns.h - 664 sys sys 1068215525 11376
 sys/src/9/port/portmkfile - 664 sys sys 1067722766 2098
 sys/src/9/port/print.c - 664 sys sys 1014931178 227
@@ -5488,22 +5488,22 @@ sys/src/9/ppc/fns.h - 664 sys sys 1067722798 4211
 sys/src/9/ppc/init9.s - 664 sys sys 1059490827 572
 sys/src/9/ppc/initcode - 664 sys sys 1059490754 444
 sys/src/9/ppc/io.h - 664 sys sys 1059490752 1017
-sys/src/9/ppc/l.s - 664 sys sys 1067722848 21035
+sys/src/9/ppc/l.s - 664 sys sys 1072705423 20411
 sys/src/9/ppc/lblast.h - 664 sys sys 1059490752 1694
 sys/src/9/ppc/lucu.h - 664 sys sys 1059490752 935
-sys/src/9/ppc/m8260.c - 664 sys sys 1059490752 14264
+sys/src/9/ppc/m8260.c - 664 sys sys 1072705483 14480
 sys/src/9/ppc/m8260.h - 664 sys sys 1068135488 20913
-sys/src/9/ppc/main.c - 664 sys sys 1059490752 9203
+sys/src/9/ppc/main.c - 664 sys sys 1072705483 9044
 sys/src/9/ppc/mcc.c - 664 sys sys 1059490752 9667
-sys/src/9/ppc/mem.h - 664 sys sys 1059490752 7015
+sys/src/9/ppc/mem.h - 664 sys sys 1072705482 6998
 sys/src/9/ppc/mkfile - 664 sys sys 1067722849 1813
 sys/src/9/ppc/mmu.c - 664 sys sys 1059490753 4865
-sys/src/9/ppc/msaturn.c - 664 sys sys 1059490753 3009
+sys/src/9/ppc/msaturn.c - 664 sys sys 1072705482 2801
 sys/src/9/ppc/msaturn.h - 664 sys sys 1059490753 99
 sys/src/9/ppc/mtx.c - 664 sys sys 1059490753 177
 sys/src/9/ppc/random.c - 664 sys sys 1059490753 1983
-sys/src/9/ppc/saturntimer.c - 664 sys sys 1059490753 1734
-sys/src/9/ppc/trap.c - 664 sys sys 1059490753 17248
+sys/src/9/ppc/saturntimer.c - 664 sys sys 1072705482 1737
+sys/src/9/ppc/trap.c - 664 sys sys 1072705481 17531
 sys/src/9/ppc/uartsaturn.c - 664 sys sys 1059490754 7151
 sys/src/9/ppc/uartsmc.c - 664 sys sys 1068135489 11462
 sys/src/9/ppc/ucu - 664 sys sys 1067722849 672
@@ -6782,12 +6782,12 @@ sys/src/cmd/acme/exec.c - 664 sys sys 1067723165 27057
 sys/src/cmd/acme/file.c - 664 sys sys 1044626079 5717
 sys/src/cmd/acme/fns.h - 664 sys sys 1067723164 2922
 sys/src/cmd/acme/fsys.c - 664 sys sys 1022512648 12727
-sys/src/cmd/acme/look.c - 664 sys sys 1072019591 14096
+sys/src/cmd/acme/look.c - 664 sys sys 1072729041 14132
 sys/src/cmd/acme/mkfile - 664 sys sys 1058463682 543
 sys/src/cmd/acme/regx.c - 664 sys sys 1014926094 16057
 sys/src/cmd/acme/rows.c - 664 sys sys 1068140772 14637
 sys/src/cmd/acme/scrl.c - 664 sys sys 1014926095 3072
-sys/src/cmd/acme/text.c - 664 sys sys 1045504840 24133
+sys/src/cmd/acme/text.c - 664 sys sys 1072729041 26813
 sys/src/cmd/acme/time.c - 664 sys sys 1014926095 1783
 sys/src/cmd/acme/util.c - 664 sys sys 1045546057 6435
 sys/src/cmd/acme/wind.c - 664 sys sys 1016833877 11063
@@ -7394,7 +7394,7 @@ sys/src/cmd/disk/kfs/sub.c - 664 sys sys 1022008488 10804
 sys/src/cmd/disk/kfs/uid.c - 664 sys sys 1071335904 6791
 sys/src/cmd/disk/kfscmd.c - 664 sys sys 1015009135 1109
 sys/src/cmd/disk/mbr.c - 664 sys sys 1063855285 4325
-sys/src/cmd/disk/mkext.c - 664 sys sys 1070377355 5716
+sys/src/cmd/disk/mkext.c - 664 sys sys 1072729311 5727
 sys/src/cmd/disk/mkfile - 664 sys sys 1022385851 500
 sys/src/cmd/disk/mkfs.c - 664 sys sys 1032059493 14298
 sys/src/cmd/disk/prep - 20000000775 sys sys 988249968 0
@@ -7512,53 +7512,53 @@ sys/src/cmd/fax/send.c - 664 sys sys 944960990 923
 sys/src/cmd/fax/subr.c - 664 sys sys 1015090401 1245
 sys/src/cmd/file.c - 664 sys sys 1071719684 20614
 sys/src/cmd/fmt.c - 664 sys sys 1070032009 4088
-sys/src/cmd/fortune.c - 664 sys sys 1035832953 1674
+sys/src/cmd/fortune.c - 664 sys sys 1072729222 1779
 sys/src/cmd/fossil - 20000000775 sys sys 1042005512 0
 sys/src/cmd/fossil/9.h - 664 sys sys 1069683864 4268
 sys/src/cmd/fossil/9auth.c - 664 sys sys 1061530721 3393
-sys/src/cmd/fossil/9dir.c - 664 sys sys 1042005502 1995
+sys/src/cmd/fossil/9dir.c - 664 sys sys 1072705704 2075
 sys/src/cmd/fossil/9excl.c - 664 sys sys 1042005502 1887
 sys/src/cmd/fossil/9fid.c - 664 sys sys 1045600016 5521
 sys/src/cmd/fossil/9fsys.c - 664 sys sys 1068591358 29979
 sys/src/cmd/fossil/9lstn.c - 664 sys sys 1042005503 2865
-sys/src/cmd/fossil/9p.c - 664 sys sys 1069818231 21498
+sys/src/cmd/fossil/9p.c - 664 sys sys 1072705703 21629
 sys/src/cmd/fossil/9ping.c - 664 sys sys 1042005503 1563
-sys/src/cmd/fossil/9proc.c - 664 sys sys 1069683861 14521
+sys/src/cmd/fossil/9proc.c - 664 sys sys 1072705704 14523
 sys/src/cmd/fossil/9srv.c - 664 sys sys 1066098097 3682
 sys/src/cmd/fossil/9user.c - 664 sys sys 1071179088 17260
 sys/src/cmd/fossil/Ccli.c - 664 sys sys 1042005504 1624
 sys/src/cmd/fossil/Ccmd.c - 664 sys sys 1066098098 7244
 sys/src/cmd/fossil/Ccons.c - 664 sys sys 1055703737 6620
 sys/src/cmd/fossil/Clog.c - 664 sys sys 1042005505 591
-sys/src/cmd/fossil/archive.c - 664 sys sys 1061530723 9109
+sys/src/cmd/fossil/archive.c - 664 sys sys 1072705705 9558
 sys/src/cmd/fossil/build - 664 sys sys 1042005505 449
 sys/src/cmd/fossil/buildsh - 775 sys sys 1042005505 561
 sys/src/cmd/fossil/bwatch.c - 664 sys sys 1042005505 6754
-sys/src/cmd/fossil/cache.c - 664 sys sys 1071007936 43090
+sys/src/cmd/fossil/cache.c - 664 sys sys 1072705706 42740
 sys/src/cmd/fossil/conf.rc - 775 sys sys 1055703747 1407
 sys/src/cmd/fossil/dat.h - 664 sys sys 1061530727 7851
 sys/src/cmd/fossil/deadlock - 775 sys sys 1042005506 413
-sys/src/cmd/fossil/disk.c - 664 sys sys 1068526661 6336
+sys/src/cmd/fossil/disk.c - 664 sys sys 1072705706 6409
 sys/src/cmd/fossil/dump.c - 664 sys sys 1042005506 1340
 sys/src/cmd/fossil/epoch.c - 664 sys sys 1045600021 997
-sys/src/cmd/fossil/error.c - 664 sys sys 1042005507 1367
-sys/src/cmd/fossil/error.h - 664 sys sys 1042005507 744
-sys/src/cmd/fossil/file.c - 664 sys sys 1066848926 28000
+sys/src/cmd/fossil/error.c - 664 sys sys 1072705707 1413
+sys/src/cmd/fossil/error.h - 664 sys sys 1072705710 772
+sys/src/cmd/fossil/file.c - 664 sys sys 1072705707 30231
 sys/src/cmd/fossil/flchk.c - 664 sys sys 1061530720 14296
-sys/src/cmd/fossil/flfmt.c - 664 sys sys 1061530720 10358
+sys/src/cmd/fossil/flfmt.c - 664 sys sys 1072705703 10799
 sys/src/cmd/fossil/flproto - 664 sys sys 1042005508 210
-sys/src/cmd/fossil/fns.h - 664 sys sys 1068526660 3077
+sys/src/cmd/fossil/fns.h - 664 sys sys 1072705709 3168
 sys/src/cmd/fossil/fossil-acid - 664 sys sys 1042005508 3965
-sys/src/cmd/fossil/fossil.c - 664 sys sys 1069683860 2114
-sys/src/cmd/fossil/fs.c - 664 sys sys 1061530725 21071
-sys/src/cmd/fossil/fs.h - 664 sys sys 1055703744 1398
+sys/src/cmd/fossil/fossil.c - 664 sys sys 1072705702 2450
+sys/src/cmd/fossil/fs.c - 664 sys sys 1072705707 21071
+sys/src/cmd/fossil/fs.h - 664 sys sys 1072705709 1489
 sys/src/cmd/fossil/history - 664 sys sys 1055703793 1400
 sys/src/cmd/fossil/invariants - 664 sys sys 1042005509 4073
-sys/src/cmd/fossil/mkfile - 664 sys sys 1055703730 1842
+sys/src/cmd/fossil/mkfile - 664 sys sys 1072705702 2077
 sys/src/cmd/fossil/nobwatch.c - 664 sys sys 1042005509 329
 sys/src/cmd/fossil/pack.c - 664 sys sys 1061530726 4682
 sys/src/cmd/fossil/periodic.c - 664 sys sys 1061530726 1087
-sys/src/cmd/fossil/source.c - 664 sys sys 1068591358 18771
+sys/src/cmd/fossil/source.c - 664 sys sys 1072705708 19899
 sys/src/cmd/fossil/srcload.c - 664 sys sys 1042005510 4178
 sys/src/cmd/fossil/stdinc.h - 664 sys sys 1042005510 155
 sys/src/cmd/fossil/trunc.c - 664 sys sys 1042005511 280
@@ -9417,7 +9417,7 @@ sys/src/cmd/ip/httpd/authorize.c - 664 sys sys 1016902735 2387
 sys/src/cmd/ip/httpd/content.c - 664 sys sys 1015090170 3140
 sys/src/cmd/ip/httpd/emem.c - 664 sys sys 984773807 278
 sys/src/cmd/ip/httpd/hints.c - 664 sys sys 1024927592 6314
-sys/src/cmd/ip/httpd/httpd.c - 664 sys sys 1037722911 10356
+sys/src/cmd/ip/httpd/httpd.c - 664 sys sys 1072729008 10663
 sys/src/cmd/ip/httpd/httpsrv.h - 664 sys sys 1016466463 1388
 sys/src/cmd/ip/httpd/imagemap.c - 664 sys sys 984773808 5229
 sys/src/cmd/ip/httpd/init.c - 664 sys sys 1015090171 2182
@@ -9458,15 +9458,15 @@ sys/src/cmd/ip/mkfile - 664 sys sys 1063897563 1250
 sys/src/cmd/ip/ping.c - 664 sys sys 1061496964 5552
 sys/src/cmd/ip/ppp - 20000000775 sys sys 988249980 0
 sys/src/cmd/ip/ppp/block.c - 664 sys sys 1015090266 5353
-sys/src/cmd/ip/ppp/compress.c - 664 sys sys 1015090266 11743
+sys/src/cmd/ip/ppp/compress.c - 664 sys sys 1072729513 11774
 sys/src/cmd/ip/ppp/doclient - 775 sys sys 944961007 50
 sys/src/cmd/ip/ppp/doserve - 775 sys sys 944961009 91
 sys/src/cmd/ip/ppp/dotest - 775 sys sys 944961006 152
 sys/src/cmd/ip/ppp/ipaux.c - 664 sys sys 1015090266 2326
 sys/src/cmd/ip/ppp/mkfile - 664 sys sys 1063897576 352
 sys/src/cmd/ip/ppp/mppc.c - 664 sys sys 1015090267 16624
-sys/src/cmd/ip/ppp/ppp.c - 664 sys sys 1065963823 59455
-sys/src/cmd/ip/ppp/ppp.h - 664 sys sys 1050360942 8225
+sys/src/cmd/ip/ppp/ppp.c - 664 sys sys 1072729353 59503
+sys/src/cmd/ip/ppp/ppp.h - 664 sys sys 1072729353 8260
 sys/src/cmd/ip/ppp/testppp.c - 664 sys sys 1045505281 3011
 sys/src/cmd/ip/ppp/thw.c - 664 sys sys 1015090268 5962
 sys/src/cmd/ip/ppp/thwack.c - 664 sys sys 1015090268 8004
@@ -9760,9 +9760,9 @@ sys/src/cmd/page/util.c - 664 sys sys 944961364 2090
 sys/src/cmd/page/view.c - 664 sys sys 1045505472 18161
 sys/src/cmd/paqfs - 20000000775 sys sys 1017696804 0
 sys/src/cmd/paqfs/mkfile - 664 sys sys 1032060366 228
-sys/src/cmd/paqfs/mkpaqfs.c - 664 sys sys 1032060367 8509
-sys/src/cmd/paqfs/paqfs.c - 664 sys sys 1032060367 18320
-sys/src/cmd/paqfs/paqfs.h - 664 sys sys 1018721430 966
+sys/src/cmd/paqfs/mkpaqfs.c - 664 sys sys 1072729575 8836
+sys/src/cmd/paqfs/paqfs.c - 664 sys sys 1072729575 19566
+sys/src/cmd/paqfs/paqfs.h - 664 sys sys 1072729575 1016
 sys/src/cmd/pbd.c - 664 sys sys 944961351 247
 sys/src/cmd/pcc.c - 664 sys sys 1048644546 5994
 sys/src/cmd/pic - 20000000775 sys sys 954037275 0
@@ -10195,7 +10195,7 @@ sys/src/cmd/rio/scrl.c - 664 sys sys 1014926357 3245
 sys/src/cmd/rio/time.c - 664 sys sys 1014926357 1829
 sys/src/cmd/rio/util.c - 664 sys sys 1014926357 2061
 sys/src/cmd/rio/wctl.c - 664 sys sys 1023206837 8808
-sys/src/cmd/rio/wind.c - 664 sys sys 1046363182 29893
+sys/src/cmd/rio/wind.c - 664 sys sys 1072729026 32762
 sys/src/cmd/rio/xfid.c - 664 sys sys 1032061723 17424
 sys/src/cmd/rm.c - 664 sys sys 1014926615 1563
 sys/src/cmd/rtstats - 20000000775 sys sys 1018897680 0
@@ -10871,7 +10871,7 @@ sys/src/cmd/usb - 20000000775 sys sys 1017802022 0
 sys/src/cmd/usb/audio - 20000000775 sys sys 1017802021 0
 sys/src/cmd/usb/audio/audioclass.h - 664 sys sys 1017802021 5463
 sys/src/cmd/usb/audio/config.c - 664 sys sys 1045503797 8526
-sys/src/cmd/usb/audio/controls.c - 664 sys sys 1045503797 13379
+sys/src/cmd/usb/audio/controls.c - 664 sys sys 1072729649 13371
 sys/src/cmd/usb/audio/dat.h - 664 sys sys 1045503798 3603
 sys/src/cmd/usb/audio/dump.c - 664 sys sys 1045503798 7065
 sys/src/cmd/usb/audio/fns.h - 664 sys sys 1018387004 474
@@ -10888,7 +10888,7 @@ sys/src/cmd/usb/lib/setup.c - 664 sys sys 1018387003 1256
 sys/src/cmd/usb/lib/usb.h - 664 sys sys 1032060786 3367
 sys/src/cmd/usb/lib/usbproto.h - 664 sys sys 1017802021 2813
 sys/src/cmd/usb/lib/util.c - 664 sys sys 1017802020 339
-sys/src/cmd/usb/mkfile - 664 sys sys 1018462835 206
+sys/src/cmd/usb/mkfile - 664 sys sys 1072728986 219
 sys/src/cmd/usb/mouse - 20000000775 sys sys 1017802022 0
 sys/src/cmd/usb/mouse/mkfile - 664 sys sys 1017802022 211
 sys/src/cmd/usb/mouse/usbmouse.c - 664 sys sys 1017802022 3074

+ 59 - 0
dist/replica/plan9.log

@@ -13180,3 +13180,62 @@
 1072227643 0 c sys/games/lib/fortunes - 664 sys sys 1072227105 247401
 1072562490 0 c sys/src/cmd/upas/smtp/smtp.c - 664 sys sys 1072561144 18914
 1072562490 1 c sys/src/cmd/upas/smtp/smtpd.c - 664 sys sys 1072561144 24496
+1072704703 0 c sys/src/9/port/chan.c - 664 sys sys 1072704672 29140
+1072704703 1 c sys/src/9/port/devcons.c - 664 sys sys 1072704673 22374
+1072704703 2 c sys/src/9/port/edf.c - 664 sys sys 1072704672 12331
+1072704703 3 c sys/src/9/port/pgrp.c - 664 sys sys 1072704671 3940
+1072704703 4 c sys/src/9/port/portclock.c - 664 sys sys 1072704672 4294
+1072704703 5 c sys/src/9/port/portdat.h - 664 sys sys 1072704671 22700
+1072706502 0 c sys/include/venti.h - 664 sys sys 1072705708 7049
+1072706502 1 c sys/man/8/fossilcons - 664 sys sys 1072705694 15161
+1072706502 2 c sys/src/9/bitsy/mkfile - 664 sys sys 1072705544 2452
+1072706502 3 c sys/src/9/pc/l.s - 664 sys sys 1072704796 22700
+1072706502 4 c sys/src/9/pc/main.c - 664 sys sys 1072704797 14685
+1072706502 5 c sys/src/9/pc/trap.c - 664 sys sys 1072704797 20506
+1072706502 6 c sys/src/9/pc/etherrhine.c - 664 sys sys 1072704797 13438
+1072706502 7 c sys/src/9/ppc/l.s - 664 sys sys 1072705423 20411
+1072706502 8 c sys/src/9/ppc/m8260.c - 664 sys sys 1072705483 14480
+1072706502 9 c sys/src/9/ppc/main.c - 664 sys sys 1072705483 9044
+1072706502 10 c sys/src/9/ppc/mem.h - 664 sys sys 1072705482 6998
+1072706502 11 c sys/src/9/ppc/msaturn.c - 664 sys sys 1072705482 2801
+1072706502 12 c sys/src/9/ppc/saturntimer.c - 664 sys sys 1072705482 1737
+1072706502 13 c sys/src/9/ppc/trap.c - 664 sys sys 1072705481 17531
+1072706502 14 c sys/src/cmd/fossil/9dir.c - 664 sys sys 1072705704 2075
+1072706502 15 c sys/src/cmd/fossil/9p.c - 664 sys sys 1072705703 21629
+1072706502 16 c sys/src/cmd/fossil/9proc.c - 664 sys sys 1072705704 14523
+1072706502 17 c sys/src/cmd/fossil/archive.c - 664 sys sys 1072705705 9558
+1072706502 18 c sys/src/cmd/fossil/cache.c - 664 sys sys 1072705706 42740
+1072706502 19 c sys/src/cmd/fossil/disk.c - 664 sys sys 1072705706 6409
+1072706502 20 c sys/src/cmd/fossil/error.c - 664 sys sys 1072705707 1413
+1072706502 21 c sys/src/cmd/fossil/error.h - 664 sys sys 1072705710 772
+1072706502 22 c sys/src/cmd/fossil/file.c - 664 sys sys 1072705707 30231
+1072706502 23 c sys/src/cmd/fossil/flfmt.c - 664 sys sys 1072705703 10799
+1072706502 24 c sys/src/cmd/fossil/fns.h - 664 sys sys 1072705709 3168
+1072706502 25 c sys/src/cmd/fossil/fossil.c - 664 sys sys 1072705702 2450
+1072706502 26 c sys/src/cmd/fossil/fs.c - 664 sys sys 1072705707 21071
+1072706502 27 c sys/src/cmd/fossil/fs.h - 664 sys sys 1072705709 1489
+1072706502 28 c sys/src/cmd/fossil/mkfile - 664 sys sys 1072705702 2077
+1072706502 29 c sys/src/cmd/fossil/source.c - 664 sys sys 1072705708 19899
+1072729906 0 c 386/bin/rio - 775 sys sys 1072729027 312035
+1072729906 1 c 386/bin/disk/exsort - 775 sys sys 1072729312 58501
+1072729906 2 c 386/bin/disk/format - 775 sys sys 1072729312 91581
+1072729906 3 c 386/bin/disk/kfscmd - 775 sys sys 1072729312 38425
+1072729906 4 c 386/bin/disk/mbr - 775 sys sys 1072729313 73154
+1072729906 5 c 386/bin/disk/mkfs - 775 sys sys 1072729313 87175
+1072729906 6 c 386/bin/mkpaqfs - 775 sys sys 1072729575 94045
+1072729906 7 c 386/bin/paqfs - 775 sys sys 1072729576 109516
+1072729906 8 c sys/man/1/rio - 664 sys sys 1072729053 14321
+1072729906 9 c sys/src/cmd/acme/look.c - 664 sys sys 1072729041 14132
+1072729906 10 c sys/src/cmd/acme/text.c - 664 sys sys 1072729041 26813
+1072729906 11 c sys/src/cmd/disk/mkext.c - 664 sys sys 1072729311 5727
+1072729906 12 c sys/src/cmd/ip/httpd/httpd.c - 664 sys sys 1072729008 10663
+1072729906 13 c sys/src/cmd/ip/ppp/compress.c - 664 sys sys 1072729513 11774
+1072729906 14 c sys/src/cmd/ip/ppp/ppp.c - 664 sys sys 1072729353 59503
+1072729906 15 c sys/src/cmd/ip/ppp/ppp.h - 664 sys sys 1072729353 8260
+1072729906 16 c sys/src/cmd/paqfs/mkpaqfs.c - 664 sys sys 1072729575 8836
+1072729906 17 c sys/src/cmd/paqfs/paqfs.c - 664 sys sys 1072729575 19566
+1072729906 18 c sys/src/cmd/paqfs/paqfs.h - 664 sys sys 1072729575 1016
+1072729906 19 c sys/src/cmd/fortune.c - 664 sys sys 1072729222 1779
+1072729906 20 c sys/src/cmd/rio/wind.c - 664 sys sys 1072729026 32762
+1072729906 21 c sys/src/cmd/usb/audio/controls.c - 664 sys sys 1072729649 13371
+1072729906 22 c sys/src/cmd/usb/mkfile - 664 sys sys 1072728986 219

+ 1 - 0
sys/include/venti.h

@@ -79,6 +79,7 @@ enum {
 	VtEntryDepthShift = 2,		/* shift for pointer depth */
 	VtEntryDepthMask = (0x7<<2),	/* mask for pointer depth */
 	VtEntryLocal = (1<<5),		/* used for local storage: should not be set for Venti blocks */
+	VtEntryNoArchive = (1<<6),	/* used for local storage: should not be set for Venti blocks */
 };
 
 struct VtRoot {

+ 6 - 0
sys/man/1/rio

@@ -365,6 +365,10 @@ the selected text; for example, typing a BS with a word selected
 places the word in the snarf buffer, removes it from the screen,
 and erases the character before the word.
 .PP
+An ACK character (control-F) or Insert character triggers file name completion
+for the preceding string (see
+.IR complete (2)).
+.PP
 Text may be moved vertically within the window.
 A scroll bar on the left of the window shows in its clear portion what fragment of the
 total output text is visible on the screen, and in its gray part what
@@ -390,6 +394,8 @@ The DEL character sends an
 note to all processes in the window's process group.
 Unlike the other characters, the DEL, VIEW, and up- and down-arrow
 keys do not affect the selected text.
+The left (right) arrow key moves the selection to one character
+before (after) the current selection.
 .PP
 Normally, written output to a window blocks when
 the text reaches the end of the screen;

+ 10 - 4
sys/man/8/fossilcons

@@ -93,7 +93,7 @@ con /srv/fscons
 .I name
 .B open
 [
-.B -APWr
+.B -APVWr
 ]
 [
 .B -c
@@ -599,8 +599,11 @@ If no
 command is issued before
 .IR open ,
 the default Venti server will be used.
-If the file system is open, the command
-redials the Venti server.
+If the file system is open,
+and was not opened with the
+.B -V
+flag,
+the command redials the Venti server.
 This can be used to reestablish broken connections.
 It is not a good idea to use the command to switch
 between Venti servers, since Fossil does not keep track
@@ -618,6 +621,9 @@ run with no authentication
 .B -P
 run with no permission checking
 .TP
+.B -V
+do not attempt to connect to a Venti server
+.TP
 .B -W
 allow wstat to make arbitrary changes to the user and group fields
 .TP
@@ -885,12 +891,12 @@ a	\fRappend only
 d	\fRdirectory
 l	\fRexclusive use
 s	\fRis the root of a snapshot
+t	\fRtemporary bit
 A	\fRMS-DOS archive bit
 G	\fRsetgid
 H	\fRMS-DOS hidden bit
 L	\fRsymbolic link
 S	\fRMS-DOS system bit
-T	\fRMS-DOS temporary bit
 U	\fRsetuid
 Y	\fRsticky
 .EE

+ 1 - 1
sys/src/9/bitsy/mkfile

@@ -123,7 +123,7 @@ paqdisk:V:
 	rm -fr armpaq
 	mkdir armpaq
 	cd armpaq
-	disk/mkfs -a /sys/lib/sysconfig/proto/armpaqproto|disk/mkext -d .
+	disk/mkfs -d . /sys/lib/sysconfig/proto/armpaqproto
 	mkpaqfs -o ../paqdisk
 	cd ..
 	echo load ramdisk

+ 2 - 2
sys/src/9/pc/etherrhine.c

@@ -25,8 +25,8 @@ typedef struct Desc Desc;
 typedef struct Ctlr Ctlr;
 
 enum {
-	Ntxd = 4,
-	Nrxd = 4,
+	Ntxd = 8,
+	Nrxd = 16,
 	Nwait = 50,
 	Ntxstats = 9,
 	Nrxstats = 8,

+ 0 - 19
sys/src/9/pc/l.s

@@ -555,25 +555,6 @@ TEXT xchgw(SB), $0
 	XCHGW	AX, (BX)
 	RET
 
-/*
- * mul64fract(uvlong* r, uvlong a, uvlong b)
- *
- * multiply uvlong a by uvlong b and return a uvlong result.
- *
- * One of the input arguments is a uvlong integer,
- * the other represents a fractional number with
- * the integer portion in the most significant word and
- * the fractional portion in the least significant word.
- *
- * Example: mul64fract(&r, 2ULL, 3ULL << 31) returns 1ULL
- *
- * The uvlong integer result is returned through r
- *
- *	ignored		r0 = lo(a0*b0)
- *	lsw of result	r1 = hi(a0*b0) +lo(a0*b1) +lo(a1*b0)
- *	msw of result	r2 = 		hi(a0*b1) +hi(a1*b0) +lo(a1*b1)
- *	ignored		r3 = hi(a1*b1)
- */
 TEXT mul64fract(SB), $0
 	MOVL	r+0(FP), CX
 	XORL	BX, BX				/* BX = 0 */

+ 3 - 3
sys/src/9/pc/main.c

@@ -77,22 +77,22 @@ main(void)
 	ioinit();
 	i8250console();
 	quotefmtinstall();
+	screeninit();
 
 	print("\nPlan 9\n");
 
 	kbdinit();
 	i8253init();
 	cpuidentify();
-	screeninit();
 	meminit();
 	confinit();
-	archinit();	/* launches other processors on an mp */
+	archinit();
 	xinit();
 	trapinit();
 	printinit();
 	cpuidprint();
 	mmuinit();
-	if(arch->intrinit)
+	if(arch->intrinit)	/* launches other processors on an mp */
 		arch->intrinit();
 	timersinit();
 	mathinit();

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

@@ -13,6 +13,8 @@ void	noted(Ureg*, ulong);
 static void debugbpt(Ureg*, void*);
 static void fault386(Ureg*, void*);
 static void doublefault(Ureg*, void*);
+static void unexpected(Ureg*, void*);
+static void _dumpstack(Ureg*);
 
 static Lock vctllock;
 static Vctl *vctl[256];
@@ -209,7 +211,7 @@ trapinit(void)
 	trapenable(VectorBPT, debugbpt, 0, "debugpt");
 	trapenable(VectorPF, fault386, 0, "fault386");
 	trapenable(Vector2F, doublefault, 0, "doublefault");
-
+	trapenable(Vector15, unexpected, 0, "unexpected");
 	nmienable();
 
 	addarchfile("irqalloc", 0444, irqallocread, nil);
@@ -400,6 +402,10 @@ trap(Ureg* ureg)
 			}
 		}
 		dumpregs(ureg);
+		if(!user){
+			ureg->sp = (ulong)&ureg->sp;
+			_dumpstack(ureg);
+		}
 		if(vno < nelem(excname))
 			panic("%s", excname[vno]);
 		panic("unknown trap/intr: %d\n", vno);
@@ -487,8 +493,11 @@ _dumpstack(Ureg *ureg)
 {
 	ulong l, v, i, estack;
 	extern ulong etext;
+	int x;
 
-	print("ktrace /kernel/path %.8lux %.8lux\n", ureg->pc, ureg->sp);
+	iprint("dumpstack\n");
+	x = 0;
+	x += print("ktrace /kernel/path %.8lux %.8lux\n", ureg->pc, ureg->sp);
 	i = 0;
 	if(up
 	&& (ulong)&l >= (ulong)up->kstack
@@ -499,23 +508,25 @@ _dumpstack(Ureg *ureg)
 		estack = (ulong)m+MACHSIZE;
 	else
 		return;
+	x += print("estackx %.8lux\n", estack);
 
 	for(l=(ulong)&l; l<estack; l+=4){
 		v = *(ulong*)l;
-		if(KTZERO < v && v < (ulong)&etext){
+		if((KTZERO < v && v < (ulong)&etext) || estack-l<256){
 			/*
 			 * we could Pick off general CALL (((uchar*)v)[-5] == 0xE8)
 			 * and CALL indirect through AX (((uchar*)v)[-2] == 0xFF && ((uchar*)v)[-2] == 0xD0),
 			 * but this is too clever and misses faulting address.
 			 */
-			print("%.8lux=%.8lux ", l, v);
+			x += print("%.8lux=%.8lux ", l, v);
 			i++;
 		}
 		if(i == 4){
 			i = 0;
-			print("\n");
+			x += print("\n");
 		}
 	}
+iprint("serialoq %d printed %d\n", qlen(serialoq), x);
 	if(i)
 		print("\n");
 }
@@ -545,6 +556,11 @@ doublefault(Ureg*, void*)
 	panic("double fault");
 }
 
+static void
+unexpected(Ureg* ureg, void*)
+{
+	print("unexpected trap %lud; ignoring\n", ureg->trap);
+}
 
 static void
 fault386(Ureg* ureg, void*)

+ 4 - 4
sys/src/9/port/chan.c

@@ -98,9 +98,9 @@ incref(Ref *r)
 {
 	long x;
 
-	lock(&r->l);
+	lock(r);
 	x = ++r->ref;
-	unlock(&r->l);
+	unlock(r);
 	return x;
 }
 
@@ -109,9 +109,9 @@ decref(Ref *r)
 {
 	long x;
 
-	lock(&r->l);
+	lock(r);
 	x = --r->ref;
-	unlock(&r->l);
+	unlock(r);
 	if(x < 0)
 		panic("deccnt pc=0x%lux", getcallerpc(&r));
 

+ 11 - 0
sys/src/9/port/devcons.c

@@ -57,6 +57,7 @@ enum
 	CMhalt,
 	CMreboot,
 	CMpanic,
+	CMcoop, /* RSC */
 };
 
 Cmdtab rebootmsg[] =
@@ -64,6 +65,7 @@ Cmdtab rebootmsg[] =
 	CMhalt,		"halt",		1,
 	CMreboot,	"reboot",	0,
 	CMpanic,	"panic",	0,
+	CMcoop,	"coop",	0, /* RSC */
 };
 
 void
@@ -94,6 +96,10 @@ prflush(void)
 			break;
 }
 
+/*
+ * Log console output so it can be retrieved via /dev/kmesg.
+ * This is good for catching boot-time messages after the fact.
+ */
 struct {
 	Lock lk;
 	char buf[16384];
@@ -1011,6 +1017,11 @@ conswrite(Chan *c, void *va, long n, vlong off)
 		case CMpanic:
 			*(ulong*)0=0;
 			panic("/dev/reboot");
+		case CMcoop: /* RSC */
+			{extern int coopsched; coopsched = !coopsched;
+			print("coopsched %d\n", coopsched);
+			}
+			break;
 		}
 		poperror();
 		free(cb);

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

@@ -573,7 +573,6 @@ testschedulability(Proc *theproc)
 	}
 	H=0;
 	G=0;
-	ticks = 0;
 	for(steps = 0; steps < Maxsteps; steps++){
 		p = qschedulability;
 		qschedulability = p->edf->testnext;

+ 2 - 2
sys/src/9/port/pgrp.c

@@ -151,10 +151,10 @@ pgrpcpy(Pgrp *to, Pgrp *from)
 	/*
 	 * Allocate mount ids in the same sequence as the parent group
 	 */
-	lock(&mountid.l);
+	lock(&mountid);
 	for(m = order; m; m = m->order)
 		m->copy->mountid = mountid.ref++;
-	unlock(&mountid.l);
+	unlock(&mountid);
 	wunlock(&from->ns);
 }
 

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

@@ -165,7 +165,6 @@ timerintr(Ureg *u, uvlong)
 	callhzclock = 0;
 	tt = &timers[m->machno];
 	now = fastticks(nil);
-	when = 0;
 	ilock(tt);
 	while(t = tt->head){
 		when = t->twhen;

+ 3 - 8
sys/src/9/port/portdat.h

@@ -57,7 +57,7 @@ typedef int    Devgen(Chan*, char*, Dirtab*, int, int, Dir*);
 
 struct Ref
 {
-	Lock	l;
+	Lock;
 	long	ref;
 };
 
@@ -153,8 +153,7 @@ struct Block
 
 struct Chan
 {
-	Lock;
-	Ref;
+	Ref;				/* the Lock in this Ref is also Chan's lock */
 	Chan*	next;			/* allocation */
 	Chan*	link;
 	vlong	offset;			/* in fd */
@@ -343,7 +342,6 @@ struct Swapalloc
 
 struct Image
 {
-	Lock;
 	Ref;
 	Chan	*c;			/* channel to text file */
 	Qid 	qid;			/* Qid for page cache coherence */
@@ -398,7 +396,6 @@ struct Physseg
 
 struct Segment
 {
-	Lock;
 	Ref;
 	QLock	lk;
 	ushort	steal;		/* Page stealer lock */
@@ -442,8 +439,7 @@ struct Pgrp
 
 struct Rgrp
 {
-	Lock;
-	Ref;
+	Ref;				/* the Ref's lock is also the Rgrp's lock */
 	Proc	*rendhash[RENDHASH];	/* Rendezvous tag hash */
 };
 
@@ -469,7 +465,6 @@ struct Evalue
 
 struct Fgrp
 {
-	Lock;
 	Ref;
 	Chan	**fd;
 	int	nfd;			/* number allocated */

+ 1 - 19
sys/src/9/ppc/l.s

@@ -1011,25 +1011,6 @@ TEXT kreboot(SB),$0
 	MOVW	R3, LR
 	RETURN
 
-/* mul64fract(uvlong*r, uvlong a, uvlong b)
- *
- * multiply uvlong a by uvlong b and return a uvlong result.
- *
- * One of the input arguments is a uvlong integer,
- * the other represents a fractional number with
- * the integer portion in the most significant word and
- * the fractional portion in the least significant word.
- *
- * Example: mul64fract(&r, 2ULL, 3ULL << 31) returns 1ULL
- *
- * The uvlong integer result is returned through r
- *
- *	ignored			r0 = lo(a0*b0)
- *	lsw of result	r1 = hi(a0*b0) +lo(a0*b1) +	lo(a1*b0)
- *	msw of result	r2 = 			hi(a0*b1) +	hi(a1*b0) +	lo(a1*b1)
- *	ignored			r3 =									hi(a1*b1)
- */
-
 TEXT	mul64fract(SB), $0
 	MOVW	a0+8(FP), R9
 	MOVW	a1+4(FP), R10
@@ -1054,3 +1035,4 @@ TEXT	mul64fract(SB), $0
 	MOVW	R12, 4(R3)
 	MOVW	R13, 0(R3)
 	RETURN
+

+ 151 - 131
sys/src/9/ppc/m8260.c

@@ -115,10 +115,138 @@ struct {
  *	CS7: E0000000 -> E0FFFFFF (16 M FPGA)
  */
 
-IMM* iomem;
+IMM* iomem = (IMM*)IOMEM;
 
 static Lock cpmlock;
 
+void
+machinit(void)
+{
+	ulong scmr;
+	int pllmf;
+	extern char* plan9inistr;
+
+	memset(m, 0, sizeof(*m));
+	m->cputype = getpvr()>>16;	/* pvr = 0x00810101 for the 8260 */
+	m->imap = (Imap*)INTMEM;
+
+	m->loopconst = 1096;
+
+	/* Make sure Ethernet is disabled (boot code may have buffers allocated anywhere in memory) */
+	iomem->fcc[0].gfmr &= ~(BIT(27)|BIT(26));
+	iomem->fcc[1].gfmr &= ~(BIT(27)|BIT(26));
+	iomem->fcc[2].gfmr &= ~(BIT(27)|BIT(26));
+
+	/* Flashed CS configuration is wrong for DSP2.  It's set to 64 bits, should be 16 */
+	iomem->bank[3].br = 0x04001001;	/* Set 16-bit port */
+
+	/*
+	 * FPGA is capable of doing 64-bit transfers.  To use these, set br to 0xe0000001.
+	 * Currently we use 32-bit transfers, because the 8260 does not easily do 64-bit operations.
+	 */
+	iomem->bank[6].br = 0xe0001801;
+	iomem->bank[6].or = 0xff000816;	/* Was 0xff000856; one wait state */
+
+/*
+ * All systems with rev. A.1 (0K26N) silicon had serious problems when doing
+ * DMA transfers with data cache enabled (usually this shows when  using
+ * one of the FCC's with some traffic on the ethernet).  Allocating FCC buffer
+ * descriptors in main memory instead of DP ram solves this problem.
+ */
+
+	/* Guess at clocks based upon the PLL configuration from the
+	 * power-on reset.
+	 */
+	scmr = iomem->scmr;
+
+	/* The EST8260 is typically run using either 33 or 66 MHz
+	 * external clock.  The configuration byte in the Flash will
+	 * tell us which is configured.  The blast appears to be slightly
+	 * overclocked at 72 MHz (if set to 66 MHz, the uart runs too fast)
+	 */
+
+	m->clkin = CLKIN;
+
+	pllmf = scmr & 0xfff;
+
+	/* This is arithmetic from the 8260 manual, section 9.4.1. */
+
+	/* Collect the bits from the scmr.
+	*/
+	m->vco_out = m->clkin * (pllmf + 1);
+	if (scmr & BIT(19))	/* plldf (division factor is 1 or 2) */
+		m->vco_out >>= 1;
+
+	m->cpmhz = m->vco_out >> 1;	/* cpm hz is half of vco_out */
+	m->brghz = m->vco_out >> (2 * ((iomem->sccr & 0x3) + 1));
+	m->bushz = m->vco_out / (((scmr & 0x00f00000) >> 20) + 1);
+
+	/* Serial init sets BRG clock....I don't know how to compute
+	 * core clock from core configuration, but I think I know the
+	 * mapping....
+	 */
+	switch(scmr >> (31-7)){
+	case 0x0a:
+		m->cpuhz = m->clkin * 2;
+		break;
+	case 0x0b:
+		m->cpuhz = (m->clkin >> 1) * 5;
+		break;
+	default:
+	case 0x0d:
+		m->cpuhz = m->clkin * 3;
+		break;
+	case 0x14:
+		m->cpuhz = (m->clkin >> 1) * 7;
+		break;
+	case 0x1c:
+		m->cpuhz = m->clkin * 4;
+		break;
+	}
+
+	m->cyclefreq = m->bushz / 4;
+
+/*	Expect:
+	intfreq	133		m->cpuhz
+	busfreq	33		m->bushz
+	cpmfreq	99		m->cpmhz
+	brgfreq	49.5		m->brghz
+	vco		198
+*/
+
+	active.machs = 1;
+	active.exiting = 0;
+
+	putmsr(getmsr() | MSR_ME);
+
+	/*
+	 * turn on data cache before instruction cache;
+	 * for some reason which I don't understand,
+	 * you can't turn on both caches at once
+	 */
+	icacheenb();
+	dcacheenb();
+
+	kfpinit();
+
+	/* Plan9.ini location in flash is FLASHMEM+PLAN9INI
+	 * if PLAN9INI == ~0, it's not stored in flash or there is no flash
+	 * if *cp == 0xff, flash memory is not initialized
+	 */
+	if (PLAN9INI == ~0 || *(plan9inistr = (char*)(FLASHMEM+PLAN9INI)) == 0xff){
+		/* No plan9.ini in flash */
+		plan9inistr =
+			"console=0\n"
+			"ether0=type=fcc port=0 ea=00601d051dd8\n"
+			"flash0=mem=0xfe000000\n"
+			"fs=135.104.9.42\n"
+			"auth=135.104.9.7\n"
+			"authdom=cs.bell-labs.com\n"
+			"sys=blast\n"
+			"ntp=135.104.9.52\n";
+	}
+}
+
 void
 fpgareset(void)
 {
@@ -146,21 +274,8 @@ hwintrinit(void)
 
 	iomem->sypcr &= ~2;	/* cause a machine check interrupt on memory timeout */
 
-	/* Flashed CS configuration is wrong for DSP2.  It's set to 64 bits, should be 16 */
-	if (iomem->bank[3].br != 0x04000001)
-		print("We got the wrong guy!\n");
-	else
-		iomem->bank[3].br = 0x04001001;	/* Set 16-bit port */
-
-	/*
-	 * FPGA is capable of doing 64-bit transfers.  To use these, set br to 0xe0000001.
-	 * Currently we use 32-bit transfers, because the 8260 does not easily do 64-bit operations.
-	 */
-	iomem->bank[6].br = 0xe0001801;
-	iomem->bank[6].or = 0xff000816;	/* Was 0xff000856; one wait state */
-
 	/* Initialize fpga reset pin */
-	iomem->port[1].pdir |= Pin4;	/* 1 is an output */
+	iomem->port[1].pdir |= Pin4;		/* 1 is an output */
 	iomem->port[1].ppar &= ~Pin4;
 	iomem->port[1].pdat |= Pin4;		/* force reset signal back to one */
 }
@@ -180,12 +295,14 @@ vectorenable(Vctl *v)
 		print("m8260enable: nonexistent vector %d\n", v->irq);
 		return -1;
 	}
+	ioplock();
 	/* Clear the interrupt before enabling */
 	iomem->sipnr_h |= hi;
 	iomem->sipnr_l |= lo;
 	/* Enable */
 	iomem->simr_h |= hi;
 	iomem->simr_l |= lo;
+	iopunlock();
 	return v->irq;
 }
 
@@ -204,8 +321,10 @@ vectordisable(Vctl *v)
 		print("m8260disable: nonexistent vector %d\n", v->irq);
 		return;
 	}
+	ioplock();
 	iomem->simr_h &= ~hi;
 	iomem->simr_l &= ~lo;
+	iopunlock();
 }
 
 int
@@ -218,8 +337,10 @@ void
 intend(int vno)
 {
 	/* Clear interrupt */
+	ioplock();
 	iomem->sipnr_h |= vec2mask[vno].hi;
 	iomem->sipnr_l |= vec2mask[vno].lo;
+	iopunlock();
 }
 
 int
@@ -495,122 +616,6 @@ ioringinit(Ring* r, int nrdre, int ntdre, int bufsize)
 	return 0;
 }
 
-void
-machinit(void)
-{
-	ulong scmr;
-	int pllmf;
-	extern char* plan9inistr;
-
-	memset(m, 0, sizeof(*m));
-	m->cputype = getpvr()>>16;	/* pvr = 0x00810101 for the 8260 */
-	m->imap = (Imap*)INTMEM;
-	iomem = (IMM*)IOMEM;
-	m->flash = (uchar*)FLASHMEM;
-
-	m->loopconst = 1096;
-
-	/* Make sure Ethernet is disabled (boot code may have buffers allocated anywhere in memory) */
-	iomem->fcc[0].gfmr &= ~(BIT(27)|BIT(26));
-	iomem->fcc[1].gfmr &= ~(BIT(27)|BIT(26));
-	iomem->fcc[2].gfmr &= ~(BIT(27)|BIT(26));
-/*
- * All systems with rev. A.1 (0K26N) silicon had serious problems when doing
- * DMA transfers with data cache enabled (usually this shows when  using
- * one of the FCC's with some traffic on the ethernet).  Allocating FCC buffer
- * descriptors in main memory instead of DP ram solves this problem.
- */
-
-	/* Guess at clocks based upon the PLL configuration from the
-	 * power-on reset.
-	 */
-	scmr = iomem->scmr;
-
-	/* The EST8260 is typically run using either 33 or 66 MHz
-	 * external clock.  The configuration byte in the Flash will
-	 * tell us which is configured.  The blast appears to be slightly
-	 * overclocked at 72 MHz (if set to 66 MHz, the uart runs too fast)
-	 */
-
-	m->clkin = CLKIN;
-
-	pllmf = scmr & 0xfff;
-
-	/* This is arithmetic from the 8260 manual, section 9.4.1. */
-
-	/* Collect the bits from the scmr.
-	*/
-	m->vco_out = m->clkin * (pllmf + 1);
-	if (scmr & BIT(19))	/* plldf (division factor is 1 or 2) */
-		m->vco_out >>= 1;
-
-	m->cpmhz = m->vco_out >> 1;	/* cpm hz is half of vco_out */
-	m->brghz = m->vco_out >> (2 * ((iomem->sccr & 0x3) + 1));
-	m->bushz = m->vco_out / (((scmr & 0x00f00000) >> 20) + 1);
-
-	/* Serial init sets BRG clock....I don't know how to compute
-	 * core clock from core configuration, but I think I know the
-	 * mapping....
-	 */
-	switch(scmr >> (31-7)){
-	case 0x0a:
-		m->cpuhz = m->clkin * 2;
-		break;
-	case 0x0b:
-		m->cpuhz = (m->clkin >> 1) * 5;
-		break;
-	default:
-	case 0x0d:
-		m->cpuhz = m->clkin * 3;
-		break;
-	case 0x14:
-		m->cpuhz = (m->clkin >> 1) * 7;
-		break;
-	case 0x1c:
-		m->cpuhz = m->clkin * 4;
-	}
-
-/*	Expect:
-	intfreq	133		m->cpuhz
-	busfreq	33		m->bushz
-	cpmfreq	99		m->cpmhz
-	brgfreq	49.5		m->brghz
-	vco		198
-*/
-
-	active.machs = 1;
-	active.exiting = 0;
-
-	putmsr(getmsr() | MSR_ME);
-
-	/*
-	 * turn on data cache before instruction cache;
-	 * for some reason which I don't understand,
-	 * you can't turn on both caches at once
-	 */
-	icacheenb();
-	dcacheenb();
-
-	kfpinit();
-
-	/* Plan9.ini location in flash is FLASHMEM+PLAN9INI
-	 * if PLAN9INI == ~0, it's not stored in flash or there is no flash
-	 * if *cp == 0xff, flash memory is not initialized
-	 */
-	if (PLAN9INI == ~0 || *(plan9inistr = (char*)(FLASHMEM+PLAN9INI)) == 0xff){
-		/* No plan9.ini in flash */
-		plan9inistr =
-			"console=0\n"
-			"ether0=type=fcc port=0 ea=00601d3d8fc2\n"
-			"flash0=mem=0xfe000000\n"
-			"fs=135.104.9.42\n"
-			"auth=135.104.9.7\n"
-			"authdom=cs.bell-labs.com\n"
-			"sys=pe0\n"
-			"ntp=135.104.9.52\n";
-	}
-}
-
 void
 trapinit(void)
 {
@@ -636,3 +641,18 @@ trapinit(void)
 
 	putmsr(getmsr() & ~MSR_IP);
 }
+
+void
+reboot(void*, void*, ulong)
+{
+	ulong *p;
+	int x;
+
+	p = (ulong*)0x90000000;
+	x = splhi();
+	iomem->sypcr |= 0xc0;
+	print("iomem->sypcr = 0x%lux\n", iomem->sypcr);
+	*p = 0;
+	print("still alive\n");
+	splx(x);
+}

+ 49 - 44
sys/src/9/ppc/main.c

@@ -6,6 +6,7 @@
 #include	"io.h"
 #include	"init.h"
 #include	"pool.h"
+#include	"tos.h"
 
 #define	MAXCONF		64
 
@@ -26,7 +27,37 @@ Lock		testlock;
 
 static void	plan9iniinit(void);
 
-void (*_reboot)(void);
+char *
+cpuid(void)
+{
+	char *id;
+
+	id = "unknown PowerPC";
+	switch(m->cputype) {
+	case 8:
+		id = "PowerPC 750";
+		break;
+	case 9:
+		id = "PowerPC 604e";
+		break;
+	case 0x81:
+		id = "PowerPC 8260";
+		break;
+	case 0x8081:
+		id = "PowerPC 826xA";
+		break;
+	default:
+		break;
+	}
+	return id;
+}
+
+void
+cpuidprint(void)
+{
+	print("cpu0: %s, rev 0x%lux, cpu hz %lld, bus hz %ld\n", 
+		cpuid(), getpvr()&0xffff, m->cpuhz, m->bushz);
+}
 
 void
 main(void)
@@ -61,31 +92,6 @@ main(void)
 	schedinit();
 }
 
-void
-cpuidprint(void)
-{
-	char *id;
-
-	id = "unknown PowerPC";
-	switch(m->cputype) {
-	case 8:
-		id = "PowerPC 750";
-		break;
-	case 9:
-		id = "PowerPC 604e";
-		break;
-	case 0x81:
-		id = "PowerPC 8260";
-		break;
-	case 0x8081:
-		id = "PowerPC 826xA";
-		break;
-	default:
-		break;
-	}
-	print("cpu0: %s, rev 0x%lux\n", id, getpvr()&0xffff);
-}
-
 char*
 getconf(char *name)
 {
@@ -104,20 +110,11 @@ plan9iniinit(void)
 	int c;
 	char *cp, line[MAXCONF], *p, *q;
 
-	_reboot = (void (*)(void))0xff400000;
-
 	/*
 	 *  parse configuration args from dos file plan9.ini
 	 */
 
-	/* Plan9.ini location in flash is FLASHMEM+PLAN9INI
-	 * if PLAN9INI == ~0, it's not stored in flash or there is no flash
-	 * if *cp == 0xff, flash memory is not initialized
-	 */
-	if (PLAN9INI == ~0 || *(cp = (char*)(FLASHMEM+PLAN9INI)) == 0xff){
-		/* No plan9.ini in flash */
-		cp = plan9inistr;
-	}
+	cp = plan9inistr;
 	for(i = 0; i < MAXCONF; i++){
 		/*
 		 * Strip out '\r', change '\t' -> ' ', test for 0xff which is end of file
@@ -148,13 +145,6 @@ plan9iniinit(void)
 	}
 }
 
-/* still to do */
-void
-reboot(void*, void*, ulong)
-{
-	_reboot();
-}
-
 void
 init0(void)
 {
@@ -194,7 +184,7 @@ init0(void)
 	}
 	kproc("alarm", alarmkproc, 0);
 	kproc("mmusweep", mmusweep, 0);
-	touser((void*)(USTKTOP-8));
+	touser((void*)(USTKTOP-sizeof(Tos)));
 }
 
 void
@@ -296,12 +286,27 @@ procsetup(Proc *p)
 	p->fpstate = FPinit;
 }
 
+void
+procrestore(Proc *p)
+{
+	uvlong t;
+
+	if(p->kp)
+		return;
+	cycles(&t);
+	p->pcycles -= t;
+}
+
 /*
  *  Save the mach dependent part of the process state.
  */
 void
 procsave(Proc *p)
 {
+	uvlong t;
+
+	cycles(&t);
+	p->pcycles += t;
 	if(p->fpstate == FPactive){
 		if(p->state != Moribund)
 			fpsave(&up->fpsave);

+ 4 - 5
sys/src/9/ppc/mem.h

@@ -4,8 +4,7 @@
 
 #ifdef ucuconf
 #include "ucu.h"
-#endif
-#ifdef blastconf
+#else
 #include "blast.h"
 #endif
 
@@ -38,7 +37,7 @@
 /*
  * Time
  */
-#define	HZ		100			/* clock frequency */
+#define	HZ		1000			/* clock frequency */
 #define	TK2SEC(t)	((t)/HZ)		/* ticks to seconds */
 
 /*
@@ -50,6 +49,8 @@
 #define SDR1	25
 #define SRR0	26		/* Saved Registers (exception) */
 #define SRR1	27
+#define TBRL	268
+#define TBRU	269		/* Time base Upper/Lower (Reading) */
 #define SPRG0	272		/* Supervisor Private Registers */
 #define SPRG1	273
 #define SPRG2	274
@@ -60,8 +61,6 @@
 #define SPRG7	279
 #define ASR	280		/* Address Space Register */
 #define EAR	282		/* External Access Register (optional) */
-#define TBRU	269		/* Time base Upper/Lower (Reading) */
-#define TBRL	268
 #define TBWU	284		/* Time base Upper/Lower (Writing) */
 #define TBWL	285
 #define PVR	287		/* Processor Version */

+ 15 - 13
sys/src/9/ppc/msaturn.c

@@ -49,15 +49,8 @@ void
 hwintrinit(void)
 {
 	int i;
-	ushort iar;
 
 	*(ulong*)Ier=0;
-if(0){
-	iar=*(ushort*)Iar;		// reset the stack
-	if(iar != 0xf)
-		panic("saturnintinit: iar not at 0xf (-> %d)\n", iar);
-	intack();
-}
 
 	for(i=0; i<nelem(intprio)/2; i++)
 		((uchar*)Ipri)[i] = (intprio[2*i]<<4)|intprio[2*i+1];
@@ -117,6 +110,7 @@ machinit(void)
 	int rrate;
 	ulong hid;
 	extern char* plan9inistr;
+	ulong l2cr;
 
 	memset(m, 0, sizeof(*m));
 	m->cputype = getpvr()>>16;
@@ -140,17 +134,20 @@ machinit(void)
 		break;
 	}
 
+	if(getpll() == 0x80000000)
+		m->cpuhz = 300000000;
+	else
+		m->cpuhz = 200000000;		/* 750FX? */
+	m->cyclefreq = m->bushz / 4;
+
 	active.machs = 1;
 	active.exiting = 0;
 
 	putmsr(getmsr() | MSR_ME);
 
-	/* disable the l2 cache because it slows down the processor.
-	     the only way (that i know) to get a consistent memory view
-	     with l2 enabled is by enabling write-through operations in 
-	     the bats and ptes.  disabling write-through and only using the
-	     l1 caches improves performance */
-	l2disable();		
+	dcflush((void*)KZERO, 0x2000000);
+	l2cr = getl2cr();
+	putl2cr(l2cr|BIT(10));
 
 	kfpinit();
 
@@ -186,3 +183,8 @@ trapinit(void)
 
 	putmsr(getmsr() & ~MSR_IP);
 }
+
+void
+reboot(void*, void*, ulong)
+{
+}

+ 3 - 2
sys/src/9/ppc/saturntimer.c

@@ -49,6 +49,7 @@ timerinit(void)
 	*(ulong*)Timer0_cnt = m->bushz / HZ;
 	*(ulong*)Timer1_load = m->bushz;
 	*(ulong*)Timer1_cnt = m->bushz;
+
 	intrenable(Vectimer0, saturntimerintr, nil, "timer");
 
 	timer_ctl = T0_cen|T0_ie|T1_cen;
@@ -81,8 +82,8 @@ timerset(uvlong next)
 
 	now = fastticks(nil);
 	offset = next - now;
-	if((long)offset<25000)
-		offset = 25000;
+	if((long)offset < 10000)
+		offset = 10000;
 	else if(offset > m->bushz)
 		offset = m->bushz;
 

+ 43 - 29
sys/src/9/ppc/trap.c

@@ -5,6 +5,7 @@
 #include	"fns.h"
 #include	"ureg.h"
 #include	"../port/error.h"
+#include	"tos.h"
 
 static Lock vctllock;
 static Vctl *vctl[256];
@@ -133,6 +134,20 @@ char *regname[]={
 	"DAR",	"DSISR",
 };
 
+void
+kexit(Ureg*)
+{
+	uvlong t;
+	Tos *tos;
+
+	/* precise time accounting, kernel exit */
+	tos = (Tos*)(USTKTOP-sizeof(Tos));
+	cycles(&t);
+	tos->kcycles += t - up->kentry;
+	tos->pcycles = up->pcycles;
+	tos->pid = up->pid;
+}
+
 void
 trap(Ureg *ureg)
 {
@@ -141,9 +156,10 @@ trap(Ureg *ureg)
 
 	ecode = (ureg->cause >> 8) & 0xff;
 	user = (ureg->srr1 & MSR_PR) != 0;
-	if(user)
+	if(user){
+		cycles(&up->kentry);
 		up->dbgreg = ureg;
-
+	}
 	if(ureg->status & MSR_RI == 0)
 		print("double fault?: ecode = %d\n", ecode);
 
@@ -161,12 +177,8 @@ trap(Ureg *ureg)
 			dumpregs(ureg);
 			panic("kernel fault");
 		}
-		if (up->mmureg)
-			panic("recursing");
 		up->mmureg = ureg;
-		up->mmuinstr = 0;
 		faultpower(ureg, ureg->dar, (ureg->dsisr & BIT(6)) == 0);
-		up->mmureg = nil;
 		break;
 	case CISI:
 		m->pfault++;
@@ -174,54 +186,41 @@ trap(Ureg *ureg)
 			dumpregs(ureg);
 			panic("kernel fault");
 		}
-		if (up->mmureg)
-			panic("recursing");
 		up->mmureg = ureg;
-		up->mmuinstr = 0;
 		faultpower(ureg, ureg->pc, 1);
-		up->mmureg = nil;
 		break;
 	case CIMISS:	/* instruction miss */
 		if (up == nil){
 			dumpregs(ureg);
 			panic("kernel fault");
 		}
-		if (up->mmureg)
-			panic("recursing");
 		up->mmureg = ureg;
-		up->mmuinstr = 0;
 		faultpower(ureg, ureg->imiss, 1);
-		up->mmureg = nil;
 		break;
 	case CLMISS:	/* data load miss */
 		if (up == nil){
 			dumpregs(ureg);
 			panic("kernel fault");
 		}
-		if (up->mmureg)
-			panic("recursing");
 		up->mmureg = ureg;
-		up->mmuinstr = 0;
 		faultpower(ureg, ureg->dmiss, 1);
-		up->mmureg = nil;
 		break;
 	case CSMISS:	/* data store miss */
 		if (up == nil){
 			dumpregs(ureg);
 			panic("kernel fault");
 		}
-		if (up->mmureg)
-			panic("recursing");
 		up->mmureg = ureg;
-		up->mmuinstr = 0;
 		faultpower(ureg, ureg->dmiss, 0);
-		up->mmureg = nil;
 		break;
 
 	case CSYSCALL:
 		if(!user)
 			panic("syscall in kernel: srr1 0x%4.4luX\n", ureg->srr1);
 		syscall(ureg);
+		if (up->delaysched)
+			sched();
+		kexit(ureg);
 		return;		/* syscall() calls notify itself, don't do it again */
 
 	case CFPU:
@@ -296,6 +295,9 @@ trap(Ureg *ureg)
 		notify(ureg);
 		if(up->fpstate != FPactive)
 			ureg->srr1 &= ~MSR_FP;
+		if (up->delaysched)
+			sched();
+		kexit(ureg);
 	}
 }
 
@@ -373,21 +375,35 @@ setmvec(int v, void (*r)(void), void (*t)(void))
 		vp[n] = (18<<26)|(pa&0x3FFFFFC)|3;	/* bla */
 }
 
+int intrstack[5];
+uvlong intrtime[5];
+vlong lastoffset;
+int inintr;
+
 void
 intr(Ureg *ureg)
 {
 	int vno;
 	Vctl *ctl, *v;
-	static int inintr;
 
-	if (inintr > 4)
+#ifdef notdef
+	if (inintr > 4){
+		int i;
+		for(i = 0; i != inintr; i++)
+			iprint("intr[%d] %d %.lld\n", i, intrstack[i], intrtime[i]);
+		iprint("current vector %d, lastoffset %lld, %.lld\n", intvec(), lastoffset,
+				fastticks(nil));
 		panic("recursing");
+	}
 	inintr++;
+#endif
 	vno = intvec();
 
+//	intrstack[inintr - 1] = vno;
+
 	if(vno > nelem(vctl) || (ctl = vctl[vno]) == 0) {
 		iprint("spurious intr %d\n", vno);
-		inintr--;
+//		inintr--;
 		return;
 	}
 
@@ -397,9 +413,7 @@ intr(Ureg *ureg)
 	}
 
 	intend(vno);	/* reenable the interrupt */
-
-	inintr--;
-
+//	inintr--;
 	preempted();
 }
 
@@ -553,7 +567,7 @@ execregs(ulong entry, ulong ssize, ulong nargs)
 	ureg->pc = entry;
 	ureg->srr1 &= ~MSR_FP;		/* disable floating point */
 	up->fpstate = FPinit;
-	return USTKTOP-BY2WD;		/* address of user-level clock */
+	return USTKTOP-sizeof(Tos);		/* address of kernel/user shared data */
 }
 
 void

+ 1 - 0
sys/src/cmd/acme/look.c

@@ -319,6 +319,7 @@ isfilec(Rune r)
 	return FALSE;
 }
 
+/* Runestr wrapper for cleanname */
 Runestr
 cleanrname(Runestr rs)
 {

+ 151 - 8
sys/src/cmd/acme/text.c

@@ -8,6 +8,7 @@
 #include <frame.h>
 #include <fcall.h>
 #include <plumb.h>
+#include <complete.h>
 #include "dat.h"
 #include "fns.h"
 
@@ -524,28 +525,160 @@ textbswidth(Text *t, Rune c)
 	return t->q0-q;
 }
 
+int
+textfilewidth(Text *t, uint q0, int oneelement)
+{
+	uint q;
+	Rune r;
+
+	q = q0;
+	while(q > 0){
+		r = textreadc(t, q-1);
+		if(r <= ' ')
+			break;
+		if(oneelement && r=='/')
+			break;
+		--q;
+	}
+	return q0-q;
+}
+
+Rune*
+textcomplete(Text *t)
+{
+	int i, nstr, npath;
+	uint q;
+	Rune tmp[200];
+	Rune *str, *path;
+	Rune *rp;
+	Completion *c;
+	char *s, *dirs;
+	Runestr dir;
+
+	/* control-f: filename completion; works back to white space or / */
+	if(t->q0<t->file->nc && textreadc(t, t->q0)>' ')	/* must be at end of word */
+		return nil;
+	nstr = textfilewidth(t, t->q0, TRUE);
+	str = runemalloc(nstr);
+	npath = textfilewidth(t, t->q0-nstr, FALSE);
+	path = runemalloc(npath);
+
+	c = nil;
+	rp = nil;
+	dirs = nil;
+
+	q = t->q0-nstr;
+	for(i=0; i<nstr; i++)
+		str[i] = textreadc(t, q++);
+	q = t->q0-nstr-npath;
+	for(i=0; i<npath; i++)
+		path[i] = textreadc(t, q++);
+	/* is path rooted? if not, we need to make it relative to window path */
+	if(npath>0 && path[0]=='/')
+		dir = (Runestr){path, npath};
+	else{
+		dir = dirname(t, nil, 0);
+		if(dir.nr + 1 + npath > nelem(tmp)){
+			free(dir.r);
+			goto Return;
+		}
+		if(dir.nr == 0){
+			dir.nr = 1;
+			dir.r = runestrdup(L".");
+		}
+		runemove(tmp, dir.r, dir.nr);
+		tmp[dir.nr] = '/';
+		runemove(tmp+dir.nr+1, path, npath);
+		free(dir.r);
+		dir.r = tmp;
+		dir.nr += 1+npath;
+		dir = cleanrname(dir);
+	}
+
+	s = smprint("%.*S", nstr, str);
+	dirs = smprint("%.*S", dir.nr, dir.r);
+	c = complete(dirs, s);
+	free(s);
+	if(c == nil){
+		warning(nil, "error attempting completion: %r\n");
+		goto Return;
+	}
+
+	if(!c->advance){
+		warning(nil, "%.*S%s%.*S*\n",
+			dir.nr, dir.r,
+			dir.nr>0 && dir.r[dir.nr-1]!='/' ? "/" : "",
+			nstr, str);
+		for(i=0; i<c->nfile; i++)
+			warning(nil, " %s\n", c->filename[i]);
+	}
+
+	if(c->advance)
+		rp = runesmprint("%s", c->string);
+	else
+		rp = nil;
+  Return:
+	freecompletion(c);
+	free(dirs);
+	free(str);
+	free(path);
+	return rp;
+}
+
 void
 texttype(Text *t, Rune r)
 {
 	uint q0, q1;
 	int nnb, nb, n, i;
+	int nr;
+	Rune *rp;
 	Text *u;
 
 	if(t->what!=Body && r=='\n')
 		return;
+	nr = 1;
+	rp = &r;
 	switch(r){
-	case Kdown:
 	case Kleft:
+		if(t->q0 > 0){
+			textcommit(t, TRUE);
+			textshow(t, t->q0-1, t->q0-1, TRUE);
+		}
+		return;
 	case Kright:
-		n = t->maxlines/2;
+		if(t->q1 < t->file->nc){
+			textcommit(t, TRUE);
+			textshow(t, t->q1+1, t->q1+1, TRUE);
+		}
+		return;
+	case Kdown:
+		n = t->maxlines/3;
+		goto case_Down;
+	case Kpgdown:
+		n = 2*t->maxlines/3;
+	case_Down:
 		q0 = t->org+frcharofpt(t, Pt(t->r.min.x, t->r.min.y+n*t->font->height));
 		textsetorigin(t, q0, FALSE);
 		return;
 	case Kup:
-		n = t->maxlines/2;
+		n = t->maxlines/3;
+		goto case_Up;
+	case Kpgup:
+		n = 2*t->maxlines/3;
+	case_Up:
 		q0 = textbacknl(t, t->org, n);
 		textsetorigin(t, q0, FALSE);
 		return;
+	case Khome:
+		textshow(t, 0, 0, FALSE);
+		return;
+	case Kend:
+		if(t->w)
+			wincommit(t->w, t);
+		else
+			textcommit(t, TRUE);
+		textshow(t, t->file->nc, t->file->nc, FALSE);
+		return;
 	}
 	if(t->what == Body){
 		seq++;
@@ -559,6 +692,13 @@ texttype(Text *t, Rune r)
 	}
 	textshow(t, t->q0, t->q0, 1);
 	switch(r){
+	case 0x06:
+	case Kins:
+		rp = textcomplete(t);
+		if(rp == nil)
+			return;
+		nr = runestrlen(rp);
+		break;	/* fall through to normal insertion case */
 	case 0x1B:
 		if(t->eq0 != ~0)
 			textsetselect(t, t->eq0, t->q0);
@@ -621,16 +761,19 @@ texttype(Text *t, Rune r)
 			u->cq0 = t->q0;
 		else if(t->q0 != u->cq0+u->ncache)
 			error("text.type cq1");
-		textinsert(u, t->q0, &r, 1, FALSE);
+		textinsert(u, t->q0, rp, nr, FALSE);
 		if(u != t)
 			textsetselect(u, u->q0, u->q1);
-		if(u->ncache == u->ncachealloc){
-			u->ncachealloc += 10;
+		if(u->ncache+nr > u->ncachealloc){
+			u->ncachealloc += 10 + nr;
 			u->cache = runerealloc(u->cache, u->ncachealloc);
 		}
-		u->cache[u->ncache++] = r;
+		runemove(u->cache+u->ncache, rp, nr);
+		u->ncache += nr;
 	}
-	textsetselect(t, t->q0+1, t->q0+1);
+	if(rp != &r)
+		free(rp);
+	textsetselect(t, t->q0+nr, t->q0+nr);
 	if(r=='\n' && t->w!=nil)
 		wincommit(t->w, t);
 }

+ 1 - 0
sys/src/cmd/disk/mkext.c

@@ -161,6 +161,7 @@ mkdir(char *name, ulong mode, ulong mtime, char *uid, char *gid)
 			warn("can't make directory %q, mode %luo: %s", name, mode, olderr);
 			return;
 		}
+		free(d);
 	}
 	close(fd);
 

+ 6 - 1
sys/src/cmd/fortune.c

@@ -29,13 +29,17 @@ main(int argc, char *argv[])
 	if(argc == 1){
 		ix = open(index, OREAD);
 		if(ix>=0){
-			oldindex = 1;
 			ixbuf = dirfstat(ix);
 			fbuf = dirfstat(Bfildes(f));
 			if(ixbuf == nil || fbuf == nil){
 				print("Misfortune?\n");
 				exits("misfortune");
 			}
+			if(ixbuf->length == 0){
+				/* someone else is rewriting the index */
+				goto NoIndex;
+			}
+			oldindex = 1;
 			if(fbuf->mtime > ixbuf->mtime){
 				nix = create(index, OWRITE, 0666);
 				if(nix >= 0){
@@ -62,6 +66,7 @@ main(int argc, char *argv[])
 		}else
 			strcpy(choice, "Misfortune!");
 	}else{
+NoIndex:
 		Binit(&g, ix, 1);
 		srand(truerand());
 		for(i=1;;i++){

+ 4 - 0
sys/src/cmd/fossil/9dir.c

@@ -59,6 +59,10 @@ dirDe2M(DirEntry* de, uchar* p, int np)
 		dir.qid.type |= QTMOUNT;	/* just for debugging */
 		dir.mode |= DMMOUNT;
 	}
+	if(de->mode & ModeTemporary){
+		dir.qid.type |= QTTMP;
+		dir.mode |= DMTMP;
+	}
 
 	dir.atime = de->atime;
 	dir.mtime = de->mtime;

+ 7 - 3
sys/src/cmd/fossil/9p.c

@@ -205,7 +205,7 @@ rTwstat(Msg* m)
 		 */
 		if(dir.mode == ~0)
 			dir.mode = (dir.qid.type<<24)|(de.mode & 0777);
-		if(dir.mode & ~(DMDIR|DMAPPEND|DMEXCL|0777)){
+		if(dir.mode & ~(DMDIR|DMAPPEND|DMEXCL|DMTMP|0777)){
 			vtSetError("wstat -- unknown bits in qid.type/mode");
 			goto error;
 		}
@@ -220,14 +220,16 @@ rTwstat(Msg* m)
 			mode |= ModeAppend;
 		if(dir.mode & DMDIR)
 			mode |= ModeDir;
+		if(dir.mode & DMTMP)
+			mode |= ModeTemporary;
 
 		if((de.mode^mode) & ModeDir){
 			vtSetError("wstat -- attempt to change directory bit");
 			goto error;
 		}
 
-		if((de.mode & (ModeAppend|ModeExclusive|0777)) != mode){
-			de.mode &= ~(ModeAppend|ModeExclusive|0777);
+		if((de.mode & (ModeAppend|ModeExclusive|ModeTemporary|0777)) != mode){
+			de.mode &= ~(ModeAppend|ModeExclusive|ModeTemporary|0777);
 			de.mode |= mode;
 			op = 1;
 		}
@@ -630,6 +632,8 @@ rTcreate(Msg* m)
 		mode |= ModeAppend;
 	if(m->t.perm & DMEXCL)
 		mode |= ModeExclusive;
+	if(m->t.perm & DMTMP)
+		mode |= ModeTemporary;
 
 	if((file = fileCreate(fid->file, m->t.name, mode, fid->uid)) == nil){
 		fidPut(fid);

+ 2 - 2
sys/src/cmd/fossil/9proc.c

@@ -6,8 +6,8 @@
 
 enum {
 	NConInit	= 128,
-	NMsgInit	= 20,
-	NMsgProcInit	= 4,
+	NMsgInit	= 384,
+	NMsgProcInit	= 64,
 	NMsizeInit	= 8192+IOHDRSZ,
 };
 

+ 14 - 3
sys/src/cmd/fossil/archive.c

@@ -210,8 +210,9 @@ archWalk(Param *p, u32int addr, uchar type, u32int tag)
 			if(e){
 				if(!(e->flags&VtEntryActive))
 					continue;
-				if(e->snap != 0 && e->archive == 0){
-				//	fprint(2, "snap; faking %#ux\n", b->addr);
+				if((e->snap && !e->archive)
+				|| (e->flags&VtEntryNoArchive)){
+					if(0) fprint(2, "snap; faking %#ux\n", b->addr);
 					if(data == b->data){
 						data = copyBlock(b, p->blockSize);
 						if(data == nil){
@@ -254,8 +255,18 @@ archWalk(Param *p, u32int addr, uchar type, u32int tag)
 				ret = ArchFailure;
 				goto Out;
 			case ArchFaked:
-if(0) fprint(2, "faked %#ux, faking %#ux (%V)\n", addr, b->addr, p->score);
+				/*
+				 * When we're writing the entry for an archive directory
+				 * (like /archive/2003/1215) then even if we've faked
+				 * any data, record the score unconditionally.
+				 * This way, we will always record the Venti score here.
+				 * Otherwise, temporary data or corrupted file system
+				 * would cause us to keep holding onto the on-disk
+				 * copy of the archive.
+				 */
+				if(e==nil || !e->archive)
 				if(data == b->data){
+if(0) fprint(2, "faked %#ux, faking %#ux (%V)\n", addr, b->addr, p->score);
 					data = copyBlock(b, p->blockSize);
 					if(data == nil){
 						ret = ArchFailure;

+ 25 - 57
sys/src/cmd/fossil/cache.c

@@ -52,6 +52,7 @@ struct Cache
 
 	VtRendez *flush;
 	VtRendez *flushwait;
+	VtRendez *heapwait;
 	BAddr *baddr;
 	int bw, br, be;
 	int nflush;
@@ -206,6 +207,7 @@ bwatchSetBlockSize(c->size);
 	c->unlink = vtRendezAlloc(c->lk);
 	c->flush = vtRendezAlloc(c->lk);
 	c->flushwait = vtRendezAlloc(c->lk);
+	c->heapwait = vtRendezAlloc(c->lk);
 	c->sync = periodicAlloc(cacheSync, c, 30*1000);
 
 	if(mode == OReadWrite){
@@ -273,9 +275,9 @@ cacheDump(Cache *c)
 
 	for(i = 0; i < c->nblocks; i++){
 		b = &c->blocks[i];
-		fprint(2, "p=%d a=%ud %V t=%d ref=%d state=%s io=%s\n",
-			b->part, b->addr, b->score, b->l.type, b->ref,
-			bsStr(b->l.state), bioStr(b->iostate));
+		fprint(2, "%d. p=%d a=%ud %V t=%d ref=%d state=%s io=%s pc=0x%lux\n",
+			i, b->part, b->addr, b->score, b->l.type, b->ref,
+			bsStr(b->l.state), bioStr(b->iostate), b->pc);
 	}
 }
 
@@ -343,8 +345,15 @@ cacheBumpBlock(Cache *c)
 	 * locate the block with the oldest second to last use.
 	 * remove it from the heap, and fix up the heap.
 	 */
-	if(c->nheap == 0)
-		vtFatal("cacheBumpBlock: no free blocks in cache");
+	if(c->nheap == 0){
+		while(c->nheap == 0){
+			fprint(2, "entire cache is busy, %d dirty -- waking flush thread\n", c->ndirty);
+			vtWakeup(c->flush);
+			vtSleep(c->heapwait);
+		}
+		fprint(2, "cache is okay again\n");
+	}
+
 	b = c->heap[0];
 	heapDel(b);
 
@@ -578,9 +587,8 @@ cacheLocalData(Cache *c, u32int addr, int type, u32int tag, int mode, u32int epo
 	if(b == nil)
 		return nil;
 	if(b->l.type != type || b->l.tag != tag){
-		fprint(2, "cacheLocalData: addr=%d type got %d exp %d: tag got %x exp %x\n",
+		fprint(2, "cacheLocalData: addr=%d type got %d exp %d: tag got %ux exp %ux\n",
 			addr, b->l.type, type, b->l.tag, tag);
-abort();
 		vtSetError(ELabelMismatch);
 		blockPut(b);
 		return nil;
@@ -1146,42 +1154,6 @@ blistFree(Cache *c, BList *bl)
 cacheFlush(c, 0);
 }
 
-/*
- * Flush b or one of the blocks it depends on.
- */
-void
-blockFlush(Block *b)
-{
-	int first;
-	BList *p, **pp;
-	Block *bb;
-	Cache *c;
-
-//fprint(2, "blockFlush %p\n", b);
-
-	c = b->c;
-
-	first = 1;
-	pp = &b->prior;
-	for(p=*pp; p; p=*pp){
-		bb = cacheLocalLookup(c, p->part, p->addr, p->vers);
-		if(bb == nil){
-			*pp = p->next;
-			blistFree(c, p);
-			continue;
-		}
-		if(!first)
-			blockPut(b);
-		first = 0;
-		b = bb;
-		pp = &b->prior;
-	}
-
-	diskWriteAndWait(c->disk, b);
-	if(!first)
-		blockPut(b);
-}
-
 /*
  * Record that bb must be written out before b.
  * If index is given, we're about to overwrite the score/e
@@ -1242,19 +1214,17 @@ if(0)fprint(2, "%d:%x:%d depends on %d:%x:%d\n", b->part, b->addr, b->l.type, bb
 
 /*
  * Mark an in-memory block as dirty.  If there are too many
- * dirty blocks, start writing some out to disk.  If there are way
- * too many dirty blocks, write this one out too.
- *
- * Note that since we might call blockFlush, which walks
- * the prior list, we can't call blockDirty while holding a lock
- * on any of our priors.  This can be tested by recompiling
- * with flush always set to 1 below.
+ * dirty blocks, start writing some out to disk. 
+ * 
+ * If there were way too many dirty blocks, we used to
+ * try to do some flushing ourselves, but it's just too dangerous -- 
+ * it implies that the callers cannot have any of our priors locked,
+ * but this is hard to avoid in some cases.
  */
 int
 blockDirty(Block *b)
 {
 	Cache *c;
-	int flush;
 
 	c = b->c;
 
@@ -1269,12 +1239,8 @@ blockDirty(Block *b)
 	c->ndirty++;
 	if(c->ndirty > (c->maxdirty>>1))
 		vtWakeup(c->flush);
-	flush = c->ndirty > c->maxdirty;
 	vtUnlock(c->lk);
 
-	if(flush)
-		blockFlush(b);
-
 	return 1;
 }
 
@@ -1843,6 +1809,7 @@ heapIns(Block *b)
 {
 	assert(b->heap == BadHeap);
 	upHeap(b->c->nheap++, b);
+	vtWakeup(b->c->heapwait);
 }
 
 /*
@@ -2026,9 +1993,10 @@ cacheFlushBlock(Cache *c)
 			continue;
 
 		/* Failed to acquire lock; sleep if happens a lot. */
-		if(lockfail && ++nfail > 100)
+		if(lockfail && ++nfail > 100){
 			sleep(500);
-
+			nfail = 0;
+		}
 		/* Requeue block. */
 		if(c->bw < c->be)
 			c->baddr[c->bw++] = *p;

+ 7 - 1
sys/src/cmd/fossil/disk.c

@@ -270,6 +270,12 @@ diskSize(Disk *disk, int part)
 	return partEnd(disk, part) - partStart(disk, part);
 }
 
+static ulong
+mypc(int x)
+{
+	return getcallerpc(&x);
+}
+
 static void
 diskThread(void *a)
 {
@@ -319,8 +325,8 @@ diskThread(void *a)
 if(0)fprint(2, "diskThread: %d:%d %x\n", getpid(), b->part, b->addr);
 		bwatchLock(b);
 		vtLock(b->lk);
+		b->pc = mypc(0);
 		assert(b->nlock == 1);
-
 		switch(b->iostate){
 		default:
 			abort();

+ 1 - 0
sys/src/cmd/fossil/error.c

@@ -29,6 +29,7 @@ char ENotEmpty[] = "directory not empty";
 char ENotFile[] = "not a file";
 char EReadOnly[] = "file is read only";
 char ERemoved[] = "file has been removed";
+char ENotArchived[] = "file is not archived";
 char EResize[] = "only support truncation to zero length";
 char ERoot[] = "cannot remove root";
 char ESnapOld[] = "snapshot has been deleted";

+ 1 - 0
sys/src/cmd/fossil/error.h

@@ -24,6 +24,7 @@ extern char ENotEmpty[];
 extern char ENotFile[];
 extern char EReadOnly[];
 extern char ERemoved[];
+extern char ENotArchived[];
 extern char EResize[];
 extern char ERoot[];
 extern char ESnapOld[];

+ 132 - 6
sys/src/cmd/fossil/file.c

@@ -355,6 +355,35 @@ fileOpen(Fs *fs, char *path)
 	return _fileOpen(fs, path, 0);
 }
 
+static void
+fileSetTmp(File *f, int istmp)
+{
+	int i;
+	Entry e;
+	Source *r;
+
+	for(i=0; i<2; i++){
+		if(i==0)
+			r = f->source;
+		else
+			r = f->msource;
+		if(r == nil)
+			continue;
+		if(!sourceGetEntry(f->source, &e)){
+			fprint(2, "sourceGetEntry failed (cannot happen): %r\n");
+			continue;
+		}
+		if(istmp)
+			e.flags |= VtEntryNoArchive;
+		else
+			e.flags &= ~VtEntryNoArchive;
+		if(!sourceSetEntry(f->source, &e)){
+			fprint(2, "sourceSetEntry failed (cannot happen): %r\n");
+			continue;
+		}
+	}
+}
+
 File *
 fileCreate(File *f, char *elem, ulong mode, char *uid)
 {
@@ -427,13 +456,23 @@ fileCreate(File *f, char *elem, ulong mode, char *uid)
 	if(ff->boff == NilBlock)
 		goto Err;
 
-	/* committed */
 	sourceUnlock(f->source);
 	sourceUnlock(f->msource);
 
 	ff->source = r;
 	ff->msource = mr;
 
+	if(mode&ModeTemporary){
+		if(!sourceLock2(r, mr, -1))
+			goto Err1;
+		fileSetTmp(ff, 1);
+		sourceUnlock(r);
+		if(mr)
+			sourceUnlock(mr);
+	}
+
+	/* committed */
+
 	/* link in and up parent ref count */
 	ff->next = f->down;
 	f->down = ff;
@@ -529,6 +568,87 @@ Err1:
 	return -1;
 }
 
+/* 
+ * Changes the file block bn to be the given block score.
+ * Very sneaky.  Only used by flfmt.
+ */
+int
+fileMapBlock(File *f, ulong bn, uchar score[VtScoreSize], ulong tag)
+{
+	Block *b;
+	Entry e;
+	Source *s;
+
+	if(!fileLock(f))
+		return 0;
+
+	s = nil;
+	if(f->dir.mode & ModeDir){
+		vtSetError(ENotFile);
+		goto Err;
+	}
+
+	if(f->source->mode != OReadWrite){
+		vtSetError(EReadOnly);
+		goto Err;
+	}
+
+	if(!sourceLock(f->source, -1))
+		goto Err;
+
+	s = f->source;
+	b = _sourceBlock(s, bn, OReadWrite, 1, tag);
+	if(b == nil)
+		goto Err;
+
+	if(!sourceGetEntry(s, &e))
+		goto Err;
+	if(b->l.type == BtDir){
+		memmove(e.score, score, VtScoreSize);
+		assert(e.tag == tag || e.tag == 0);
+		e.tag = tag;
+		e.flags |= VtEntryLocal;
+		entryPack(&e, b->data, f->source->offset % f->source->epb);
+	}else
+		memmove(b->data + (bn%(e.psize/VtScoreSize))*VtScoreSize, score, VtScoreSize);
+	blockDirty(b);
+	blockPut(b);
+	sourceUnlock(s);
+	fileUnlock(f);
+	return 1;
+
+Err:
+	if(s)
+		sourceUnlock(s);
+	fileUnlock(f);
+	return 0;
+}
+
+int
+fileSetSize(File *f, uvlong size)
+{
+	int r;
+
+	if(!fileLock(f))
+		return 0;
+	r = 0;
+	if(f->dir.mode & ModeDir){
+		vtSetError(ENotFile);
+		goto Err;
+	}
+	if(f->source->mode != OReadWrite){
+		vtSetError(EReadOnly);
+		goto Err;
+	}
+	if(!sourceLock(f->source, -1))
+		goto Err;
+	r = sourceSetSize(f->source, size);
+	sourceUnlock(f->source);
+Err:
+	fileUnlock(f);
+	return r;
+}
+
 int
 fileWrite(File *f, void *buf, int cnt, vlong offset, char *uid)
 {
@@ -701,21 +821,27 @@ fileSetDir(File *f, DirEntry *dir, char *uid)
 		}
 	}
 
+	if(!sourceLock2(f->source, f->msource, -1))
+		goto Err;
 	if(!fileIsDir(f)){
-		if(!sourceLock(f->source, -1))
-			goto Err;
 		size = sourceGetSize(f->source);
 		if(size != dir->size){
 			if(!sourceSetSize(f->source, dir->size)){
 				sourceUnlock(f->source);
+				if(f->msource)
+					sourceUnlock(f->msource);
 				goto Err;
 			}
 			/* commited to changing it now */
 		}
-		sourceUnlock(f->source);
 	}
-
 	/* commited to changing it now */
+	if((f->dir.mode&ModeTemporary) != (dir->mode&ModeTemporary))
+		fileSetTmp(f, dir->mode&ModeTemporary);
+	sourceUnlock(f->source);
+	if(f->msource)
+		sourceUnlock(f->msource);
+
 	oelem = nil;
 	if(strcmp(f->dir.elem, dir->elem) != 0){
 		oelem = f->dir.elem;
@@ -1660,7 +1786,7 @@ fileGetSources(File *f, Entry *e, Entry *ee, int mark)
 	|| !getEntry(f->msource, ee, mark))
 		return 0;
 	return 1;
-}
+}	
 
 int
 fileWalkSources(File *f)

+ 22 - 2
sys/src/cmd/fossil/flfmt.c

@@ -1,6 +1,7 @@
 #include "stdinc.h"
 #include "dat.h"
 #include "fns.h"
+#include "flfmt9660.h"
 
 #define blockWrite _blockWrite	/* hack */
 
@@ -27,6 +28,8 @@ Fs *fs;
 uchar *buf;
 int bsize = 8*1024;
 u64int qid = 1;
+int iso9660off;
+char *iso9660file;
 
 int
 confirm(char *msg)
@@ -68,6 +71,10 @@ main(int argc, char *argv[])
 	case 'h':
 		host = EARGF(usage());
 		break;
+	case 'i':
+		iso9660file = EARGF(usage());
+		iso9660off = atoi(EARGF(usage()));
+		break;
 	case 'l':
 		label = EARGF(usage());
 		break;
@@ -89,6 +96,9 @@ main(int argc, char *argv[])
 	if(argc != 1)
 		usage();
 
+	if(iso9660file && score)
+		vtFatal("cannot use -i with -v");
+
 	vtAttach();
 
 	fmtinstall('V', scoreFmt);
@@ -123,11 +133,17 @@ main(int argc, char *argv[])
 	if(disk == nil)
 		vtFatal("could not open disk: %r");
 
+	if(iso9660file)
+		iso9660init(fd, &h, iso9660file, iso9660off);
+
 	/* zero labels */
 	memset(buf, 0, bsize);
 	for(bn = 0; bn < diskSize(disk, PartLabel); bn++)
 		blockWrite(PartLabel, bn);
 
+	if(iso9660file)
+		iso9660labels(disk, buf, blockWrite);
+
 	if(score)
 		root = ventiRoot(host, score);
 	else{
@@ -163,7 +179,7 @@ fdsize(int fd)
 static void
 usage(void)
 {
-	fprint(2, "usage: %s [-b blocksize] [-h host] [-l label] [-v score] [-y] file\n", argv0);
+	fprint(2, "usage: %s [-b blocksize] [-h host] [-i file offset] [-l label] [-v score] [-y] file\n", argv0);
 	exits("usage");
 }
 
@@ -324,8 +340,10 @@ blockAlloc(int type, u32int tag)
 	lpb = bsize/LabelSize;
 
 	blockRead(PartLabel, addr/lpb);
-	if(!labelUnpack(&l, buf, addr % lpb) || l.state != BsFree)
+	if(!labelUnpack(&l, buf, addr % lpb))
 		vtFatal("bad label: %r");
+	if(l.state != BsFree)
+		vtFatal("want to allocate block already in use");
 	l.epoch = 1;
 	l.epochClose = ~(u32int)0;
 	l.type = type;
@@ -424,6 +442,8 @@ topLevel(char *name)
 	addFile(root, "archive", 0555);
 	addFile(root, "snapshot", 0555);
 	fileDecRef(root);
+	if(iso9660file)
+		iso9660copy(fs);
 	vtRUnlock(fs->elk);
 	fsClose(fs);
 }

+ 2 - 0
sys/src/cmd/fossil/fns.h

@@ -2,7 +2,9 @@ Source* sourceRoot(Fs*, u32int, int);
 Source* sourceOpen(Source*, ulong, int);
 Source* sourceCreate(Source*, int, int, u32int);
 Block* sourceBlock(Source*, ulong, int);
+Block* _sourceBlock(Source*, ulong, int, int, ulong);
 int sourceGetEntry(Source*, Entry*);
+int sourceSetEntry(Source*, Entry*);
 int sourceSetSize(Source*, uvlong);
 uvlong sourceGetSize(Source*);
 int sourceSetDirSize(Source*, ulong);

+ 11 - 1
sys/src/cmd/fossil/fossil.c

@@ -1,9 +1,11 @@
 #include "stdinc.h"
+#include <ctype.h>
 
 #include "9.h"
 
 int Dflag;
 char* none = "none";
+
 int stdfd[2];
 
 static void
@@ -21,9 +23,10 @@ static void
 readCmdPart(char *file, char ***pcmd, int *pncmd)
 {
 	char buf[1024+1], *f[1024];
+	char tbuf[1024];
 	int nf;
 	int i, fd, n;
-	char **cmd;
+	char **cmd, *p;
 	int ncmd;
 
 	cmd = *pcmd;
@@ -46,6 +49,13 @@ readCmdPart(char *file, char ***pcmd, int *pncmd)
 		if(f[i][0] == '#')
 			continue;
 		cmd = vtMemRealloc(cmd, (ncmd+1)*sizeof(char*));
+		/* expand argument '*' to mean current file */
+		if((p = strchr(f[i], '*')) && (p==f[i]||isspace(p[-1])) && (p[1]==0||isspace(p[1]))){
+			memmove(tbuf, f[i], p-f[i]);
+			strecpy(tbuf+(p-f[i]), tbuf+sizeof tbuf, file);
+			strecpy(tbuf+strlen(tbuf), tbuf+sizeof tbuf, p+1);
+			f[i] = tbuf;
+		}
 		cmd[ncmd++] = vtStrDup(f[i]);
 	}
 	close(fd);

+ 1 - 1
sys/src/cmd/fossil/fs.c

@@ -98,9 +98,9 @@ fsOpen(char *file, VtSession *z, long ncache, int mode)
 		}
 		superPack(&super, bs->data);
 		blockDependency(bs, b, 0, oscore, nil);
+		blockPut(b);
 		blockDirty(bs);
 		blockPut(bs);
-		blockPut(b);
 		fs->source = sourceRoot(fs, super.active, mode);
 		if(fs->source == nil){
 			vtSetError("sourceRoot: %R");

+ 2 - 0
sys/src/cmd/fossil/fs.h

@@ -32,12 +32,14 @@ int fileClri(File*, char*, char*);
 int fileClriPath(Fs*, char*, char*);
 int fileRead(File*, void *, int, vlong);
 int fileWrite(File*, void *, int, vlong, char*);
+int fileMapBlock(File*, ulong, uchar[VtScoreSize], ulong);
 uvlong fileGetId(File*);
 ulong fileGetMcount(File*);
 int fileIsDir(File*);
 int fileGetSize(File*, uvlong*);
 int fileGetDir(File*, DirEntry*);
 int fileSetDir(File*, DirEntry*, char*);
+int fileSetSize(File*, uvlong);
 File *fileGetParent(File*);
 int fileSync(File*);
 File *fileIncRef(File*);

+ 11 - 0
sys/src/cmd/fossil/mkfile

@@ -66,6 +66,13 @@ test:V: all
 #	cp /env/timezone /n/fossil/tmp
 #	cp /lib/words /n/fossil/tmp
 	dircp /sys/src/cmd/aux /n/fossil/tmp
+	chmod +t /n/fossil/tmp/lis
+	echo SHOULD NOT SEE THIS >>/n/fossil/tmp/lis
+	echo snap -a >>/srv/test.fscons
+	sleep 2
+	mount /srv/test.fossil /n/dump main/archive
+	cat /n/dump/*/*/tmp/lis
+
 #	@{cd /n/fossil/tmp && time tar xTf /sys/src/cmd/fossil/test.tar}
 #	unmount /n/fossil
 #	rm /srv/fossil
@@ -78,6 +85,10 @@ $LIB:	${LIBOFILES:%=$LIB(%)}
 	ar vu $LIB $names
 #	rm $names
 
+$O.flfmt: flfmt9660.$O
+
+flfmt%.$O: flfmt9660.h
+
 %.page:V: %.ps
 	page -w $stem.ps
 

+ 63 - 4
sys/src/cmd/fossil/source.c

@@ -214,6 +214,7 @@ Found:
 	/* found an entry - gen already set */
 	e.psize = psize;
 	e.dsize = dsize;
+	assert(psize && dsize);
 	e.flags = VtEntryActive;
 	if(dir)
 		e.flags |= VtEntryDir;
@@ -491,6 +492,27 @@ sourceGetEntry(Source *r, Entry *e)
 	return 1;
 }
 
+/*
+ * Must be careful with this.  Doesn't record
+ * dependencies, so don't introduce any!
+ */
+int
+sourceSetEntry(Source *r, Entry *e)
+{
+	Block *b;
+	Entry oe;
+
+	assert(sourceIsLocked(r));
+	b = sourceLoad(r, &oe);
+	if(b == nil)
+		return 0;
+	entryPack(e, b->data, r->offset%r->epb);
+	blockDirty(b);
+	blockPut(b);
+
+	return 1;
+}
+
 static Block *
 blockWalk(Block *p, int index, int mode, Fs *fs, Entry *e)
 {
@@ -498,7 +520,7 @@ blockWalk(Block *p, int index, int mode, Fs *fs, Entry *e)
 	Cache *c;
 	u32int addr;
 	int type;
-	uchar oscore[VtScoreSize];
+	uchar oscore[VtScoreSize], score[VtScoreSize];
 	Entry oe;
 
 	c = fs->cache;
@@ -512,6 +534,9 @@ blockWalk(Block *p, int index, int mode, Fs *fs, Entry *e)
 		b = cacheGlobal(c, p->data + index*VtScoreSize, type, e->tag, mode);
 	}
 
+	if(b)
+		b->pc = getcallerpc(&p);
+
 	if(b == nil || mode == OReadOnly)
 		return b;
 
@@ -535,9 +560,11 @@ blockWalk(Block *p, int index, int mode, Fs *fs, Entry *e)
 	if(b == nil)
 		return nil;
 
+	b->pc = getcallerpc(&p);
 	assert(b->l.epoch == fs->ehi);
 
 	blockDirty(b);
+	memmove(score, b->score, VtScoreSize);
 	if(p->l.type == BtDir){
 		memmove(e->score, b->score, VtScoreSize);
 		entryPack(e, p->data, index);
@@ -598,8 +625,8 @@ sourceGrowDepth(Source *r, Block *p, Entry *e, int depth)
 		e->flags |= VtEntryLocal;
 		blockDependency(bb, b, 0, vtZeroScore, nil);
 		blockPut(b);
-		blockDirty(bb);
 		b = bb;
+		blockDirty(b);
 	}
 
 	entryPack(e, p->data, r->offset % r->epb);
@@ -690,8 +717,13 @@ sourceShrinkDepth(Source *r, Block *p, Entry *e, int depth)
 	return d == depth;
 }
 
+/*
+ * Normally we return the block at the given number.
+ * If early is set, we stop earlier in the tree.  Setting early
+ * to 1 gives us the block that contains the pointer to bn.
+ */
 Block *
-sourceBlock(Source *r, ulong bn, int mode)
+_sourceBlock(Source *r, ulong bn, int mode, int early, ulong tag)
 {
 	Block *b, *bb;
 	int index[VtPointerDepth+1];
@@ -710,6 +742,21 @@ sourceBlock(Source *r, ulong bn, int mode)
 	b = sourceLoad(r, &e);
 	if(b == nil)
 		return nil;
+	if(r->mode == OReadOnly && (e.flags & VtEntryNoArchive)){
+		blockPut(b);
+		vtSetError(ENotArchived);
+		return nil;
+	}
+
+	if(tag){
+		if(e.tag == 0)
+			e.tag = tag;
+		else if(e.tag != tag){
+			fprint(2, "tag mismatch\n");
+			vtSetError("tag mismatch");
+			goto Err;
+		}
+	}
 
 	np = e.psize/VtScoreSize;
 	memset(index, 0, sizeof(index));
@@ -733,19 +780,31 @@ sourceBlock(Source *r, ulong bn, int mode)
 
 	index[e.depth] = r->offset % r->epb;
 
-	for(i=e.depth; i>=0; i--){
+	for(i=e.depth; i>=early; i--){
 		bb = blockWalk(b, index[i], m, r->fs, &e);
 		if(bb == nil)
 			goto Err;
 		blockPut(b);
 		b = bb;
 	}
+	b->pc = getcallerpc(&r);
 	return b;
 Err:
 	blockPut(b);
 	return nil;
 }
 
+Block*
+sourceBlock(Source *r, ulong bn, int mode)
+{
+	Block *b;
+
+	b = _sourceBlock(r, bn, mode, 0, 0);
+	if(b)
+		b->pc = getcallerpc(&r);
+	return b;
+}
+
 void
 sourceClose(Source *r)
 {

+ 15 - 1
sys/src/cmd/ip/httpd/httpd.c

@@ -341,7 +341,7 @@ static int
 send(HConnect *c)
 {
 	Dir *dir;
-	char *w, *p, *masque;
+	char *w, *w2, *p, *masque;
 	int fd, fd1, n, force301, ok;
 
 	if(c->req.search)
@@ -364,6 +364,20 @@ send(HConnect *c)
 	strcat(w, masque);
 	strcat(w, c->req.uri);
 
+	/*
+	 *  favicon can be overridden by hostname.ico
+	 */
+	if(strcmp(c->req.uri, "/favicon.ico") == 0){
+		w2 = halloc(c, n+strlen(c->head.host)+2);
+		strcpy(w2, webroot);
+		strcat(w2, masque);
+		strcat(w2, "/");
+		strcat(w2, c->head.host);
+		strcat(w2, ".ico");
+		if(access(w2, AREAD)==0)
+			w = w2;
+	}
+
 	/*
 	 * don't show the contents of .httplogin
 	 */

+ 7 - 2
sys/src/cmd/ip/ppp/compress.c

@@ -453,8 +453,6 @@ tcpuncompress(Tcpc *comp, Block *b, int type)
 	ip->cksum[0] = ip->cksum[1] = 0;
 	hnputs(ip->cksum, ipcsum(b->rptr));
 
-if(*b->rptr != 0x45) syslog(0, LOG, "bad tcpuncompress %2.2ux", *b->rptr);
-
 	return b;
 
 rescue:
@@ -519,3 +517,10 @@ compress_negotiate(Tcpc *tcp, uchar *data)
 	tcp->compressid = data[1];
 	return 0;
 }
+
+/* called by ppp when there was a bad frame received */
+void
+compress_error(Tcpc *tcp)
+{
+	tcp->err = 1;
+}

+ 2 - 0
sys/src/cmd/ip/ppp/ppp.c

@@ -466,6 +466,8 @@ getframe(PPP *ppp, int *protop)
 				return b;
 			}
 		} else if(BLEN(b) > 0){
+			if(ppp->ctcp)
+				compress_error(ppp->ctcp);
 			ppp->in.discards++;
 			netlog("ppp: discard len %ld/%ld cksum %ux (%ux %ux %ux %ux)\n",
 				BLEN(b), BLEN(buf), fcs, b->rptr[0],

+ 1 - 0
sys/src/cmd/ip/ppp/ppp.h

@@ -363,6 +363,7 @@ struct Qualpkt
 };
 
 extern Block*	compress(Tcpc*, Block*, int*);
+extern void	compress_error(Tcpc*);
 extern Tcpc*	compress_init(Tcpc*);
 extern int	compress_negotiate(Tcpc*, uchar*);
 extern Block*	tcpcompress(Tcpc*, Block*, int*);

+ 22 - 5
sys/src/cmd/paqfs/mkpaqfs.c

@@ -138,6 +138,7 @@ PaqDir *
 paqFile(char *name, Dir *dir)
 {
 	int fd, n, nn, nb;
+	vlong tot;
 	uchar *block, *pointer;
 	ulong offset;
 
@@ -151,12 +152,14 @@ paqFile(char *name, Dir *dir)
 	pointer = emallocz(blocksize);
 	nb = 0;
 	n = 0;
+	tot = 0;
 	for(;;) {
 		nn = read(fd, block+n, blocksize-n);
 		if(nn < 0) {
 			warn("read failed: %s: %r", name);
 			goto Err;
 		}
+		tot += nn;
 		if(nn == 0) {	
 			if(n == 0)
 				break;	
@@ -182,6 +185,7 @@ paqFile(char *name, Dir *dir)
 	close(fd);
 	free(pointer);
 	free(block);
+	dir->length = tot;
 	return paqDirAlloc(dir, offset);
 Err:
 	close(fd);
@@ -401,9 +405,16 @@ paqDirSize(PaqDir *d)
 void
 putHeader(uchar *p, PaqHeader *h)
 {
-	putl(p, h->magic);
-	puts(p+4, h->version);
-	puts(p+6, h->blocksize);
+	if(h->blocksize < 65536){
+		putl(p, h->magic);
+		puts(p+4, h->version);
+		puts(p+6, h->blocksize);
+	}else{
+		assert(h->magic == HeaderMagic);
+		puts(p, BigHeaderMagic);
+		puts(p+2, h->version);
+		putl(p+4, h->blocksize);
+	}
 	putl(p+8, h->time);
 	memmove(p+12, h->label, sizeof(h->label));
 }
@@ -419,8 +430,14 @@ putTrailer(uchar *p, PaqTrailer *h)
 void
 putBlock(uchar *p, PaqBlock *b)
 {
-	putl(p, b->magic);
-	puts(p+4, b->size);
+	if(b->size < 65536){
+		putl(p, b->magic);
+		puts(p+4, b->size);
+	}else{
+		assert(b->magic == BlockMagic);
+		puts(p, BigBlockMagic);
+		putl(p+2, b->size);
+	}
 	p[6] = b->type;
 	p[7] = b->encoding;
 	putl(p+8, b->adler32);

+ 63 - 12
sys/src/cmd/paqfs/paqfs.c

@@ -57,12 +57,13 @@ enum
 	Powner =	64,
 };
 
+int	noauth;
 Fid	*fids;
 Fcall	rhdr, thdr;
 int 	blocksize;
 int 	cachesize = 20;
 int	mesgsize = 8*1024 + IOHDRSZ;
-Paq 	*root;
+Paq 	*root, *rootfile;
 Block 	*cache;
 ulong 	cacheage;
 Biobuf	*bin;
@@ -156,6 +157,9 @@ main(int argc, char *argv[])
 			usage();
 		cachesize = atoi(p);
 		break;
+	case 'a':
+		noauth = 1;
+		break;
 	case 'v':
 		verify = 1;
 		break;
@@ -417,6 +421,16 @@ readdir(Fid *f)
 		f->offset = 0;
 	off = f->offset;
 
+	if(rootfile && f->paq == root){
+		if(off != 0){
+			rhdr.count = 0;
+			return nil;
+		}
+		n = packDir(rootfile->dir, buf, cnt);
+		rhdr.count = n;
+		return nil;
+	}
+
 	ptr = blockLoad(f->paq->dir->offset, PointerBlock);
 	if(ptr == nil)
 		return Ebadblock;
@@ -462,7 +476,8 @@ rread(Fid *f)
 {
 	PaqDir *pd;
 	uchar *buf;
-	ulong off;
+	vlong off;
+	ulong uoff;
 	int n, cnt, i;
 	Block *ptr, *b;
 
@@ -487,7 +502,7 @@ rread(Fid *f)
 		return Ebadblock;
 
 	i = off/blocksize;
-	off -= i*blocksize;
+	uoff = off-i*blocksize;
 
 	while(cnt > 0) {
 		b = blockLoad(getl(ptr->data + i*4), DataBlock);
@@ -495,14 +510,14 @@ rread(Fid *f)
 			blockFree(ptr);
 			return Ebadblock;
 		}
-		n = blocksize - off;
+		n = blocksize - uoff;
 		if(n > cnt)
 			n = cnt;
-		memmove(buf, b->data + off, n);
+		memmove(buf, b->data + uoff, n);
 		cnt -= n;
 		thdr.count += n;
 		buf += n;
-		off = 0;
+		uoff = 0;
 		i++;
 		blockFree(b);
 	}
@@ -693,6 +708,12 @@ paqWalk(Paq *s, char *name)
 	if(strcmp(name, "..") == 0)
 		return paqCpy(s->up);
 
+	if(rootfile && s == root){
+		if(strcmp(name, rootfile->dir->name) == 0)
+			return paqCpy(rootfile);
+		return nil;
+	}
+
 	ptr = blockLoad(s->dir->offset, PointerBlock);
 	if(ptr == nil)
 		return nil;
@@ -801,9 +822,9 @@ perm(PaqDir *s, char *user, int p)
 
 	if((p*Pother) & perm)
 		return 1;
-	if(strcmp(user, s->gid)==0 && ((p*Pgroup) & perm))
+	if((noauth || strcmp(user, s->gid)==0) && ((p*Pgroup) & perm))
 		return 1;
-	if(strcmp(user, s->uid)==0 && ((p*Powner) & perm))
+	if((noauth || strcmp(user, s->uid)==0) && ((p*Powner) & perm))
 		return 1;
 	return 0;
 }
@@ -830,7 +851,6 @@ init(char *file, int verify)
 		ds = sha1(0, 0, 0, 0);
 	
 	readHeader(&hdr, file, ds);
-
 	blocksize = hdr.blocksize;
 
 	if(verify) {
@@ -872,6 +892,20 @@ init(char *file, int verify)
 	root->ref = 1;
 	root->dir = r;
 	root->up = root;	/* parent of root is root */
+
+	/* craft root directory if root is a normal file */
+	if(!(root->qid.type&QTDIR)){
+		rootfile = root;
+		root = emallocz(sizeof(Paq));
+		root->qid = rootfile->qid;
+		root->qid.type |= QTDIR;
+		root->qid.path++;
+		root->ref = 1;
+		root->dir = emallocz(sizeof(PaqDir));
+		*root->dir = *r;
+		root->dir->mode |= DMDIR|0111;
+		root->up = root;
+	}
 }
 
 int
@@ -881,13 +915,20 @@ blockRead(uchar *data, ulong addr, int type)
 	PaqBlock b;
 	uchar *cdat;
 
-	if(Bseek(bin, addr, 0) != addr)
+	if(Bseek(bin, addr, 0) != addr){
+		fprint(2, "paqfs: seek %lud: %r\n", addr);
 		return 0;
-	if(Bread(bin, buf, BlockSize) != BlockSize)
+	}
+	if(Bread(bin, buf, BlockSize) != BlockSize){
+		fprint(2, "paqfs: read %d at %lud: %r\n", BlockSize, addr);
 		return 0;
+	}
 	getBlock(buf, &b);
-	if(b.magic != BlockMagic || b.size > blocksize || b.type != type)
+	if(b.magic != BlockMagic || b.size > blocksize || b.type != type){
+		fprint(2, "paqfs: bad block: magic %.8lux (want %.8lux) size %d (max %d) type %d (want %d)\n",
+			b.magic, BlockMagic, b.size, blocksize, b.type, type);
 		return 0;
+	}
 
 	switch(b.encoding) {
 	default:
@@ -903,6 +944,7 @@ blockRead(uchar *data, ulong addr, int type)
 			return 0;
 		}
 		if(inflateblock(data, blocksize, cdat, b.size) < 0) {
+			fprint(2, "inflate error: %r\n");
 			free(cdat);
 			return 0;
 		}
@@ -1068,6 +1110,11 @@ getHeader(uchar *p, PaqHeader *h)
 	h->magic = getl(p);
 	h->version = gets(p+4);
 	h->blocksize = gets(p+6);
+	if((h->magic>>16) == BigHeaderMagic){
+		h->magic = HeaderMagic;
+		h->version = gets(p+2);
+		h->blocksize = getl(p+4);
+	}
 	h->time = getl(p+8);
 	memmove(h->label, p+12, sizeof(h->label));
 	h->label[sizeof(h->label)-1] = 0;
@@ -1086,6 +1133,10 @@ getBlock(uchar *p, PaqBlock *b)
 {
 	b->magic = getl(p);
 	b->size = gets(p+4);
+	if((b->magic>>16) == BigBlockMagic){
+		b->magic = BlockMagic;
+		b->size = getl(p+2);
+	}
 	b->type = p[6];
 	b->encoding = p[7];
 	b->adler32 = getl(p+8);

+ 5 - 3
sys/src/cmd/paqfs/paqfs.h

@@ -6,12 +6,14 @@ typedef struct PaqDir PaqDir;
 enum {
 	HeaderMagic = 0x529ab12b,
 	HeaderSize = 44,
+	BigHeaderMagic = 0x25a9,
 	BlockMagic = 0x198a1cbf,
 	BlockSize = 12,
+	BigBlockMagic = 0x91a8,
 	TrailerMagic = 0x6b46e688,
 	TrailerSize = 28,
 	Version = 1,
-	MaxBlockSize = 56*1024,
+	MaxBlockSize = 512*1024,
 	MinBlockSize = 512,
 	MinDirSize = 28,
 };
@@ -33,7 +35,7 @@ struct PaqHeader
 {
 	ulong	magic;
 	ushort	version;
-	ushort	blocksize;
+	ulong	blocksize;
 	ulong	time;
 	char	label[32];
 };
@@ -41,7 +43,7 @@ struct PaqHeader
 struct PaqBlock
 {
 	ulong	magic;
-	ushort	size;		/* data size - always <= blocksize */
+	ulong	size;		/* data size - always <= blocksize */
 	uchar	type;
 	uchar	encoding;
 	ulong	adler32;	/* applied to unencoded data */

+ 157 - 12
sys/src/cmd/rio/wind.c

@@ -8,6 +8,7 @@
 #include <frame.h>
 #include <fcall.h>
 #include <plumb.h>
+#include <complete.h>
 #include "dat.h"
 #include "fns.h"
 
@@ -441,28 +442,161 @@ interruptproc(void *v)
 	free(notefd);
 }
 
+int
+windfilewidth(Window *w, uint q0, int oneelement)
+{
+	uint q;
+	Rune r;
+
+	q = q0;
+	while(q > 0){
+		r = w->r[q-1];
+		if(r<=' ')
+			break;
+		if(oneelement && r=='/')
+			break;
+		--q;
+	}
+	return q0-q;
+}
+
+void
+showcandidates(Window *w, Completion *c)
+{
+	int i, moveit;
+	Fmt f;
+	Rune *rp;
+	uint nr, qline, q0;
+
+	runefmtstrinit(&f);
+	if(c->nfile > 32)
+		fmtprint(&f, "[%d files]\n", c->nfile);
+	else{
+		fmtprint(&f, "[");
+		for(i=0; i<c->nfile; i++){
+			if(i > 0)
+				fmtprint(&f, " ");
+			fmtprint(&f, "%s", c->filename[i]);
+		}
+		fmtprint(&f, "]\n");
+	}
+	/* place text at beginning of line before host point */
+	qline = w->qh;
+	while(qline>0 && w->r[qline-1] != '\n')
+		qline--;
+
+	rp = runefmtstrflush(&f);
+	nr = runestrlen(rp);
+
+	q0 = w->q0;
+	moveit = q0 == w->qh;
+	winsert(w, rp, runestrlen(rp), qline);
+	if(moveit)
+		w->qh += nr;
+	free(rp);
+	wsetselect(w, q0+nr, q0+nr);
+}
+
+Rune*
+namecomplete(Window *w)
+{
+	int nstr, npath;
+	Rune *rp, *path, *str;
+	Completion *c;
+	char *s, *dir, *root;
+
+	/* control-f: filename completion; works back to white space or / */
+	if(w->q0<w->nr && w->r[w->q0]>' ')	/* must be at end of word */
+		return nil;
+	nstr = windfilewidth(w, w->q0, TRUE);
+	str = runemalloc(nstr);
+	runemove(str, w->r+(w->q0-nstr), nstr);
+	npath = windfilewidth(w, w->q0-nstr, FALSE);
+	path = runemalloc(npath);
+	runemove(path, w->r+(w->q0-nstr-npath), npath);
+	rp = nil;
+
+	/* is path rooted? if not, we need to make it relative to window path */
+	if(npath>0 && path[0]=='/'){
+		dir = malloc(UTFmax*npath+1);
+		sprint(dir, "%.*S", npath, path);
+	}else{
+		if(strcmp(w->dir, "") == 0)
+			root = ".";
+		else
+			root = w->dir;
+		dir = malloc(strlen(root)+1+UTFmax*npath+1);
+		sprint(dir, "%s/%.*S", root, npath, path);
+	}
+	dir = cleanname(dir);
+
+	s = smprint("%.*S", nstr, str);
+	c = complete(dir, s);
+	free(s);
+	if(c == nil)
+		goto Return;
+
+	if(!c->advance)
+		showcandidates(w, c);
+
+	if(c->advance)
+		rp = runesmprint("%s", c->string);
+
+  Return:
+	freecompletion(c);
+	free(dir);
+	free(path);
+	free(str);
+	return rp;
+}
+
 void
 wkeyctl(Window *w, Rune r)
 {
 	uint q0 ,q1;
-	int nb;
+	int nb, nr;
+	Rune *rp;
 	int *notefd;
 
 	if(r == 0)
 		return;
 	if(w->deleted)
 		return;
-	/* silly old compatibility: any of the three ←↓→ arrow keys go down */
-	if(!w->mouseopen && (r==Kdown || r==Kleft || r==Kright)){
-		q0 = w->org+frcharofpt(w, Pt(w->Frame.r.min.x, w->Frame.r.min.y+(w->maxlines/2)*w->font->height));
-		wsetorigin(w, q0, TRUE);
-		return;
-	}
-	if(r==Kup && !w->mouseopen){
-		q0 = wbacknl(w, w->org, w->maxlines/2);
-		wsetorigin(w, q0, TRUE);
-		return;
-	}
+	/* navigation keys work only when mouse is not open */
+	if(!w->mouseopen)
+		switch(r){
+		case Kdown: /* down arrow ↓ scrolls down */
+		case Kpgdown: /* page down scrolls down */
+			q0 = w->org+frcharofpt(w, Pt(w->Frame.r.min.x, w->Frame.r.min.y+(w->maxlines/2)*w->font->height));
+			wsetorigin(w, q0, TRUE);
+			return;
+		case Kup:	/* up arrow ↑ scrolls up */
+		case Kpgup: /* page up scrolls up */
+			q0 = wbacknl(w, w->org, w->maxlines/2);
+			wsetorigin(w, q0, TRUE);
+			return;
+		case Kleft: /* left arrow ← cursors left */
+			if(w->q0 > 0){
+				q0 = w->q0-1;
+				wsetselect(w, q0, q0);
+				wshow(w, q0);
+			}
+			return;
+		case Kright: /* right arrow → cursors right */
+			if(w->q1 < w->nr){
+				q1 = w->q1+1;
+				wsetselect(w, q1, q1);
+				wshow(w, q1);
+			}
+			return;
+		case Khome: /* home goes to beginning of text */
+			wshow(w, 0);
+			return;
+		case Kend: /* end goes to end of text */
+		case 0x05:
+			wshow(w, w->nr);
+			return;
+		}
 	if(w->rawing && (w->q0==w->nr || w->mouseopen)){
 		waddraw(w, &r, 1);
 		return;
@@ -488,6 +622,17 @@ wkeyctl(Window *w, Rune r)
 		*notefd = w->notefd;
 		proccreate(interruptproc, notefd, 4096);
 		return;
+	case 0x06:	/* ^F: file name completion */
+	case Kins:		/* Insert: file name completion */
+		rp = namecomplete(w);
+		if(rp == nil)
+			return;
+		nr = runestrlen(rp);
+		q0 = w->q0;
+		q0 = winsert(w, rp, nr, q0);
+		wshow(w, q0+nr);
+		free(rp);
+		return;
 	case 0x08:	/* ^H: erase character */
 	case 0x15:	/* ^U: erase line */
 	case 0x17:	/* ^W: erase word */

+ 2 - 2
sys/src/cmd/usb/audio/controls.c

@@ -290,7 +290,7 @@ set1(Nexus *nx, int ctl, int req, int i, int val)
 	}
 	buf[0] = val;
 	buf[1] = val>>8;
-	if(setupreq(d, type, req, ((ctl*i)<<8) | i, id, buf, count) < 0)
+	if(setupreq(d, type, req, (ctl<<8) | i, id, buf, count) < 0)
 		return Undef;
 	return 0;
 }
@@ -452,7 +452,7 @@ get1(Nexus *nx, int ctl, int req, int i)
 	case Resolution_control:
 		return Undef;
 	}
-	if(setupreq(d, type, req, ((ctl*i)<<8) | i, id, buf, count) != count){
+	if(setupreq(d, type, req, (ctl<<8) | i, id, buf, count) != count){
 		return Undef;
 	}
 	switch(count) {

+ 2 - 1
sys/src/cmd/usb/mkfile

@@ -1,10 +1,11 @@
-</386/mkfile
+</$objtype/mkfile
 
 DIRS=\
 	lib\
 	usbd\
 	audio\
 	mouse\
+	print\
 
 none:VQ:
 	echo mk all, install, installall, clean, or nuke