Browse Source

Plan 9 from Bell Labs 2005-11-07

David du Colombier 18 years ago
parent
commit
c0a86e3567
100 changed files with 5253 additions and 3112 deletions
  1. 248 247
      dist/replica/_plan9.db
  2. 247 246
      dist/replica/plan9.db
  3. 273 0
      dist/replica/plan9.log
  4. 22 19
      sys/include/a.out.h
  5. 59 55
      sys/include/mach.h
  6. 21 5
      sys/lib/acid/leak
  7. 17 5
      sys/man/1/strip
  8. 6 3
      sys/man/3/vga
  9. 9 1
      sys/man/4/factotum
  10. 14 0
      sys/man/8/plan9.ini
  11. 13 10
      sys/man/8/statusbar
  12. 0 1
      sys/man/8/vga
  13. 1 1
      sys/src/9/alphapc/apc
  14. 11 4
      sys/src/9/alphapc/dat.h
  15. 1 4
      sys/src/9/alphapc/devvga.c
  16. 3 1
      sys/src/9/alphapc/fns.h
  17. 7 7
      sys/src/9/alphapc/main.c
  18. 21 7
      sys/src/9/alphapc/mmu.c
  19. 20 7
      sys/src/9/alphapc/screen.h
  20. 0 2
      sys/src/9/alphapc/sd53c8xx.c
  21. 12 4
      sys/src/9/bitsy/dat.h
  22. 19 1
      sys/src/9/bitsy/devpenmouse.c
  23. 38 49
      sys/src/9/bitsy/main.c
  24. 1 1
      sys/src/9/bitsy/mkfile
  25. 1 21
      sys/src/9/bitsy/sdata.c
  26. 3 1
      sys/src/9/boot/bootauth.c
  27. 11 5
      sys/src/9/mtx/dat.h
  28. 3 7
      sys/src/9/mtx/main.c
  29. 10 10
      sys/src/9/pc/apbootstrap.s
  30. 13 0
      sys/src/9/pc/apic.c
  31. 2 0
      sys/src/9/pc/apm.c
  32. 2 0
      sys/src/9/pc/archmp.c
  33. 19 7
      sys/src/9/pc/dat.h
  34. 2 0
      sys/src/9/pc/devarch.c
  35. 4 5
      sys/src/9/pc/devether.c
  36. 5 3
      sys/src/9/pc/devlml.c
  37. 8 6
      sys/src/9/pc/devpccard.c
  38. 13 13
      sys/src/9/pc/devtv.c
  39. 33 5
      sys/src/9/pc/devvga.c
  40. 3 4
      sys/src/9/pc/dma.c
  41. 0 3
      sys/src/9/pc/ether79c970.c
  42. 17 17
      sys/src/9/pc/ether8139.c
  43. 8 7
      sys/src/9/pc/ether8169.c
  44. 6 6
      sys/src/9/pc/ether82543gc.c
  45. 10 10
      sys/src/9/pc/ether82557.c
  46. 2 0
      sys/src/9/pc/ether83815.c
  47. 3 3
      sys/src/9/pc/ether8390.c
  48. 5 5
      sys/src/9/pc/etherdp83820.c
  49. 4 4
      sys/src/9/pc/etherelnk3.c
  50. 6 6
      sys/src/9/pc/etherga620.c
  51. 10 8
      sys/src/9/pc/etherigbe.c
  52. 1 1
      sys/src/9/pc/ethervt6102.c
  53. 6 5
      sys/src/9/pc/etherwavelan.c
  54. 24 10
      sys/src/9/pc/fns.h
  55. 15 0
      sys/src/9/pc/i8259.c
  56. 269 21
      sys/src/9/pc/l.s
  57. 42 17
      sys/src/9/pc/main.c
  58. 36 25
      sys/src/9/pc/mem.h
  59. 364 88
      sys/src/9/pc/memory.c
  60. 38 17
      sys/src/9/pc/mkfile
  61. 656 282
      sys/src/9/pc/mmu.c
  62. 10 5
      sys/src/9/pc/mp.c
  63. 2 0
      sys/src/9/pc/mp.h
  64. 2 0
      sys/src/9/pc/pc
  65. 4 1
      sys/src/9/pc/pcauth
  66. 1 0
      sys/src/9/pc/pccd
  67. 2 0
      sys/src/9/pc/pccpu
  68. 2 0
      sys/src/9/pc/pccpuf
  69. 2 0
      sys/src/9/pc/pcdisk
  70. 2 0
      sys/src/9/pc/pcf
  71. 2 0
      sys/src/9/pc/pcflop
  72. 19 0
      sys/src/9/pc/pci.c
  73. 132 0
      sys/src/9/pc/realmode.c
  74. 0 7
      sys/src/9/pc/reboot.h
  75. 339 28
      sys/src/9/pc/screen.c
  76. 25 7
      sys/src/9/pc/screen.h
  77. 190 68
      sys/src/9/pc/sd53c8xx.c
  78. 0 773
      sys/src/9/pc/sd53c8xx.i
  79. 36 25
      sys/src/9/pc/sd53c8xx.n
  80. 103 91
      sys/src/9/pc/sdata.c
  81. 1346 0
      sys/src/9/pc/sdmv50xx.c
  82. 1 7
      sys/src/9/pc/sdmylex.c
  83. 0 20
      sys/src/9/pc/sdscsi.c
  84. 39 10
      sys/src/9/pc/trap.c
  85. 12 3
      sys/src/9/pc/vga.c
  86. 23 80
      sys/src/9/pc/vga3dfx.c
  87. 2 1
      sys/src/9/pc/vgaark2000pv.c
  88. 1 0
      sys/src/9/pc/vgabt485.c
  89. 4 30
      sys/src/9/pc/vgaclgd542x.c
  90. 29 87
      sys/src/9/pc/vgaclgd546x.c
  91. 2 1
      sys/src/9/pc/vgact65545.c
  92. 17 39
      sys/src/9/pc/vgacyber938x.c
  93. 2 1
      sys/src/9/pc/vgaet4000.c
  94. 15 61
      sys/src/9/pc/vgahiqvideo.c
  95. 38 88
      sys/src/9/pc/vgai81x.c
  96. 13 53
      sys/src/9/pc/vgamach64xx.c
  97. 22 73
      sys/src/9/pc/vgamga2164w.c
  98. 41 93
      sys/src/9/pc/vgamga4xx.c
  99. 27 84
      sys/src/9/pc/vganeomagic.c
  100. 29 74
      sys/src/9/pc/vganvidia.c

File diff suppressed because it is too large
+ 248 - 247
dist/replica/_plan9.db


+ 247 - 246
dist/replica/plan9.db

@@ -1,25 +1,25 @@
 386 - 20000000775 sys sys 1010957353 0
-386/9load - 775 sys sys 1112757508 215872
-386/9loaddebug - 775 sys sys 1126926546 310558
-386/9loadlite - 775 sys sys 1112757508 135244
-386/9loadlitedebug - 775 sys sys 1126926546 198805
-386/9pc - 775 sys sys 1130961222 1855993
-386/9pc.gz - 664 sys sys 1126005796 645747
-386/9pccpu - 775 sys sys 1130961225 1519780
-386/9pccpu.gz - 664 sys sys 1126005799 530959
-386/9pcdisk - 775 sys sys 1130961229 2047043
-386/9pcdisk.gz - 664 sys sys 1126005804 736406
-386/9pcf - 775 sys sys 1130961234 2390000
-386/9pcf.gz - 664 sys sys 1126005809 888685
-386/9pxeload - 775 sys sys 1112757508 215872
+386/9load - 775 sys sys 1131317303 216948
+386/9loaddebug - 775 sys sys 1131317308 311884
+386/9loadlite - 775 sys sys 1131317306 135668
+386/9loadlitedebug - 775 sys sys 1131317312 200131
+386/9pc - 775 sys sys 1131327135 1881573
+386/9pc.gz - 664 sys sys 1131327137 658788
+386/9pccpu - 775 sys sys 1131327140 1555849
+386/9pccpu.gz - 664 sys sys 1131327141 552578
+386/9pcdisk - 775 sys sys 1131327146 2072564
+386/9pcdisk.gz - 664 sys sys 1131327148 746868
+386/9pcf - 775 sys sys 1131327153 2415653
+386/9pcf.gz - 664 sys sys 1131327156 900998
+386/9pxeload - 775 sys sys 1131317321 216948
 386/_9pcdisk.gz - 664 sys sys 1039764191 695837
 386/bin - 20000000775 sys sys 1018897690 0
 386/bin/8a - 775 sys sys 1130594690 116001
-386/bin/8c - 775 sys sys 1131163700 358353
+386/bin/8c - 775 sys sys 1131296671 358395
 386/bin/8l - 775 sys sys 1130384229 115712
 386/bin/9660srv - 775 sys sys 1130594690 104069
 386/bin/aan - 775 sys sys 1130594690 130742
-386/bin/acid - 775 sys sys 1130594691 390519
+386/bin/acid - 775 sys sys 1131296672 400034
 386/bin/acme - 775 sys sys 1131109821 428636
 386/bin/ape - 20000000775 sys sys 1016944144 0
 386/bin/ape/basename - 775 sys sys 1127360557 132862
@@ -38,7 +38,7 @@
 386/bin/ape/tar - 775 sys sys 1130594693 61935
 386/bin/ape/uname - 775 sys sys 1127360563 132691
 386/bin/aquarela - 775 sys sys 1064598027 319170
-386/bin/ar - 775 sys sys 1130594693 110870
+386/bin/ar - 775 sys sys 1131296672 111983
 386/bin/archfs - 775 sys sys 1130731906 141206
 386/bin/ascii - 775 sys sys 1130594693 64691
 386/bin/astro - 775 sys sys 1130384233 138837
@@ -53,7 +53,7 @@
 386/bin/auth/debug - 775 sys sys 1130594696 101087
 386/bin/auth/disable - 775 sys sys 1020319057 146
 386/bin/auth/enable - 775 sys sys 1020319057 134
-386/bin/auth/factotum - 775 sys sys 1130731907 312978
+386/bin/auth/factotum - 775 sys sys 1131296673 313125
 386/bin/auth/fgui - 775 sys sys 1131109822 217996
 386/bin/auth/guard.srv - 775 sys sys 1130594697 142873
 386/bin/auth/iam - 775 sys sys 1085076981 50791
@@ -117,18 +117,18 @@
 386/bin/aux/mklatinkbd - 775 sys sys 1130594709 64202
 386/bin/aux/mnihongo - 775 sys sys 1131109822 139403
 386/bin/aux/mouse - 775 sys sys 1130384253 44044
-386/bin/aux/ms2 - 775 sys sys 1130594710 85700
+386/bin/aux/ms2 - 775 sys sys 1131296673 87464
 386/bin/aux/msexceltables - 775 sys sys 1130594710 81256
 386/bin/aux/mswordstrings - 775 sys sys 1130594710 65340
 386/bin/aux/na - 775 sys sys 1130594710 154218
 386/bin/aux/nfsmount - 775 sys sys 1130594711 234124
-386/bin/aux/nfsserver - 775 sys sys 1130594711 185436
+386/bin/aux/nfsserver - 775 sys sys 1131296673 185439
 386/bin/aux/olefs - 775 sys sys 1130731910 143686
 386/bin/aux/p9bitpost - 775 sys sys 1104121982 127974
 386/bin/aux/pcmcia - 775 sys sys 1130384255 46923
-386/bin/aux/pcnfsd - 775 sys sys 1130594712 129362
+386/bin/aux/pcnfsd - 775 sys sys 1131296674 129365
 386/bin/aux/portmap - 775 sys sys 1130594713 143642
-386/bin/aux/portmapper - 775 sys sys 1130594713 128248
+386/bin/aux/portmapper - 775 sys sys 1131296674 128251
 386/bin/aux/postgif - 775 sys sys 1087442507 175380
 386/bin/aux/postprint - 775 sys sys 1087442507 160041
 386/bin/aux/postreverse - 775 sys sys 1087442508 164726
@@ -188,7 +188,7 @@
 386/bin/cpu - 775 sys sys 1130594724 139130
 386/bin/crop - 775 sys sys 1130594724 116040
 386/bin/date - 775 sys sys 1130384272 43279
-386/bin/db - 775 sys sys 1130594725 336349
+386/bin/db - 775 sys sys 1131302428 345503
 386/bin/dc - 775 sys sys 1130594725 99051
 386/bin/dd - 775 sys sys 1130384273 45416
 386/bin/deroff - 775 sys sys 1130594726 74267
@@ -225,7 +225,7 @@
 386/bin/faces - 775 sys sys 1131109826 193479
 386/bin/factor - 775 sys sys 1130594733 61498
 386/bin/fcp - 775 sys sys 1131163702 82218
-386/bin/file - 775 sys sys 1130594733 119129
+386/bin/file - 775 sys sys 1131296674 121021
 386/bin/fmt - 775 sys sys 1130594733 65324
 386/bin/fortune - 775 sys sys 1130594734 67159
 386/bin/fossil - 20000000775 sys sys 1042005470 0
@@ -313,8 +313,8 @@
 386/bin/join - 775 sys sys 1130594758 114123
 386/bin/jpg - 775 sys sys 1130594758 174551
 386/bin/kbmap - 775 sys sys 1131109830 143398
-386/bin/kprof - 775 sys sys 1130594758 102550
-386/bin/ktrace - 775 sys sys 1130594759 116639
+386/bin/kprof - 775 sys sys 1131296675 105507
+386/bin/ktrace - 775 sys sys 1131296675 121949
 386/bin/lens - 775 sys sys 1131109830 150495
 386/bin/lex - 775 sys sys 1130594760 98687
 386/bin/lnfs - 775 sys sys 1130594760 99472
@@ -322,7 +322,7 @@
 386/bin/ls - 775 sys sys 1130594760 82503
 386/bin/mc - 775 sys sys 1130594760 133643
 386/bin/md5sum - 775 sys sys 1130594761 61297
-386/bin/mk - 775 sys sys 1130594761 144071
+386/bin/mk - 775 sys sys 1131302428 144690
 386/bin/mkdir - 775 sys sys 1130594761 60996
 386/bin/mkpaqfs - 775 sys sys 1130594762 94532
 386/bin/mntgen - 775 sys sys 1130731913 139629
@@ -346,7 +346,7 @@
 386/bin/netstat - 775 sys sys 1130594767 84696
 386/bin/news - 775 sys sys 1130594767 71692
 386/bin/nfs - 775 sys sys 1130731913 315832
-386/bin/nm - 775 sys sys 1130594769 121826
+386/bin/nm - 775 sys sys 1131296675 125784
 386/bin/nntpfs - 775 sys sys 1130731914 161341
 386/bin/ns - 775 sys sys 1130594769 65283
 386/bin/p - 775 sys sys 1130594769 65013
@@ -364,7 +364,7 @@
 386/bin/ppm - 775 sys sys 1130594773 149370
 386/bin/pr - 775 sys sys 1130594773 77431
 386/bin/primes - 775 sys sys 1130384322 38811
-386/bin/prof - 775 sys sys 1130594773 107968
+386/bin/prof - 775 sys sys 1131296676 110924
 386/bin/proof - 775 sys sys 1131109832 178492
 386/bin/ps - 775 sys sys 1130594774 68017
 386/bin/pwd - 775 sys sys 1130384323 36915
@@ -393,10 +393,10 @@
 386/bin/sed - 775 sys sys 1130594781 89546
 386/bin/seq - 775 sys sys 1130384331 38414
 386/bin/sha1sum - 775 sys sys 1130594782 61165
-386/bin/size - 775 sys sys 1130594782 77006
+386/bin/size - 775 sys sys 1131296676 78794
 386/bin/sleep - 775 sys sys 1085077097 3413
-386/bin/snap - 775 sys sys 1130594783 303743
-386/bin/snapfs - 775 sys sys 1130731915 373001
+386/bin/snap - 775 sys sys 1131302429 310917
+386/bin/snapfs - 775 sys sys 1131302430 380175
 386/bin/sniffer - 775 sys sys 1038443185 99028
 386/bin/snoopy - 775 sys sys 1130594784 168241
 386/bin/sort - 775 sys sys 1130594784 82308
@@ -409,13 +409,13 @@
 386/bin/sshnet - 775 sys sys 1130731916 283308
 386/bin/stats - 775 sys sys 1131109834 190360
 386/bin/strings - 775 sys sys 1130594787 62147
-386/bin/strip - 775 sys sys 1130594787 62013
+386/bin/strip - 775 sys sys 1131296676 80766
 386/bin/sum - 775 sys sys 1130384338 39488
 386/bin/swap - 775 sys sys 1130594787 62126
 386/bin/syscall - 775 sys sys 1130594788 73568
 386/bin/tail - 775 sys sys 1130594788 66201
 386/bin/tar - 775 sys sys 1130594788 97067
-386/bin/tbl - 775 sys sys 1130594788 113269
+386/bin/tbl - 775 sys sys 1131302431 113308
 386/bin/tcs - 775 sys sys 1130384340 256598
 386/bin/tee - 775 sys sys 1130384340 38446
 386/bin/telco - 775 sys sys 1130594788 103347
@@ -429,7 +429,7 @@
 386/bin/topng - 775 sys sys 1130594792 138351
 386/bin/toppm - 775 sys sys 1130594792 165173
 386/bin/touch - 775 sys sys 1130594792 63795
-386/bin/tprof - 775 sys sys 1130594793 290212
+386/bin/tprof - 775 sys sys 1131296677 297344
 386/bin/tr - 775 sys sys 1130594793 61883
 386/bin/trace - 775 sys sys 1131109834 180855
 386/bin/troff - 775 sys sys 1127360609 357940
@@ -521,8 +521,8 @@
 386/include/ape/ureg.h - 664 sys sys 944946041 812
 386/include/u.h - 664 sys sys 1115924095 1481
 386/include/ureg.h - 664 sys sys 944946012 523
-386/init - 775 sys sys 1130594818 101212
-386/ld.com - 775 sys sys 1109598589 72076
+386/init - 775 sys sys 1131317332 101212
+386/ld.com - 775 sys sys 1131317344 72524
 386/lib - 20000000775 sys sys 1016826328 0
 386/lib/ape - 20000000775 sys sys 944969312 0
 386/lib/ape/lib9.a - 664 sys sys 1038237538 6378
@@ -553,7 +553,7 @@
 386/lib/libhttpd.a - 664 sys sys 1127790504 99596
 386/lib/libip.a - 664 sys sys 1116126324 35602
 386/lib/libl.a - 664 sys sys 1115950154 5384
-386/lib/libmach.a - 664 sys sys 1120619355 755696
+386/lib/libmach.a - 664 sys sys 1131296679 782950
 386/lib/libmemdraw.a - 664 sys sys 1120792317 284130
 386/lib/libmemlayer.a - 664 sys sys 1115950157 47360
 386/lib/libmp.a - 664 sys sys 1127360619 79944
@@ -566,10 +566,10 @@
 386/lib/libsunrpc.a - 664 sys sys 1115950160 355994
 386/lib/libthread.a - 664 sys sys 1127405452 72374
 386/lib/libventi.a - 664 sys sys 1124766772 97708
-386/mbr - 775 sys sys 1022125974 407
+386/mbr - 775 sys sys 1131317338 407
 386/mkfile - 664 sys sys 948141303 46
-386/pbs - 775 sys sys 1022125973 494
-386/pbslba - 775 sys sys 1022125974 507
+386/pbs - 775 sys sys 1131317339 494
+386/pbslba - 775 sys sys 1131317342 507
 68000 - 20000000775 sys sys 947991045 0
 68000/bin - 20000000775 sys sys 985559408 0
 68000/bin/bitsy - 20000000775 sys sys 985559408 0
@@ -5943,7 +5943,7 @@ sys/games/sudoku - 20000000775 sys sys 1117225532 0
 sys/include - 20000000775 sys sys 1016902416 0
 sys/include/9p.h - 664 sys sys 1130649668 4420
 sys/include/String.h - 664 sys sys 1091904425 1319
-sys/include/a.out.h - 664 sys sys 1114218489 1291
+sys/include/a.out.h - 664 sys sys 1131293220 1407
 sys/include/ape - 20000000775 sys sys 1014927784 0
 sys/include/ape/Plan9libnet.h - 664 sys sys 944948760 487
 sys/include/ape/ar.h - 664 sys sys 944948759 354
@@ -6030,7 +6030,7 @@ sys/include/ip.h - 664 sys sys 1103554773 2989
 sys/include/keyboard.h - 664 sys sys 1079577798 815
 sys/include/libc.h - 664 sys sys 1115925565 19623
 sys/include/libsec.h - 664 sys sys 1124709121 9345
-sys/include/mach.h - 664 sys sys 1119476886 8368
+sys/include/mach.h - 664 sys sys 1131289126 8586
 sys/include/memdraw.h - 664 sys sys 1091904419 5645
 sys/include/memlayer.h - 664 sys sys 1051031022 1851
 sys/include/mouse.h - 664 sys sys 1035232010 1003
@@ -6059,7 +6059,7 @@ sys/lib/acid/alpha - 664 sys sys 944955985 4849
 sys/lib/acid/arm - 664 sys sys 984696197 1842
 sys/lib/acid/coverage - 664 sys sys 944955985 1746
 sys/lib/acid/kernel - 664 sys sys 1126699644 6303
-sys/lib/acid/leak - 664 sys sys 1110989276 2185
+sys/lib/acid/leak - 664 sys sys 1131289472 2363
 sys/lib/acid/mips - 664 sys sys 944955985 5472
 sys/lib/acid/network - 664 sys sys 1020313817 2499
 sys/lib/acid/pool - 664 sys sys 1063858105 4898
@@ -7355,7 +7355,7 @@ sys/man/1/src - 664 sys sys 954266293 1138
 sys/man/1/ssh - 664 sys sys 1048643947 6622
 sys/man/1/stop - 664 sys sys 944959673 658
 sys/man/1/strings - 664 sys sys 944959675 774
-sys/man/1/strip - 664 sys sys 958580250 448
+sys/man/1/strip - 664 sys sys 1131293239 523
 sys/man/1/sum - 664 sys sys 984772442 1390
 sys/man/1/syscall - 664 sys sys 1016466457 1439
 sys/man/1/tail - 664 sys sys 1113743327 1413
@@ -7567,7 +7567,7 @@ sys/man/3/ssl - 664 sys sys 1018386776 3413
 sys/man/3/tls - 664 sys sys 1045501496 7018
 sys/man/3/uart - 664 sys sys 1102093395 1710
 sys/man/3/usb - 664 sys sys 1126971427 6960
-sys/man/3/vga - 664 sys sys 1020356225 4827
+sys/man/3/vga - 664 sys sys 1131301005 4957
 sys/man/4 - 20000000775 sys sys 1018581459 0
 sys/man/4/0intro - 664 sys sys 944959699 472
 sys/man/4/INDEX - 664 sys sys 1104811679 985
@@ -7581,7 +7581,7 @@ sys/man/4/dossrv - 664 sys sys 1015024813 4176
 sys/man/4/execnet - 664 sys sys 1019866708 1069
 sys/man/4/exportfs - 664 sys sys 1115314261 4653
 sys/man/4/ext2srv - 664 sys sys 1055692986 2409
-sys/man/4/factotum - 664 sys sys 1128483118 14709
+sys/man/4/factotum - 664 sys sys 1131294573 14841
 sys/man/4/fossil - 664 sys sys 1112368411 9546
 sys/man/4/fs - 664 sys sys 1019058716 3387
 sys/man/4/ftpfs - 664 sys sys 1112563349 4410
@@ -7708,7 +7708,7 @@ sys/man/8/nfsserver - 664 sys sys 1128483119 3397
 sys/man/8/pcmcia - 664 sys sys 944959679 408
 sys/man/8/pem - 664 sys sys 1060263669 1189
 sys/man/8/ping - 664 sys sys 1084473185 3436
-sys/man/8/plan9.ini - 664 sys sys 1117814755 21579
+sys/man/8/plan9.ini - 664 sys sys 1131294569 22077
 sys/man/8/pop3 - 664 sys sys 1063854676 2720
 sys/man/8/ppp - 664 sys sys 1125530075 4414
 sys/man/8/prep - 664 sys sys 1079705872 13820
@@ -7724,7 +7724,7 @@ sys/man/8/send - 664 sys sys 1045501634 2168
 sys/man/8/smtp - 664 sys sys 1091126310 4724
 sys/man/8/snoopy - 664 sys sys 1128179510 4054
 sys/man/8/stats - 664 sys sys 1067722908 4291
-sys/man/8/statusbar - 664 sys sys 1131209276 1199
+sys/man/8/statusbar - 664 sys sys 1131317865 1251
 sys/man/8/stub - 664 sys sys 1044830500 943
 sys/man/8/swap - 664 sys sys 944959679 880
 sys/man/8/timesync - 664 sys sys 1107606876 1717
@@ -7734,7 +7734,7 @@ sys/man/8/udpecho - 664 sys sys 954305553 303
 sys/man/8/update - 664 sys sys 961259288 2336
 sys/man/8/venti - 664 sys sys 1069101926 5422
 sys/man/8/ventiaux - 664 sys sys 1063855987 10487
-sys/man/8/vga - 664 sys sys 1114454069 3936
+sys/man/8/vga - 664 sys sys 1131301001 3864
 sys/man/fonts - 664 sys sys 944959700 218
 sys/man/index.html - 664 sys sys 1019918444 1859
 sys/man/mkfile - 664 sys sys 1018974173 2264
@@ -7748,7 +7748,7 @@ sys/man/vol1.ps.gz - 664 sys sys 1020374752 2174519
 sys/src - 20000000775 sys sys 1016902537 0
 sys/src/9 - 20000000775 sys sys 1017795023 0
 sys/src/9/alphapc - 20000000775 sys sys 1018721238 0
-sys/src/9/alphapc/apc - 664 sys sys 1084331942 629
+sys/src/9/alphapc/apc - 664 sys sys 1131289706 630
 sys/src/9/alphapc/apccpu - 664 sys sys 1084331942 531
 sys/src/9/alphapc/arch164.c - 664 sys sys 1015012783 6100
 sys/src/9/alphapc/audio.h - 664 sys sys 1015012783 349
@@ -7756,30 +7756,30 @@ sys/src/9/alphapc/axp.h - 664 sys sys 1015012783 1090
 sys/src/9/alphapc/cga.c - 664 sys sys 1015012783 1814
 sys/src/9/alphapc/clock.c - 664 sys sys 1032052963 1472
 sys/src/9/alphapc/cycintr.c - 664 sys sys 1018721238 230
-sys/src/9/alphapc/dat.h - 664 sys sys 1127215703 5238
+sys/src/9/alphapc/dat.h - 664 sys sys 1131289707 5196
 sys/src/9/alphapc/devarch.c - 664 sys sys 1039753422 9760
-sys/src/9/alphapc/devvga.c - 664 sys sys 1015012784 7513
+sys/src/9/alphapc/devvga.c - 664 sys sys 1131289707 7420
 sys/src/9/alphapc/dma.c - 664 sys sys 1015012784 6112
 sys/src/9/alphapc/etherif.h - 664 sys sys 1045063621 1025
 sys/src/9/alphapc/faultalpha.c - 664 sys sys 1015012784 1257
 sys/src/9/alphapc/fdc37c93x.c - 664 sys sys 1015012785 1110
 sys/src/9/alphapc/floppy.h - 664 sys sys 1015012785 3783
-sys/src/9/alphapc/fns.h - 664 sys sys 1111851541 3572
+sys/src/9/alphapc/fns.h - 664 sys sys 1131289707 3613
 sys/src/9/alphapc/fptrap.c - 664 sys sys 1015012785 707
 sys/src/9/alphapc/i8259.c - 664 sys sys 1015012785 3409
 sys/src/9/alphapc/initcode - 664 sys sys 1039753419 779
 sys/src/9/alphapc/io.h - 664 sys sys 1087657423 4540
 sys/src/9/alphapc/kbd.c - 664 sys sys 1015012785 8676
 sys/src/9/alphapc/l.s - 664 sys sys 1067722580 9124
-sys/src/9/alphapc/main.c - 664 sys sys 1126586256 13624
+sys/src/9/alphapc/main.c - 664 sys sys 1131289707 13672
 sys/src/9/alphapc/mem.h - 664 sys sys 1077408326 3131
 sys/src/9/alphapc/memmove.s - 664 sys sys 1015012786 2936
 sys/src/9/alphapc/memset.s - 664 sys sys 1015012786 844
 sys/src/9/alphapc/mkfile - 664 sys sys 1109218102 1682
-sys/src/9/alphapc/mmu.c - 664 sys sys 1123438209 4905
+sys/src/9/alphapc/mmu.c - 664 sys sys 1131289708 4945
 sys/src/9/alphapc/pci.c - 664 sys sys 1039753420 7868
-sys/src/9/alphapc/screen.h - 664 sys sys 1060267151 3584
-sys/src/9/alphapc/sd53c8xx.c - 664 sys sys 1015012787 51009
+sys/src/9/alphapc/screen.h - 664 sys sys 1131289708 3818
+sys/src/9/alphapc/sd53c8xx.c - 664 sys sys 1131289709 50963
 sys/src/9/alphapc/sio.c - 664 sys sys 1015012787 293
 sys/src/9/alphapc/trap.c - 664 sys sys 1105030177 18099
 sys/src/9/bitsy - 20000000775 sys sys 1018721429 0
@@ -7787,12 +7787,12 @@ sys/src/9/bitsy/Booting101 - 664 sys sys 1054798506 8841
 sys/src/9/bitsy/bitsy - 664 sys sys 1067722592 424
 sys/src/9/bitsy/bitsyreset.s - 664 sys sys 1017695510 2352
 sys/src/9/bitsy/clock.c - 664 sys sys 1037028998 4835
-sys/src/9/bitsy/dat.h - 664 sys sys 1099805278 5857
+sys/src/9/bitsy/dat.h - 664 sys sys 1131289775 5829
 sys/src/9/bitsy/defont.c - 664 sys sys 1017695511 21570
 sys/src/9/bitsy/devether.c - 664 sys sys 1116097769 10675
 sys/src/9/bitsy/devflash.c - 664 sys sys 1018386999 16832
 sys/src/9/bitsy/devpcmcia.c - 664 sys sys 1099801570 12977
-sys/src/9/bitsy/devpenmouse.c - 664 sys sys 1067722592 9296
+sys/src/9/bitsy/devpenmouse.c - 664 sys sys 1131289775 9589
 sys/src/9/bitsy/devuda1341.c - 664 sys sys 1071245420 30346
 sys/src/9/bitsy/devµc.c - 664 sys sys 1068393562 8125
 sys/src/9/bitsy/etherif.h - 664 sys sys 1045501788 913
@@ -7807,10 +7807,10 @@ sys/src/9/bitsy/gamma.h - 664 sys sys 1017695514 540718
 sys/src/9/bitsy/init9.s - 664 sys sys 1043922398 183
 sys/src/9/bitsy/io.h - 664 sys sys 1064584624 8040
 sys/src/9/bitsy/l.s - 664 sys sys 1055700934 18211
-sys/src/9/bitsy/main.c - 664 sys sys 1126586256 9081
+sys/src/9/bitsy/main.c - 664 sys sys 1131289775 8816
 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 1072705544 2452
+sys/src/9/bitsy/mkfile - 664 sys sys 1131289775 2459
 sys/src/9/bitsy/mmu.c - 664 sys sys 1123438209 11261
 sys/src/9/bitsy/mouse.c - 664 sys sys 1017695516 962
 sys/src/9/bitsy/paqfiles - 20000000775 sys sys 1020011250 0
@@ -7827,7 +7827,7 @@ sys/src/9/bitsy/sa1110dma.h - 664 sys sys 1017695520 381
 sys/src/9/bitsy/screen.c - 664 sys sys 1053340962 10145
 sys/src/9/bitsy/screen.h - 664 sys sys 1017695520 260
 sys/src/9/bitsy/sd.h - 664 sys sys 1037029038 0
-sys/src/9/bitsy/sdata.c - 664 sys sys 1055700868 44660
+sys/src/9/bitsy/sdata.c - 664 sys sys 1131289776 44404
 sys/src/9/bitsy/tar.c - 664 sys sys 1017695521 1375
 sys/src/9/bitsy/trap.c - 664 sys sys 1105030166 19484
 sys/src/9/bitsy/uartsa1110.c - 664 sys sys 1037029045 8530
@@ -7837,7 +7837,7 @@ sys/src/9/boot - 20000000775 sys sys 1018556557 0
 sys/src/9/boot/aux.c - 664 sys sys 1063857702 2579
 sys/src/9/boot/boot.c - 664 sys sys 1130982159 6067
 sys/src/9/boot/boot.h - 664 sys sys 1063857659 1785
-sys/src/9/boot/bootauth.c - 664 sys sys 1039763726 1097
+sys/src/9/boot/bootauth.c - 664 sys sys 1131289783 1160
 sys/src/9/boot/bootcache.c - 664 sys sys 1063857645 1579
 sys/src/9/boot/bootip.c - 664 sys sys 1072972133 3418
 sys/src/9/boot/bootmkfile - 664 sys sys 1091732792 404
@@ -7887,7 +7887,7 @@ sys/src/9/mkfile - 664 sys sys 1063857477 205
 sys/src/9/mtx - 20000000775 sys sys 1018721288 0
 sys/src/9/mtx/clock.c - 664 sys sys 1032053278 1293
 sys/src/9/mtx/cycintr.c - 664 sys sys 1018721285 230
-sys/src/9/mtx/dat.h - 664 sys sys 1127215703 3897
+sys/src/9/mtx/dat.h - 664 sys sys 1131289814 3843
 sys/src/9/mtx/devarch.c - 664 sys sys 1018721285 6793
 sys/src/9/mtx/devether.c - 664 sys sys 1116097786 9281
 sys/src/9/mtx/devrtc.c - 664 sys sys 1018721285 6772
@@ -7900,7 +7900,7 @@ sys/src/9/mtx/initcode - 664 sys sys 1039753442 444
 sys/src/9/mtx/io.h - 664 sys sys 1087657404 4817
 sys/src/9/mtx/kbd.c - 664 sys sys 1018721286 8358
 sys/src/9/mtx/l.s - 664 sys sys 1067722599 10730
-sys/src/9/mtx/main.c - 664 sys sys 1126586256 8342
+sys/src/9/mtx/main.c - 664 sys sys 1131289814 8307
 sys/src/9/mtx/mem.h - 664 sys sys 1026848200 5959
 sys/src/9/mtx/mkfile - 664 sys sys 1072972534 1520
 sys/src/9/mtx/mmu.c - 664 sys sys 1123438210 4421
@@ -7913,83 +7913,83 @@ sys/src/9/mtx/trap.c - 664 sys sys 1105030157 15882
 sys/src/9/mtx/uarti8250.c - 664 sys sys 1018721288 11590
 sys/src/9/pc - 20000000775 sys sys 1018721225 0
 sys/src/9/pc/apbootstrap.h - 664 sys sys 1018553448 928
-sys/src/9/pc/apbootstrap.s - 664 sys sys 1015014512 3037
-sys/src/9/pc/apic.c - 664 sys sys 1084475126 8643
-sys/src/9/pc/apm.c - 664 sys sys 1015014513 3697
+sys/src/9/pc/apbootstrap.s - 664 sys sys 1131293655 3037
+sys/src/9/pc/apic.c - 664 sys sys 1131290206 8748
+sys/src/9/pc/apm.c - 664 sys sys 1131290210 3723
 sys/src/9/pc/apmjump.s - 664 sys sys 1032058947 1527
-sys/src/9/pc/archmp.c - 664 sys sys 1084475127 2311
+sys/src/9/pc/archmp.c - 664 sys sys 1131290214 2357
 sys/src/9/pc/audio.h - 664 sys sys 1015014513 343
 sys/src/9/pc/cga.c - 664 sys sys 1015014513 1843
-sys/src/9/pc/dat.h - 664 sys sys 1091904418 6281
-sys/src/9/pc/devarch.c - 664 sys sys 1115566123 18554
-sys/src/9/pc/devether.c - 664 sys sys 1116173410 10327
+sys/src/9/pc/dat.h - 664 sys sys 1131290217 6462
+sys/src/9/pc/devarch.c - 664 sys sys 1131290259 18594
+sys/src/9/pc/devether.c - 664 sys sys 1131290265 10315
 sys/src/9/pc/devfloppy.c - 664 sys sys 1055689885 20024
 sys/src/9/pc/devi82365.c - 664 sys sys 1099761153 20505
 sys/src/9/pc/devlm78.c - 664 sys sys 1128255048 6291
-sys/src/9/pc/devlml.c - 664 sys sys 1026847636 7486
+sys/src/9/pc/devlml.c - 664 sys sys 1131290276 7505
 sys/src/9/pc/devlml.h - 664 sys sys 1026847636 2948
 sys/src/9/pc/devlpt.c - 664 sys sys 1015014514 4420
-sys/src/9/pc/devpccard.c - 664 sys sys 1107531947 40194
+sys/src/9/pc/devpccard.c - 664 sys sys 1131290281 40203
 sys/src/9/pc/devrtc.c - 664 sys sys 1015014515 7167
-sys/src/9/pc/devtv.c - 664 sys sys 1091734484 45725
+sys/src/9/pc/devtv.c - 664 sys sys 1131290299 45676
 sys/src/9/pc/devusb.c - 664 sys sys 1105193103 18364
-sys/src/9/pc/devvga.c - 664 sys sys 1063857412 8714
-sys/src/9/pc/dma.c - 664 sys sys 1015014515 4736
+sys/src/9/pc/devvga.c - 664 sys sys 1131290315 9332
+sys/src/9/pc/dma.c - 664 sys sys 1131290319 4715
 sys/src/9/pc/ether2000.c - 664 sys sys 1089299187 4819
 sys/src/9/pc/ether2114x.c - 664 sys sys 1081706476 41545
 sys/src/9/pc/ether589.c - 664 sys sys 1015014516 4644
-sys/src/9/pc/ether79c970.c - 664 sys sys 1071245466 14094
+sys/src/9/pc/ether79c970.c - 664 sys sys 1131290338 13953
 sys/src/9/pc/ether8003.c - 664 sys sys 1015014516 6665
-sys/src/9/pc/ether8139.c - 664 sys sys 1121393473 18385
-sys/src/9/pc/ether8169.c - 664 sys sys 1121391723 22704
-sys/src/9/pc/ether82543gc.c - 664 sys sys 1055689887 32296
-sys/src/9/pc/ether82557.c - 664 sys sys 1117550886 30121
-sys/src/9/pc/ether83815.c - 664 sys sys 1115744557 23481
-sys/src/9/pc/ether8390.c - 664 sys sys 1112382834 17701
+sys/src/9/pc/ether8139.c - 664 sys sys 1131290376 18400
+sys/src/9/pc/ether8169.c - 664 sys sys 1131290377 22723
+sys/src/9/pc/ether82543gc.c - 664 sys sys 1131290377 32294
+sys/src/9/pc/ether82557.c - 664 sys sys 1131290377 30107
+sys/src/9/pc/ether83815.c - 664 sys sys 1131287537 23542
+sys/src/9/pc/ether8390.c - 664 sys sys 1131290377 17702
 sys/src/9/pc/ether8390.h - 664 sys sys 1015014517 1511
-sys/src/9/pc/etherdp83820.c - 664 sys sys 1083469193 29134
+sys/src/9/pc/etherdp83820.c - 664 sys sys 1131290378 29128
 sys/src/9/pc/etherec2t.c - 664 sys sys 1086960044 4039
-sys/src/9/pc/etherelnk3.c - 664 sys sys 1081706477 48724
-sys/src/9/pc/etherga620.c - 664 sys sys 1074785126 28754
+sys/src/9/pc/etherelnk3.c - 664 sys sys 1131290378 48733
+sys/src/9/pc/etherga620.c - 664 sys sys 1131290379 28748
 sys/src/9/pc/etherga620fw.h - 664 sys sys 1026847642 222295
 sys/src/9/pc/etherif.h - 664 sys sys 1088178711 961
-sys/src/9/pc/etherigbe.c - 664 sys sys 1127393123 44412
+sys/src/9/pc/etherigbe.c - 664 sys sys 1131290379 44431
 sys/src/9/pc/ethermii.c - 664 sys sys 1084331434 4612
 sys/src/9/pc/ethermii.h - 664 sys sys 1086873891 3258
 sys/src/9/pc/etherrhine.c - 664 sys sys 1081706478 13799
 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/ethervt6102.c - 664 sys sys 1109202304 22569
-sys/src/9/pc/etherwavelan.c - 664 sys sys 1107448246 3723
+sys/src/9/pc/ethervt6102.c - 664 sys sys 1131290379 22572
+sys/src/9/pc/etherwavelan.c - 664 sys sys 1131290380 3747
 sys/src/9/pc/floppy.h - 664 sys sys 1055700609 3835
-sys/src/9/pc/fns.h - 664 sys sys 1111851554 4198
+sys/src/9/pc/fns.h - 664 sys sys 1131290383 4461
 sys/src/9/pc/hcwAMC.h - 664 sys sys 1026860163 166004
 sys/src/9/pc/i8253.c - 664 sys sys 1096379063 6279
-sys/src/9/pc/i8259.c - 664 sys sys 1015014519 4423
+sys/src/9/pc/i8259.c - 664 sys sys 1131290399 4586
 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 1099761152 8095
 sys/src/9/pc/kbd.c - 664 sys sys 1130848300 12362
-sys/src/9/pc/l.s - 664 sys sys 1115566067 23833
-sys/src/9/pc/main.c - 664 sys sys 1126586232 14691
-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
-sys/src/9/pc/mmu.c - 664 sys sys 1125564128 10489
+sys/src/9/pc/l.s - 664 sys sys 1131290403 28347
+sys/src/9/pc/main.c - 664 sys sys 1131290418 15224
+sys/src/9/pc/mem.h - 664 sys sys 1131290422 5209
+sys/src/9/pc/memory.c - 664 sys sys 1131290429 18222
+sys/src/9/pc/mkfile - 664 sys sys 1131294850 3580
+sys/src/9/pc/mmu.c - 664 sys sys 1131326224 19739
 sys/src/9/pc/mouse.c - 664 sys sys 1098479254 7057
-sys/src/9/pc/mp.c - 664 sys sys 1123637234 17024
-sys/src/9/pc/mp.h - 664 sys sys 1015014520 6575
+sys/src/9/pc/mp.c - 664 sys sys 1131326235 17157
+sys/src/9/pc/mp.h - 664 sys sys 1131290475 6638
 sys/src/9/pc/nv_dma.h - 664 sys sys 1081384508 12943
-sys/src/9/pc/pc - 664 sys sys 1127411319 1408
-sys/src/9/pc/pcauth - 664 sys sys 1073851852 657
-sys/src/9/pc/pccd - 664 sys sys 1091458811 1408
-sys/src/9/pc/pccpu - 664 sys sys 1127411311 835
-sys/src/9/pc/pccpuf - 664 sys sys 1127411330 1467
-sys/src/9/pc/pcdisk - 664 sys sys 1073851851 1427
-sys/src/9/pc/pcf - 664 sys sys 1104430623 1485
+sys/src/9/pc/pc - 664 sys sys 1131290481 1427
+sys/src/9/pc/pcauth - 664 sys sys 1131290482 714
+sys/src/9/pc/pccd - 664 sys sys 1131290486 1418
+sys/src/9/pc/pccpu - 664 sys sys 1131290488 866
+sys/src/9/pc/pccpuf - 664 sys sys 1131299996 1486
+sys/src/9/pc/pcdisk - 664 sys sys 1131299995 1446
+sys/src/9/pc/pcf - 664 sys sys 1131299996 1504
 sys/src/9/pc/pcfl - 664 sys sys 1042004821 1563
-sys/src/9/pc/pcflop - 664 sys sys 1112361040 1454
-sys/src/9/pc/pci.c - 664 sys sys 1121260128 26418
+sys/src/9/pc/pcflop - 664 sys sys 1131299996 1473
+sys/src/9/pc/pci.c - 664 sys sys 1131290505 26817
 sys/src/9/pc/pcmciamodem.c - 664 sys sys 1099761153 1586
 sys/src/9/pc/pcmkfile - 664 sys sys 1109303822 101
 sys/src/9/pc/piix4smbus.c - 664 sys sys 1091129037 5230
@@ -7997,46 +7997,47 @@ sys/src/9/pc/plan9l.s - 664 sys sys 1015014521 910
 sys/src/9/pc/psaux.c - 664 sys sys 1026847650 915
 sys/src/9/pc/ptclbsum386.s - 664 sys sys 1015014521 1493
 sys/src/9/pc/random.c - 664 sys sys 1036812832 2021
-sys/src/9/pc/reboot.h - 664 sys sys 1015014522 334
+sys/src/9/pc/realmode.c - 664 sys sys 1131294602 2658
 sys/src/9/pc/rebootcode.s - 664 sys sys 1015014522 988
-sys/src/9/pc/screen.c - 664 sys sys 1039753497 7266
-sys/src/9/pc/screen.h - 664 sys sys 1060267144 3797
-sys/src/9/pc/sd53c8xx.c - 664 sys sys 1112461125 52220
-sys/src/9/pc/sd53c8xx.i - 664 sys sys 1045063730 27355
-sys/src/9/pc/sd53c8xx.n - 664 sys sys 1032059019 12455
-sys/src/9/pc/sdata.c - 664 sys sys 1127404875 51702
-sys/src/9/pc/sdmylex.c - 664 sys sys 1071245460 27812
-sys/src/9/pc/sdscsi.c - 664 sys sys 1077033661 7487
-sys/src/9/pc/trap.c - 664 sys sys 1123438642 20550
+sys/src/9/pc/screen.c - 664 sys sys 1131290512 13460
+sys/src/9/pc/screen.h - 664 sys sys 1131290516 4156
+sys/src/9/pc/sd53c8xx.c - 664 sys sys 1131290539 55206
+sys/src/9/pc/sd53c8xx.n - 664 sys sys 1131290556 12657
+sys/src/9/pc/sdata.c - 664 sys sys 1131290578 52168
+sys/src/9/pc/sdmv50xx.c - 664 sys sys 1131290638 25780
+sys/src/9/pc/sdmylex.c - 664 sys sys 1131290583 27737
+sys/src/9/pc/sdscsi.c - 664 sys sys 1131293342 7133
+sys/src/9/pc/trap.c - 664 sys sys 1131306249 21180
 sys/src/9/pc/uarti8250.c - 664 sys sys 1102820421 13958
 sys/src/9/pc/uartisa.c - 664 sys sys 1127126907 1777
 sys/src/9/pc/uartpci.c - 664 sys sys 1096379063 2891
 sys/src/9/pc/usb.h - 664 sys sys 1099760881 3650
 sys/src/9/pc/usbuhci.c - 664 sys sys 1099760881 30955
-sys/src/9/pc/vga.c - 664 sys sys 1039753497 4963
-sys/src/9/pc/vga3dfx.c - 664 sys sys 1071247360 4867
-sys/src/9/pc/vgaark2000pv.c - 664 sys sys 1015014524 3416
-sys/src/9/pc/vgabt485.c - 664 sys sys 1015014525 5041
-sys/src/9/pc/vgaclgd542x.c - 664 sys sys 1015014525 5068
-sys/src/9/pc/vgaclgd546x.c - 664 sys sys 1071245447 4770
-sys/src/9/pc/vgact65545.c - 664 sys sys 1015014525 2243
-sys/src/9/pc/vgacyber938x.c - 664 sys sys 1015014526 4192
-sys/src/9/pc/vgaet4000.c - 664 sys sys 1015014526 5105
-sys/src/9/pc/vgahiqvideo.c - 664 sys sys 1048635701 5033
-sys/src/9/pc/vgai81x.c - 664 sys sys 1032052924 4905
-sys/src/9/pc/vgamach64xx.c - 664 sys sys 1071245447 29146
-sys/src/9/pc/vgamga2164w.c - 664 sys sys 1015014527 5654
-sys/src/9/pc/vgamga4xx.c - 664 sys sys 1015014527 11122
-sys/src/9/pc/vganeomagic.c - 664 sys sys 1104430511 11327
-sys/src/9/pc/vganvidia.c - 664 sys sys 1120909910 12617
-sys/src/9/pc/vgargb524.c - 664 sys sys 1015014527 4235
-sys/src/9/pc/vgas3.c - 664 sys sys 1090439162 12189
+sys/src/9/pc/vga.c - 664 sys sys 1131290595 5148
+sys/src/9/pc/vga3dfx.c - 664 sys sys 1131290600 3833
+sys/src/9/pc/vgaark2000pv.c - 664 sys sys 1131290600 3422
+sys/src/9/pc/vgabt485.c - 664 sys sys 1131290600 5057
+sys/src/9/pc/vgaclgd542x.c - 664 sys sys 1131290600 4550
+sys/src/9/pc/vgaclgd546x.c - 664 sys sys 1131290600 3716
+sys/src/9/pc/vgact65545.c - 664 sys sys 1131290600 2249
+sys/src/9/pc/vgacyber938x.c - 664 sys sys 1131290601 3707
+sys/src/9/pc/vgaet4000.c - 664 sys sys 1131290601 5111
+sys/src/9/pc/vgahiqvideo.c - 664 sys sys 1131290601 4098
+sys/src/9/pc/vgai81x.c - 664 sys sys 1131290601 4030
+sys/src/9/pc/vgamach64xx.c - 664 sys sys 1131290601 28257
+sys/src/9/pc/vgamga2164w.c - 664 sys sys 1131290602 4637
+sys/src/9/pc/vgamga4xx.c - 664 sys sys 1131290602 10201
+sys/src/9/pc/vganeomagic.c - 664 sys sys 1131290602 10143
+sys/src/9/pc/vganvidia.c - 664 sys sys 1131290602 11783
+sys/src/9/pc/vgargb524.c - 664 sys sys 1131290602 4251
+sys/src/9/pc/vgas3.c - 664 sys sys 1131290603 10994
 sys/src/9/pc/vgasavage.c - 664 sys sys 1064679984 16251
-sys/src/9/pc/vgat2r4.c - 664 sys sys 1015014528 10355
-sys/src/9/pc/vgatvp3020.c - 664 sys sys 1015014528 4491
-sys/src/9/pc/vgatvp3026.c - 664 sys sys 1015014528 3940
-sys/src/9/pc/vgavmware.c - 664 sys sys 1063858321 6398
-sys/src/9/pc/vgax.c - 664 sys sys 1015014528 1655
+sys/src/9/pc/vgat2r4.c - 664 sys sys 1131290603 9351
+sys/src/9/pc/vgatvp3020.c - 664 sys sys 1131290603 4507
+sys/src/9/pc/vgatvp3026.c - 664 sys sys 1131290603 3956
+sys/src/9/pc/vgavesa.c - 664 sys sys 1131290603 2369
+sys/src/9/pc/vgavmware.c - 664 sys sys 1131290604 5840
+sys/src/9/pc/vgax.c - 664 sys sys 1131290604 1671
 sys/src/9/pc/wavelan.c - 664 sys sys 1127743243 27879
 sys/src/9/pc/wavelan.h - 664 sys sys 1107448246 6169
 sys/src/9/port - 20000000775 sys sys 1018469625 0
@@ -8045,15 +8046,15 @@ sys/src/9/port/alloc.c - 664 sys sys 1130964595 5674
 sys/src/9/port/allocb.c - 664 sys sys 1123676437 3340
 sys/src/9/port/auth.c - 664 sys sys 1123647282 2392
 sys/src/9/port/cache.c - 664 sys sys 1126586168 9241
-sys/src/9/port/chan.c - 664 sys sys 1129373741 33642
+sys/src/9/port/chan.c - 664 sys sys 1131298713 33663
 sys/src/9/port/cis.c - 664 sys sys 1099761153 9248
 sys/src/9/port/debugalloc.c - 664 sys sys 1014931171 10402
-sys/src/9/port/dev.c - 664 sys sys 1126586172 8246
+sys/src/9/port/dev.c - 664 sys sys 1131289870 8219
 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 1130759309 22495
-sys/src/9/port/devdraw.c - 664 sys sys 1091733670 41996
+sys/src/9/port/devdraw.c - 664 sys sys 1131289870 43537
 sys/src/9/port/devdup.c - 664 sys sys 1014931172 2332
 sys/src/9/port/devenv.c - 664 sys sys 1048644225 6992
 sys/src/9/port/devfs.c - 664 sys sys 1105799131 10783
@@ -8065,11 +8066,11 @@ sys/src/9/port/devmntstats.c - 664 sys sys 1014931173 4039
 sys/src/9/port/devmouse.c - 664 sys sys 1130848303 13517
 sys/src/9/port/devpipe.c - 664 sys sys 1077055016 5825
 sys/src/9/port/devpnp.c - 664 sys sys 1088560907 13624
-sys/src/9/port/devproc.c - 664 sys sys 1126586197 28465
+sys/src/9/port/devproc.c - 664 sys sys 1131289878 28233
 sys/src/9/port/devroot.c - 664 sys sys 1067722764 4254
-sys/src/9/port/devsd.c - 664 sys sys 1123255503 28564
+sys/src/9/port/devsd.c - 664 sys sys 1131289885 30798
 sys/src/9/port/devsdp.c - 664 sys sys 1057323393 44800
-sys/src/9/port/devsegment.c - 664 sys sys 1017679394 9600
+sys/src/9/port/devsegment.c - 664 sys sys 1131289891 9610
 sys/src/9/port/devsrv.c - 664 sys sys 1107232208 5418
 sys/src/9/port/devssl.c - 664 sys sys 1131107944 26133
 sys/src/9/port/devtinyfs.c - 664 sys sys 1015278339 15347
@@ -8079,13 +8080,13 @@ sys/src/9/port/devwd.c - 664 sys sys 1126582325 2342
 sys/src/9/port/edf.c - 664 sys sys 1099760881 12742
 sys/src/9/port/edf.h - 664 sys sys 1084475128 1156
 sys/src/9/port/error.h - 664 sys sys 1117055493 2637
-sys/src/9/port/fault.c - 664 sys sys 1126586199 7282
+sys/src/9/port/fault.c - 664 sys sys 1131289901 7271
 sys/src/9/port/initcode.c - 664 sys sys 1055688491 574
 sys/src/9/port/latin1.c - 664 sys sys 1015278339 1418
 sys/src/9/port/latin1.h - 664 sys sys 1103633666 3563
-sys/src/9/port/lib.h - 664 sys sys 1126103560 5770
+sys/src/9/port/lib.h - 664 sys sys 1131289913 6040
 sys/src/9/port/log.c - 664 sys sys 1014931175 2860
-sys/src/9/port/master - 664 sys sys 1104430269 505
+sys/src/9/port/master - 664 sys sys 1131289934 510
 sys/src/9/port/master.local - 664 sys sys 1063856961 130
 sys/src/9/port/mkbootrules - 775 sys sys 1055700518 923
 sys/src/9/port/mkdevc - 775 sys sys 1109202243 3889
@@ -8101,41 +8102,41 @@ sys/src/9/port/mksystab - 664 sys sys 1014931176 783
 sys/src/9/port/mul64fract.c - 664 sys sys 1071671674 867
 sys/src/9/port/netif.c - 664 sys sys 1066514951 13421
 sys/src/9/port/netif.h - 664 sys sys 1066514947 2975
-sys/src/9/port/page.c - 664 sys sys 1102133425 8281
+sys/src/9/port/page.c - 664 sys sys 1131289949 8449
 sys/src/9/port/parse.c - 664 sys sys 1014931177 2026
 sys/src/9/port/pgrp.c - 664 sys sys 1072704671 3940
 sys/src/9/port/portclock.c - 664 sys sys 1102093397 4556
-sys/src/9/port/portdat.h - 664 sys sys 1127215703 22586
-sys/src/9/port/portfns.h - 664 sys sys 1126586141 11002
+sys/src/9/port/portdat.h - 664 sys sys 1131289971 22628
+sys/src/9/port/portfns.h - 664 sys sys 1131289972 10925
 sys/src/9/port/portmkfile - 664 sys sys 1124708650 2052
 sys/src/9/port/print.c - 664 sys sys 1014931178 227
-sys/src/9/port/proc.c - 664 sys sys 1099760501 28207
+sys/src/9/port/proc.c - 664 sys sys 1131289980 28264
 sys/src/9/port/qio.c - 664 sys sys 1070287837 23562
 sys/src/9/port/qlock.c - 664 sys sys 1067722765 3196
 sys/src/9/port/rdb.c - 664 sys sys 1018721202 1698
 sys/src/9/port/rebootcmd.c - 664 sys sys 1015278340 1561
-sys/src/9/port/sd.h - 664 sys sys 1098546338 2348
-sys/src/9/port/segment.c - 664 sys sys 1121259584 13761
+sys/src/9/port/sd.h - 664 sys sys 1131289990 2494
+sys/src/9/port/segment.c - 664 sys sys 1131298540 13722
 sys/src/9/port/swap.c - 664 sys sys 1055688551 6980
 sys/src/9/port/sysfile.c - 664 sys sys 1126586199 22173
-sys/src/9/port/sysproc.c - 664 sys sys 1130387080 15144
+sys/src/9/port/sysproc.c - 664 sys sys 1131298541 15159
 sys/src/9/port/systab.h - 664 sys sys 1062721698 3044
-sys/src/9/port/taslock.c - 664 sys sys 1084475129 3658
+sys/src/9/port/taslock.c - 664 sys sys 1131290039 3928
 sys/src/9/port/thwack.c - 664 sys sys 1057323394 7253
 sys/src/9/port/thwack.h - 664 sys sys 1015278340 1792
 sys/src/9/port/tod.c - 664 sys sys 1067722762 4856
 sys/src/9/port/unthwack.c - 664 sys sys 1057323394 5249
-sys/src/9/port/xalloc.c - 664 sys sys 1097074047 4030
+sys/src/9/port/xalloc.c - 664 sys sys 1131290051 4063
 sys/src/9/ppc - 20000000775 sys sys 1059490838 0
 sys/src/9/ppc/blast - 664 sys sys 1107436310 670
 sys/src/9/ppc/blast.h - 664 sys sys 1059490750 3109
-sys/src/9/ppc/clock.c - 664 sys sys 1100701675 1036
+sys/src/9/ppc/clock.c - 664 sys sys 1131290066 1076
 sys/src/9/ppc/dat.h - 664 sys sys 1127274100 4735
-sys/src/9/ppc/devether.c - 664 sys sys 1116097817 9264
+sys/src/9/ppc/devether.c - 664 sys sys 1131290184 9327
 sys/src/9/ppc/devflash.c - 664 sys sys 1059490750 19885
 sys/src/9/ppc/devirq.c - 664 sys sys 1100701675 6314
 sys/src/9/ppc/devtls.c - 664 sys sys 1059490751 43721
-sys/src/9/ppc/etherfcc.c - 664 sys sys 1100701674 19690
+sys/src/9/ppc/etherfcc.c - 664 sys sys 1131290110 19599
 sys/src/9/ppc/etherif.h - 664 sys sys 1059490751 785
 sys/src/9/ppc/ethersaturn.c - 664 sys sys 1059490751 4321
 sys/src/9/ppc/fns.h - 664 sys sys 1111851554 3095
@@ -8147,7 +8148,7 @@ 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 1123094594 14482
 sys/src/9/ppc/m8260.h - 664 sys sys 1100701674 20899
-sys/src/9/ppc/main.c - 664 sys sys 1126586256 9039
+sys/src/9/ppc/main.c - 664 sys sys 1131290117 9075
 sys/src/9/ppc/mcc.c - 664 sys sys 1059490752 9667
 sys/src/9/ppc/mem.h - 664 sys sys 1091021860 7002
 sys/src/9/ppc/mkfile - 664 sys sys 1067722849 1813
@@ -8157,9 +8158,9 @@ 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 1072705482 1737
-sys/src/9/ppc/trap.c - 664 sys sys 1105030152 18384
+sys/src/9/ppc/trap.c - 664 sys sys 1131290140 17067
 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/uartsmc.c - 664 sys sys 1131290162 9764
 sys/src/9/ppc/ucu - 664 sys sys 1067722849 672
 sys/src/9/ppc/ucu.h - 664 sys sys 1059490754 531
 sys/src/NOTICE - 444 sys sys 1018803112 63
@@ -9238,11 +9239,11 @@ sys/src/cmd/9nfs/authhostowner.c - 664 sys sys 1071498519 4190
 sys/src/cmd/9nfs/chat.c - 664 sys sys 1017337813 2096
 sys/src/cmd/9nfs/dat.h - 664 sys sys 1071498518 4406
 sys/src/cmd/9nfs/fns.h - 664 sys sys 1071498519 1908
-sys/src/cmd/9nfs/listalloc.c - 664 sys sys 1015090372 297
+sys/src/cmd/9nfs/listalloc.c - 664 sys sys 1131293679 275
 sys/src/cmd/9nfs/mkfile - 664 sys sys 1071498518 640
 sys/src/cmd/9nfs/mport.c - 664 sys sys 1050715069 3779
 sys/src/cmd/9nfs/nametest.c - 664 sys sys 1015090372 1723
-sys/src/cmd/9nfs/nfs.c - 664 sys sys 1130424013 9509
+sys/src/cmd/9nfs/nfs.c - 664 sys sys 1131293679 9526
 sys/src/cmd/9nfs/nfs.h - 664 sys sys 1015090372 642
 sys/src/cmd/9nfs/nfsmount.c - 664 sys sys 1071498520 6142
 sys/src/cmd/9nfs/nfsserver.c - 664 sys sys 1040952455 15576
@@ -9256,22 +9257,22 @@ sys/src/cmd/9nfs/strparse.c - 664 sys sys 1015090373 506
 sys/src/cmd/9nfs/system.c - 664 sys sys 1017337815 437
 sys/src/cmd/9nfs/testit - 775 sys sys 1017337816 251
 sys/src/cmd/9nfs/unixnames.c - 664 sys sys 1065963574 6006
-sys/src/cmd/9nfs/xfile.c - 664 sys sys 1017337816 1847
+sys/src/cmd/9nfs/xfile.c - 664 sys sys 1131293680 1894
 sys/src/cmd/aan.c - 664 sys sys 1019856827 9758
 sys/src/cmd/acid - 20000000775 sys sys 944960739 0
-sys/src/cmd/acid/acid.h - 664 sys sys 1127393275 4389
-sys/src/cmd/acid/builtin.c - 664 sys sys 1127214825 20156
-sys/src/cmd/acid/dbg.y - 664 sys sys 1081736447 5567
-sys/src/cmd/acid/dot.c - 664 sys sys 944960739 2161
-sys/src/cmd/acid/exec.c - 664 sys sys 1016833876 8187
-sys/src/cmd/acid/expr.c - 664 sys sys 1127393280 15220
-sys/src/cmd/acid/lex.c - 664 sys sys 1046198960 7861
-sys/src/cmd/acid/list.c - 664 sys sys 944960738 3671
-sys/src/cmd/acid/main.c - 664 sys sys 1046198959 8475
+sys/src/cmd/acid/acid.h - 664 sys sys 1131289460 4273
+sys/src/cmd/acid/builtin.c - 664 sys sys 1131289462 20193
+sys/src/cmd/acid/dbg.y - 664 sys sys 1131289463 5568
+sys/src/cmd/acid/dot.c - 664 sys sys 1131289462 2162
+sys/src/cmd/acid/exec.c - 664 sys sys 1131289461 8383
+sys/src/cmd/acid/expr.c - 664 sys sys 1131289461 15220
+sys/src/cmd/acid/lex.c - 664 sys sys 1131289460 7963
+sys/src/cmd/acid/list.c - 664 sys sys 1131289462 3680
+sys/src/cmd/acid/main.c - 664 sys sys 1131289460 8565
 sys/src/cmd/acid/mkfile - 664 sys sys 1046199006 366
-sys/src/cmd/acid/print.c - 664 sys sys 984756705 6840
-sys/src/cmd/acid/proc.c - 664 sys sys 1119470118 4602
-sys/src/cmd/acid/util.c - 664 sys sys 1127393277 4616
+sys/src/cmd/acid/print.c - 664 sys sys 1131289462 6831
+sys/src/cmd/acid/proc.c - 664 sys sys 1131289462 4356
+sys/src/cmd/acid/util.c - 664 sys sys 1131289461 4609
 sys/src/cmd/acme - 20000000775 sys sys 969511023 0
 sys/src/cmd/acme/acme.c - 664 sys sys 1104430286 19613
 sys/src/cmd/acme/addr.c - 664 sys sys 1111171698 4805
@@ -9297,7 +9298,7 @@ sys/src/cmd/acme/time.c - 664 sys sys 1014926095 1783
 sys/src/cmd/acme/util.c - 664 sys sys 1107154483 7984
 sys/src/cmd/acme/wind.c - 664 sys sys 1122526112 11233
 sys/src/cmd/acme/xfid.c - 664 sys sys 1125314186 19766
-sys/src/cmd/ar.c - 664 sys sys 1046643027 23717
+sys/src/cmd/ar.c - 664 sys sys 1131293258 23778
 sys/src/cmd/archfs.c - 664 sys sys 1014925694 3871
 sys/src/cmd/ascii.c - 664 sys sys 964457138 3989
 sys/src/cmd/astro - 20000000775 sys sys 964456342 0
@@ -9352,7 +9353,7 @@ sys/src/cmd/auth/factotum/chap.c - 664 sys sys 1107706103 8967
 sys/src/cmd/auth/factotum/confirm.c - 664 sys sys 1044829586 3103
 sys/src/cmd/auth/factotum/dat.h - 664 sys sys 1121367028 4946
 sys/src/cmd/auth/factotum/fgui.c - 664 sys sys 1130425760 15984
-sys/src/cmd/auth/factotum/fs.c - 664 sys sys 1107706104 10447
+sys/src/cmd/auth/factotum/fs.c - 664 sys sys 1131289797 10524
 sys/src/cmd/auth/factotum/log.c - 664 sys sys 1046655068 1781
 sys/src/cmd/auth/factotum/mkfile - 664 sys sys 1107706102 481
 sys/src/cmd/auth/factotum/p9any.c - 664 sys sys 1107706103 8484
@@ -9363,7 +9364,7 @@ sys/src/cmd/auth/factotum/rpc.c - 664 sys sys 1107633794 11167
 sys/src/cmd/auth/factotum/rsa.c - 664 sys sys 1107706104 3416
 sys/src/cmd/auth/factotum/secstore.c - 664 sys sys 1107633794 14935
 sys/src/cmd/auth/factotum/sshrsa.c - 664 sys sys 1107633793 3416
-sys/src/cmd/auth/factotum/util.c - 664 sys sys 1117193215 17915
+sys/src/cmd/auth/factotum/util.c - 664 sys sys 1131289797 18035
 sys/src/cmd/auth/factotum/wep.c - 664 sys sys 1107706104 2140
 sys/src/cmd/auth/guard.srv.c - 664 sys sys 1032497638 2334
 sys/src/cmd/auth/iam.c - 664 sys sys 1015008430 841
@@ -9728,8 +9729,8 @@ sys/src/cmd/cc/compat.c - 664 sys sys 1084472048 417
 sys/src/cmd/cc/dcl.c - 664 sys sys 1089299183 26723
 sys/src/cmd/cc/dpchk.c - 664 sys sys 1107365037 7152
 sys/src/cmd/cc/funct.c - 664 sys sys 984718510 6167
-sys/src/cmd/cc/lex.c - 664 sys sys 1127766297 23848
-sys/src/cmd/cc/lexbody - 664 sys sys 1127307403 9186
+sys/src/cmd/cc/lex.c - 664 sys sys 1131293446 23883
+sys/src/cmd/cc/lexbody - 664 sys sys 1131293457 9188
 sys/src/cmd/cc/mac.c - 664 sys sys 944960808 36
 sys/src/cmd/cc/macbody - 664 sys sys 1108281581 11703
 sys/src/cmd/cc/machcap.c - 664 sys sys 1084472048 78
@@ -9796,21 +9797,21 @@ sys/src/cmd/cpu.c - 664 sys sys 1123676384 21128
 sys/src/cmd/crop.c - 664 sys sys 1039753034 4136
 sys/src/cmd/date.c - 664 sys sys 944961351 449
 sys/src/cmd/db - 20000000775 sys sys 988249965 0
-sys/src/cmd/db/command.c - 664 sys sys 1121977158 4362
-sys/src/cmd/db/defs.h - 664 sys sys 1016731555 1704
-sys/src/cmd/db/expr.c - 664 sys sys 1016731556 5450
-sys/src/cmd/db/fns.h - 664 sys sys 958696023 2011
-sys/src/cmd/db/format.c - 664 sys sys 1016731556 6873
+sys/src/cmd/db/command.c - 664 sys sys 1131297926 4377
+sys/src/cmd/db/defs.h - 664 sys sys 1131292957 1700
+sys/src/cmd/db/expr.c - 664 sys sys 1131292957 5441
+sys/src/cmd/db/fns.h - 664 sys sys 1131297926 2014
+sys/src/cmd/db/format.c - 664 sys sys 1131297926 6868
 sys/src/cmd/db/input.c - 664 sys sys 1016731556 2194
 sys/src/cmd/db/main.c - 664 sys sys 1016731556 3308
 sys/src/cmd/db/mkfile - 664 sys sys 944960880 233
 sys/src/cmd/db/output.c - 664 sys sys 1014925293 2009
 sys/src/cmd/db/pcs.c - 664 sys sys 1016731557 2859
-sys/src/cmd/db/print.c - 664 sys sys 1046363143 5856
-sys/src/cmd/db/regs.c - 664 sys sys 1014925293 1998
+sys/src/cmd/db/print.c - 664 sys sys 1131297926 5949
+sys/src/cmd/db/regs.c - 664 sys sys 1131297926 1998
 sys/src/cmd/db/runpcs.c - 664 sys sys 1014925293 2929
 sys/src/cmd/db/setup.c - 664 sys sys 1014925293 3581
-sys/src/cmd/db/trcrun.c - 664 sys sys 1016731556 4432
+sys/src/cmd/db/trcrun.c - 664 sys sys 1131297926 4433
 sys/src/cmd/dc.c - 664 sys sys 1121977159 36572
 sys/src/cmd/dd.c - 664 sys sys 1126360951 11753
 sys/src/cmd/deroff.c - 664 sys sys 1017679319 14611
@@ -12131,7 +12132,7 @@ sys/src/cmd/kl/pass.c - 664 sys sys 1045503969 9348
 sys/src/cmd/kl/sched.c - 664 sys sys 1089299170 10796
 sys/src/cmd/kl/span.c - 664 sys sys 1045503970 10146
 sys/src/cmd/kprof.c - 664 sys sys 1123244004 2550
-sys/src/cmd/ktrace.c - 664 sys sys 1119276523 5785
+sys/src/cmd/ktrace.c - 664 sys sys 1131293224 5885
 sys/src/cmd/lens.c - 664 sys sys 1130425803 5109
 sys/src/cmd/lex - 20000000775 sys sys 944961017 0
 sys/src/cmd/lex/header.c - 664 sys sys 1032060383 3368
@@ -12210,31 +12211,31 @@ sys/src/cmd/mc.c - 664 sys sys 1082924484 5520
 sys/src/cmd/md5sum.c - 664 sys sys 1014926238 1009
 sys/src/cmd/mk - 20000000775 sys sys 988249988 0
 sys/src/cmd/mk/acid - 664 sys sys 1055698806 10395
-sys/src/cmd/mk/arc.c - 664 sys sys 944961024 835
-sys/src/cmd/mk/archive.c - 664 sys sys 964662348 2941
+sys/src/cmd/mk/arc.c - 664 sys sys 1131289508 826
+sys/src/cmd/mk/archive.c - 664 sys sys 1131289509 3071
 sys/src/cmd/mk/bufblock.c - 664 sys sys 944961024 1338
-sys/src/cmd/mk/env.c - 664 sys sys 944961024 2290
-sys/src/cmd/mk/file.c - 664 sys sys 1055698807 1310
+sys/src/cmd/mk/env.c - 664 sys sys 1131289509 2281
+sys/src/cmd/mk/file.c - 664 sys sys 1131289509 1299
 sys/src/cmd/mk/fns.h - 664 sys sys 1055698809 2199
-sys/src/cmd/mk/graph.c - 664 sys sys 988225293 5842
+sys/src/cmd/mk/graph.c - 664 sys sys 1131289509 5822
 sys/src/cmd/mk/job.c - 664 sys sys 944961025 692
 sys/src/cmd/mk/lex.c - 664 sys sys 944961025 2315
 sys/src/cmd/mk/main.c - 664 sys sys 1123094366 4790
 sys/src/cmd/mk/match.c - 664 sys sys 1014926073 856
-sys/src/cmd/mk/mk.c - 664 sys sys 1123676387 5348
-sys/src/cmd/mk/mk.h - 664 sys sys 1055698812 3735
+sys/src/cmd/mk/mk.c - 664 sys sys 1131289509 5330
+sys/src/cmd/mk/mk.h - 664 sys sys 1131289508 3765
 sys/src/cmd/mk/mkconv - 775 sys sys 944961025 555
 sys/src/cmd/mk/mkfile - 664 sys sys 1055698812 376
 sys/src/cmd/mk/parse.c - 664 sys sys 944961025 5310
-sys/src/cmd/mk/plan9.c - 664 sys sys 1121977161 6929
+sys/src/cmd/mk/plan9.c - 664 sys sys 1131289511 6941
 sys/src/cmd/mk/rc.c - 664 sys sys 944961025 3206
-sys/src/cmd/mk/recipe.c - 664 sys sys 1014926074 2551
-sys/src/cmd/mk/rule.c - 664 sys sys 944961025 1970
-sys/src/cmd/mk/run.c - 664 sys sys 1014926074 5080
+sys/src/cmd/mk/recipe.c - 664 sys sys 1131289510 2543
+sys/src/cmd/mk/rule.c - 664 sys sys 1131289510 1946
+sys/src/cmd/mk/run.c - 664 sys sys 1131289510 5063
 sys/src/cmd/mk/shprint.c - 664 sys sys 952627588 1515
-sys/src/cmd/mk/symtab.c - 664 sys sys 944961025 1581
-sys/src/cmd/mk/var.c - 664 sys sys 944961025 539
-sys/src/cmd/mk/varsub.c - 664 sys sys 944961025 4438
+sys/src/cmd/mk/symtab.c - 664 sys sys 1131289510 1581
+sys/src/cmd/mk/var.c - 664 sys sys 1131289510 530
+sys/src/cmd/mk/varsub.c - 664 sys sys 1131289511 4425
 sys/src/cmd/mk/word.c - 664 sys sys 944961025 2595
 sys/src/cmd/mkdir.c - 664 sys sys 1082593106 1026
 sys/src/cmd/mkfile - 664 sys sys 1108476348 2414
@@ -12275,7 +12276,7 @@ sys/src/cmd/ndb/time.c - 664 sys sys 957402055 321
 sys/src/cmd/netstat.c - 664 sys sys 1128255434 4086
 sys/src/cmd/news.c - 664 sys sys 1014926614 3778
 sys/src/cmd/nfs.c - 664 sys sys 1050068720 31096
-sys/src/cmd/nm.c - 664 sys sys 1073313392 4912
+sys/src/cmd/nm.c - 664 sys sys 1131292928 4914
 sys/src/cmd/nntpfs.c - 664 sys sys 1100524486 18920
 sys/src/cmd/ns.c - 664 sys sys 984717934 3558
 sys/src/cmd/p.c - 664 sys sys 1121977162 1504
@@ -12719,7 +12720,7 @@ sys/src/cmd/rc/tree.c - 664 sys sys 1055698780 2071
 sys/src/cmd/rc/unix.c - 664 sys sys 1055698781 8726
 sys/src/cmd/rc/var.c - 664 sys sys 1055698781 1298
 sys/src/cmd/rc/win32.c - 664 sys sys 1055698781 8699
-sys/src/cmd/rdbfs.c - 664 sys sys 1049426950 7952
+sys/src/cmd/rdbfs.c - 664 sys sys 1131289483 7964
 sys/src/cmd/read.c - 664 sys sys 1022047660 1278
 sys/src/cmd/replica - 20000000775 sys sys 1018321113 0
 sys/src/cmd/replica/all.h - 664 sys sys 1091904421 1265
@@ -12921,7 +12922,7 @@ sys/src/cmd/ssh/sshserve.c - 664 sys sys 1062091020 5786
 sys/src/cmd/ssh/util.c - 664 sys sys 1063858753 4478
 sys/src/cmd/stats.c - 664 sys sys 1127974208 28128
 sys/src/cmd/strings.c - 664 sys sys 944961364 1216
-sys/src/cmd/strip.c - 664 sys sys 1108077276 3350
+sys/src/cmd/strip.c - 664 sys sys 1131293244 2502
 sys/src/cmd/sum.c - 664 sys sys 1014926615 5548
 sys/src/cmd/swap.c - 664 sys sys 1014926662 1141
 sys/src/cmd/syscall - 20000000775 sys sys 944961236 0
@@ -12952,12 +12953,12 @@ sys/src/cmd/tbl/t2.c - 664 sys sys 944961244 298
 sys/src/cmd/tbl/t3.c - 664 sys sys 944961244 1836
 sys/src/cmd/tbl/t4.c - 664 sys sys 944961244 8360
 sys/src/cmd/tbl/t5.c - 664 sys sys 944961244 3723
-sys/src/cmd/tbl/t6.c - 664 sys sys 1014926400 7208
+sys/src/cmd/tbl/t6.c - 664 sys sys 1131293512 7295
 sys/src/cmd/tbl/t7.c - 664 sys sys 944961244 3422
-sys/src/cmd/tbl/t8.c - 664 sys sys 944961244 8959
+sys/src/cmd/tbl/t8.c - 664 sys sys 1131293517 9041
 sys/src/cmd/tbl/t9.c - 664 sys sys 944961244 1577
 sys/src/cmd/tbl/tb.c - 664 sys sys 944961244 1732
-sys/src/cmd/tbl/tc.c - 664 sys sys 944961244 1268
+sys/src/cmd/tbl/tc.c - 664 sys sys 1131293494 1274
 sys/src/cmd/tbl/te.c - 664 sys sys 944961244 1071
 sys/src/cmd/tbl/tf.c - 664 sys sys 944961244 1283
 sys/src/cmd/tbl/tg.c - 664 sys sys 1128819351 2164
@@ -13408,7 +13409,7 @@ sys/src/cmd/upas/send/tryit - 664 sys sys 944961322 584
 sys/src/cmd/upas/smtp - 20000000775 sys sys 988250017 0
 sys/src/cmd/upas/smtp/greylist.c - 664 sys sys 1091126808 6470
 sys/src/cmd/upas/smtp/mkfile - 664 sys sys 1108910002 801
-sys/src/cmd/upas/smtp/mxdial.c - 664 sys sys 1127394225 6422
+sys/src/cmd/upas/smtp/mxdial.c - 664 sys sys 1131293478 6420
 sys/src/cmd/upas/smtp/rfc822.y - 664 sys sys 1064589606 13417
 sys/src/cmd/upas/smtp/rmtdns.c - 664 sys sys 1015013150 1069
 sys/src/cmd/upas/smtp/smtp.c - 664 sys sys 1127394218 20091
@@ -13565,7 +13566,7 @@ sys/src/cmd/vi/cmd.c - 664 sys sys 944961342 9150
 sys/src/cmd/vi/float.c - 664 sys sys 944961341 12758
 sys/src/cmd/vi/icache.c - 664 sys sys 944961342 184
 sys/src/cmd/vi/mem.c - 664 sys sys 944961342 4234
-sys/src/cmd/vi/mips.h - 664 sys sys 1124229127 4836
+sys/src/cmd/vi/mips.h - 664 sys sys 1131292943 4837
 sys/src/cmd/vi/mkfile - 664 sys sys 1124229127 289
 sys/src/cmd/vi/run.c - 664 sys sys 1014926560 13214
 sys/src/cmd/vi/special.c - 664 sys sys 944961342 6723
@@ -13837,7 +13838,7 @@ sys/src/games/music/missing - 775 sys sys 1103793915 72
 sys/src/games/music/mkfile - 664 sys sys 1103793915 723
 sys/src/games/music/mkinc - 664 sys sys 1103793915 92
 sys/src/games/music/playlistfs - 20000000775 sys sys 1103794221 0
-sys/src/games/music/playlistfs/boilerplate.c - 664 sys sys 1105531426 1362
+sys/src/games/music/playlistfs/boilerplate.c - 664 sys sys 1131293384 1547
 sys/src/games/music/playlistfs/fs.c - 664 sys sys 1111504109 17985
 sys/src/games/music/playlistfs/main.c - 664 sys sys 1103793922 1636
 sys/src/games/music/playlistfs/mk.dep - 664 sys sys 1103793923 594
@@ -14538,52 +14539,52 @@ sys/src/liblex/reject.c - 664 sys sys 944961728 1000
 sys/src/liblex/yyless.c - 664 sys sys 944961728 403
 sys/src/liblex/yywrap.c - 664 sys sys 944961728 85
 sys/src/libmach - 20000000775 sys sys 969559166 0
-sys/src/libmach/0.c - 664 sys sys 1114459829 4037
+sys/src/libmach/0.c - 664 sys sys 1131289379 4080
 sys/src/libmach/0c - 20000000775 sys sys 1114459438 0
 sys/src/libmach/0c/README - 664 sys sys 1114459609 73
 sys/src/libmach/0c/ureg.h - 664 sys sys 1114459438 886
-sys/src/libmach/2.c - 664 sys sys 964540513 2034
-sys/src/libmach/2db.c - 664 sys sys 1014929543 61245
+sys/src/libmach/2.c - 664 sys sys 1131289379 2074
+sys/src/libmach/2db.c - 664 sys sys 1131289383 61298
 sys/src/libmach/2obj.c - 664 sys sys 1091732624 2335
-sys/src/libmach/5.c - 664 sys sys 984710422 1513
-sys/src/libmach/5db.c - 664 sys sys 1114218476 21530
+sys/src/libmach/5.c - 664 sys sys 1131289380 1553
+sys/src/libmach/5db.c - 664 sys sys 1131289383 21545
 sys/src/libmach/5obj.c - 664 sys sys 1091732625 2209
-sys/src/libmach/6.c - 664 sys sys 1119476887 3366
+sys/src/libmach/6.c - 664 sys sys 1131289380 3464
 sys/src/libmach/6c - 20000000775 sys sys 1123100867 0
 sys/src/libmach/6c/6.out.h - 664 sys sys 1114459480 7984
 sys/src/libmach/6obj.c - 664 sys sys 1114459831 2382
-sys/src/libmach/7.c - 664 sys sys 964540515 3267
-sys/src/libmach/7db.c - 664 sys sys 1014929543 17320
+sys/src/libmach/7.c - 664 sys sys 1131289380 3299
+sys/src/libmach/7db.c - 664 sys sys 1131289384 17330
 sys/src/libmach/7obj.c - 664 sys sys 1091732676 2367
-sys/src/libmach/8.c - 664 sys sys 964540515 2020
-sys/src/libmach/8db.c - 664 sys sys 1114459831 50189
+sys/src/libmach/8.c - 664 sys sys 1131289381 2060
+sys/src/libmach/8db.c - 664 sys sys 1131289384 50612
 sys/src/libmach/8obj.c - 664 sys sys 1091732625 2200
-sys/src/libmach/access.c - 664 sys sys 1068478065 4309
-sys/src/libmach/elf.h - 664 sys sys 1114459895 2323
-sys/src/libmach/executable.c - 664 sys sys 1119476886 15431
-sys/src/libmach/k.c - 664 sys sys 964540516 3330
-sys/src/libmach/kdb.c - 664 sys sys 1014929544 21143
+sys/src/libmach/access.c - 664 sys sys 1131289377 4588
+sys/src/libmach/elf.h - 664 sys sys 1131292881 2301
+sys/src/libmach/executable.c - 664 sys sys 1131289375 16128
+sys/src/libmach/k.c - 664 sys sys 1131289378 3370
+sys/src/libmach/kdb.c - 664 sys sys 1131289381 21161
 sys/src/libmach/kobj.c - 664 sys sys 1091732625 2217
-sys/src/libmach/machdata.c - 664 sys sys 964540516 8814
-sys/src/libmach/map.c - 664 sys sys 964540517 3053
+sys/src/libmach/machdata.c - 664 sys sys 1131289377 8799
+sys/src/libmach/map.c - 664 sys sys 1131289376 3056
 sys/src/libmach/mkfile - 664 sys sys 1114459827 467
-sys/src/libmach/obj.c - 664 sys sys 1121367249 5918
-sys/src/libmach/obj.h - 664 sys sys 964540517 603
-sys/src/libmach/q.c - 664 sys sys 1091732625 3590
-sys/src/libmach/qdb.c - 664 sys sys 1114459830 27490
+sys/src/libmach/obj.c - 664 sys sys 1131289376 5929
+sys/src/libmach/obj.h - 664 sys sys 1131292890 604
+sys/src/libmach/q.c - 664 sys sys 1131289379 3630
+sys/src/libmach/qdb.c - 664 sys sys 1131289382 27506
 sys/src/libmach/qobj.c - 664 sys sys 1091732625 2310
 sys/src/libmach/setmach.c - 664 sys sys 1119476886 2911
-sys/src/libmach/swap.c - 664 sys sys 964540518 1026
-sys/src/libmach/sym.c - 664 sys sys 1106409575 26581
-sys/src/libmach/u.c - 664 sys sys 1114459829 3396
+sys/src/libmach/swap.c - 664 sys sys 1131289376 1056
+sys/src/libmach/sym.c - 664 sys sys 1131289377 26729
+sys/src/libmach/u.c - 664 sys sys 1131289378 3436
 sys/src/libmach/uc - 20000000775 sys sys 1114459488 0
 sys/src/libmach/uc/README - 664 sys sys 1114459488 73
 sys/src/libmach/uc/u.out.h - 664 sys sys 1114459488 3137
-sys/src/libmach/udb.c - 664 sys sys 1114459830 21893
+sys/src/libmach/udb.c - 664 sys sys 1131289382 21910
 sys/src/libmach/uobj.c - 664 sys sys 1114459831 2219
-sys/src/libmach/v.c - 664 sys sys 964540518 3403
-sys/src/libmach/vcodas.c - 664 sys sys 1014929545 10253
-sys/src/libmach/vdb.c - 664 sys sys 1014929545 22248
+sys/src/libmach/v.c - 664 sys sys 1131289378 3446
+sys/src/libmach/vcodas.c - 664 sys sys 1131289385 10258
+sys/src/libmach/vdb.c - 664 sys sys 1131289381 22264
 sys/src/libmach/vobj.c - 664 sys sys 1091732625 2206
 sys/src/libmemdraw - 20000000775 sys sys 985020762 0
 sys/src/libmemdraw/alloc.c - 664 sys sys 1046640198 3234

+ 273 - 0
dist/replica/plan9.log

@@ -22568,3 +22568,276 @@
 1131210084 0 a sys/man/8/statusbar - 664 sys sys 1131209276 1199
 1131210084 1 c sys/src/cmd/aux/statusbar.c - 664 sys sys 1131209286 6025
 1131251494 0 c 386/bin/aux/statusbar - 775 sys sys 1131250131 151558
+1131287502 0 c sys/src/9/pc/ether83815.c - 664 sys sys 1131287537 23542
+1131289302 0 c sys/include/mach.h - 664 sys sys 1131289126 8586
+1131289302 1 c sys/src/libmach/0.c - 664 sys sys 1131289379 4080
+1131289302 2 c sys/src/libmach/2.c - 664 sys sys 1131289379 2074
+1131289302 3 c sys/src/libmach/2db.c - 664 sys sys 1131289383 61298
+1131289302 4 c sys/src/libmach/5.c - 664 sys sys 1131289380 1553
+1131289302 5 c sys/src/libmach/5db.c - 664 sys sys 1131289383 21545
+1131289302 6 c sys/src/libmach/6.c - 664 sys sys 1131289380 3464
+1131289302 7 c sys/src/libmach/7.c - 664 sys sys 1131289380 3299
+1131289302 8 c sys/src/libmach/7db.c - 664 sys sys 1131289384 17330
+1131289302 9 c sys/src/libmach/8.c - 664 sys sys 1131289381 2060
+1131289302 10 c sys/src/libmach/8db.c - 664 sys sys 1131289384 50612
+1131289302 11 c sys/src/libmach/access.c - 664 sys sys 1131289377 4588
+1131289302 12 c sys/src/libmach/executable.c - 664 sys sys 1131289375 16128
+1131289302 13 c sys/src/libmach/k.c - 664 sys sys 1131289378 3370
+1131289302 14 c sys/src/libmach/kdb.c - 664 sys sys 1131289381 21161
+1131289302 15 c sys/src/libmach/machdata.c - 664 sys sys 1131289377 8799
+1131289302 16 c sys/src/libmach/map.c - 664 sys sys 1131289376 3056
+1131289302 17 c sys/src/libmach/obj.c - 664 sys sys 1131289376 5929
+1131289302 18 c sys/src/libmach/q.c - 664 sys sys 1131289379 3630
+1131289302 19 c sys/src/libmach/qdb.c - 664 sys sys 1131289382 27506
+1131289302 20 c sys/src/libmach/swap.c - 664 sys sys 1131289376 1056
+1131289302 21 c sys/src/libmach/sym.c - 664 sys sys 1131289377 26729
+1131289302 22 c sys/src/libmach/u.c - 664 sys sys 1131289378 3436
+1131289302 23 c sys/src/libmach/udb.c - 664 sys sys 1131289382 21910
+1131289302 24 c sys/src/libmach/v.c - 664 sys sys 1131289378 3446
+1131289302 25 c sys/src/libmach/vcodas.c - 664 sys sys 1131289385 10258
+1131289302 26 c sys/src/libmach/vdb.c - 664 sys sys 1131289381 22264
+1131291103 0 c 386/lib/libmach.a - 664 sys sys 1131289375 784878
+1131291103 1 c sys/lib/acid/leak - 664 sys sys 1131289472 2363
+1131291103 2 c sys/src/9/alphapc/apc - 664 sys sys 1131289706 630
+1131291103 3 c sys/src/9/alphapc/dat.h - 664 sys sys 1131289707 5196
+1131291103 4 c sys/src/9/alphapc/devvga.c - 664 sys sys 1131289707 7420
+1131291103 5 c sys/src/9/alphapc/fns.h - 664 sys sys 1131289707 3613
+1131291103 6 c sys/src/9/alphapc/main.c - 664 sys sys 1131289707 13672
+1131291103 7 c sys/src/9/alphapc/mmu.c - 664 sys sys 1131289708 4945
+1131291103 8 c sys/src/9/alphapc/screen.h - 664 sys sys 1131289708 3818
+1131291103 9 c sys/src/9/alphapc/sd53c8xx.c - 664 sys sys 1131289709 50963
+1131291103 10 c sys/src/9/bitsy/dat.h - 664 sys sys 1131289775 5829
+1131291103 11 c sys/src/9/bitsy/devpenmouse.c - 664 sys sys 1131289775 9589
+1131291103 12 c sys/src/9/bitsy/main.c - 664 sys sys 1131289775 8816
+1131291103 13 c sys/src/9/bitsy/mkfile - 664 sys sys 1131289775 2459
+1131291103 14 c sys/src/9/bitsy/sdata.c - 664 sys sys 1131289776 44404
+1131291103 15 c sys/src/9/boot/bootauth.c - 664 sys sys 1131289783 1160
+1131291103 16 c sys/src/9/mtx/dat.h - 664 sys sys 1131289814 3843
+1131291103 17 c sys/src/9/mtx/main.c - 664 sys sys 1131289814 8307
+1131291103 18 c sys/src/9/pc/apic.c - 664 sys sys 1131290206 8748
+1131291103 19 c sys/src/9/pc/apm.c - 664 sys sys 1131290210 3723
+1131291103 20 c sys/src/9/pc/archmp.c - 664 sys sys 1131290214 2357
+1131291103 21 c sys/src/9/pc/dat.h - 664 sys sys 1131290217 6462
+1131291103 22 c sys/src/9/pc/devarch.c - 664 sys sys 1131290259 18594
+1131291103 23 c sys/src/9/pc/devether.c - 664 sys sys 1131290265 10315
+1131291103 24 c sys/src/9/pc/devpccard.c - 664 sys sys 1131290281 40203
+1131291103 25 c sys/src/9/pc/devtv.c - 664 sys sys 1131290299 45676
+1131291103 26 c sys/src/9/pc/devvga.c - 664 sys sys 1131290315 9332
+1131291103 27 c sys/src/9/pc/dma.c - 664 sys sys 1131290319 4715
+1131291103 28 c sys/src/9/pc/ether79c970.c - 664 sys sys 1131290338 13953
+1131291103 29 c sys/src/9/pc/ether8139.c - 664 sys sys 1131290376 18400
+1131291103 30 c sys/src/9/pc/ether82543gc.c - 664 sys sys 1131290377 32294
+1131291103 31 c sys/src/9/pc/ether82557.c - 664 sys sys 1131290377 30107
+1131291103 32 c sys/src/9/pc/ether8390.c - 664 sys sys 1131290377 17702
+1131291103 33 c sys/src/9/pc/etherelnk3.c - 664 sys sys 1131290378 48733
+1131291103 34 c sys/src/9/pc/etherigbe.c - 664 sys sys 1131290379 44431
+1131291103 35 c sys/src/9/pc/etherwavelan.c - 664 sys sys 1131290380 3747
+1131291103 36 c sys/src/9/pc/fns.h - 664 sys sys 1131290383 4461
+1131291103 37 c sys/src/9/pc/i8259.c - 664 sys sys 1131290399 4586
+1131291103 38 c sys/src/9/pc/l.s - 664 sys sys 1131290403 28347
+1131291103 39 c sys/src/9/pc/main.c - 664 sys sys 1131290418 15224
+1131291103 40 c sys/src/9/pc/mem.h - 664 sys sys 1131290422 5209
+1131291103 41 c sys/src/9/pc/memory.c - 664 sys sys 1131290429 18222
+1131291103 42 c sys/src/9/pc/mmu.c - 664 sys sys 1131290443 19717
+1131291103 43 c sys/src/9/pc/mp.c - 664 sys sys 1131290473 17089
+1131291103 44 c sys/src/9/pc/mp.h - 664 sys sys 1131290475 6638
+1131291103 45 c sys/src/9/pc/pc - 664 sys sys 1131290481 1427
+1131291103 46 c sys/src/9/pc/pcauth - 664 sys sys 1131290482 714
+1131291103 47 c sys/src/9/pc/pccpu - 664 sys sys 1131290488 866
+1131291103 48 c sys/src/9/pc/pcdisk - 664 sys sys 1131290495 1437
+1131291103 49 c sys/src/9/pc/pcf - 664 sys sys 1131290500 1495
+1131291103 50 c sys/src/9/pc/pci.c - 664 sys sys 1131290505 26817
+1131291103 51 c sys/src/9/pc/screen.c - 664 sys sys 1131290512 13460
+1131291103 52 c sys/src/9/pc/screen.h - 664 sys sys 1131290516 4156
+1131291103 53 c sys/src/9/pc/sd53c8xx.c - 664 sys sys 1131290539 55206
+1131291103 54 c sys/src/9/pc/sd53c8xx.n - 664 sys sys 1131290556 12657
+1131291103 55 c sys/src/9/pc/sdata.c - 664 sys sys 1131290578 52168
+1131291103 56 c sys/src/9/pc/sdmylex.c - 664 sys sys 1131290583 27737
+1131291103 57 c sys/src/9/pc/trap.c - 664 sys sys 1131290591 21164
+1131291103 58 c sys/src/9/pc/vgai81x.c - 664 sys sys 1131290601 4030
+1131291103 59 a sys/src/9/pc/vgavesa.c - 664 sys sys 1131290603 2369
+1131291103 60 c sys/src/9/pc/devlml.c - 664 sys sys 1131290276 7505
+1131291103 61 c sys/src/9/pc/ether8169.c - 664 sys sys 1131290377 22723
+1131291103 62 c sys/src/9/pc/etherdp83820.c - 664 sys sys 1131290378 29128
+1131291103 63 c sys/src/9/pc/etherga620.c - 664 sys sys 1131290379 28748
+1131291103 64 c sys/src/9/pc/ethervt6102.c - 664 sys sys 1131290379 22572
+1131291103 65 c sys/src/9/pc/pccd - 664 sys sys 1131290486 1418
+1131291103 66 c sys/src/9/pc/pccpuf - 664 sys sys 1131290495 1477
+1131291103 67 c sys/src/9/pc/pcflop - 664 sys sys 1131290502 1464
+1131291103 68 a sys/src/9/pc/sdmv50xx.c - 664 sys sys 1131290638 25780
+1131291103 69 c sys/src/9/pc/vga.c - 664 sys sys 1131290595 5148
+1131291103 70 c sys/src/9/pc/vga3dfx.c - 664 sys sys 1131290600 3833
+1131291103 71 c sys/src/9/pc/vgaark2000pv.c - 664 sys sys 1131290600 3422
+1131291103 72 c sys/src/9/pc/vgabt485.c - 664 sys sys 1131290600 5057
+1131291103 73 c sys/src/9/pc/vgaclgd542x.c - 664 sys sys 1131290600 4550
+1131291103 74 c sys/src/9/pc/vgaclgd546x.c - 664 sys sys 1131290600 3716
+1131291103 75 c sys/src/9/pc/vgact65545.c - 664 sys sys 1131290600 2249
+1131291103 76 c sys/src/9/pc/vgacyber938x.c - 664 sys sys 1131290601 3707
+1131291103 77 c sys/src/9/pc/vgaet4000.c - 664 sys sys 1131290601 5111
+1131291103 78 c sys/src/9/pc/vgahiqvideo.c - 664 sys sys 1131290601 4098
+1131291103 79 c sys/src/9/pc/vgamach64xx.c - 664 sys sys 1131290601 28257
+1131291103 80 c sys/src/9/pc/vgamga2164w.c - 664 sys sys 1131290602 4637
+1131291103 81 c sys/src/9/pc/vgamga4xx.c - 664 sys sys 1131290602 10201
+1131291103 82 c sys/src/9/pc/vganeomagic.c - 664 sys sys 1131290602 10143
+1131291103 83 c sys/src/9/pc/vganvidia.c - 664 sys sys 1131290602 11783
+1131291103 84 c sys/src/9/pc/vgargb524.c - 664 sys sys 1131290602 4251
+1131291103 85 c sys/src/9/pc/vgas3.c - 664 sys sys 1131290603 10994
+1131291103 86 c sys/src/9/pc/vgat2r4.c - 664 sys sys 1131290603 9351
+1131291103 87 c sys/src/9/pc/vgatvp3020.c - 664 sys sys 1131290603 4507
+1131291103 88 c sys/src/9/pc/vgatvp3026.c - 664 sys sys 1131290603 3956
+1131291103 89 c sys/src/9/pc/vgavmware.c - 664 sys sys 1131290604 5840
+1131291103 90 c sys/src/9/pc/vgax.c - 664 sys sys 1131290604 1671
+1131291103 91 c sys/src/9/port/dev.c - 664 sys sys 1131289870 8219
+1131291103 92 c sys/src/9/port/devdraw.c - 664 sys sys 1131289870 43537
+1131291103 93 c sys/src/9/port/devproc.c - 664 sys sys 1131289878 28233
+1131291103 94 c sys/src/9/port/devsd.c - 664 sys sys 1131289885 30798
+1131291103 95 c sys/src/9/port/devsegment.c - 664 sys sys 1131289891 9610
+1131291103 96 c sys/src/9/port/fault.c - 664 sys sys 1131289901 7271
+1131291103 97 c sys/src/9/port/lib.h - 664 sys sys 1131289913 6040
+1131291103 98 c sys/src/9/port/master - 664 sys sys 1131289934 510
+1131291103 99 c sys/src/9/port/page.c - 664 sys sys 1131289949 8449
+1131291103 100 c sys/src/9/port/portdat.h - 664 sys sys 1131289971 22628
+1131291103 101 c sys/src/9/port/portfns.h - 664 sys sys 1131289972 10925
+1131291103 102 c sys/src/9/port/proc.c - 664 sys sys 1131289980 28264
+1131291103 103 c sys/src/9/port/sd.h - 664 sys sys 1131289990 2494
+1131291103 104 c sys/src/9/port/segment.c - 664 sys sys 1131290022 13720
+1131291103 105 c sys/src/9/port/taslock.c - 664 sys sys 1131290039 3928
+1131291103 106 c sys/src/9/port/xalloc.c - 664 sys sys 1131290051 4063
+1131291103 107 c sys/src/9/ppc/clock.c - 664 sys sys 1131290066 1076
+1131291103 108 c sys/src/9/ppc/devether.c - 664 sys sys 1131290184 9327
+1131291103 109 c sys/src/9/ppc/etherfcc.c - 664 sys sys 1131290110 19599
+1131291103 110 c sys/src/9/ppc/main.c - 664 sys sys 1131290117 9075
+1131291103 111 c sys/src/9/ppc/trap.c - 664 sys sys 1131290140 17067
+1131291103 112 c sys/src/9/ppc/uartsmc.c - 664 sys sys 1131290162 9764
+1131291103 113 c sys/src/cmd/acid/acid.h - 664 sys sys 1131289460 4273
+1131291103 114 c sys/src/cmd/acid/builtin.c - 664 sys sys 1131289462 20193
+1131291103 115 c sys/src/cmd/acid/dbg.y - 664 sys sys 1131289463 5568
+1131291103 116 c sys/src/cmd/acid/dot.c - 664 sys sys 1131289462 2162
+1131291103 117 c sys/src/cmd/acid/exec.c - 664 sys sys 1131289461 8383
+1131291103 118 c sys/src/cmd/acid/expr.c - 664 sys sys 1131289461 15220
+1131291103 119 c sys/src/cmd/acid/lex.c - 664 sys sys 1131289460 7963
+1131291103 120 c sys/src/cmd/acid/list.c - 664 sys sys 1131289462 3680
+1131291103 121 c sys/src/cmd/acid/main.c - 664 sys sys 1131289460 8565
+1131291103 122 c sys/src/cmd/acid/print.c - 664 sys sys 1131289462 6831
+1131291103 123 c sys/src/cmd/acid/proc.c - 664 sys sys 1131289462 4356
+1131291103 124 c sys/src/cmd/acid/util.c - 664 sys sys 1131289461 4609
+1131291103 125 c sys/src/cmd/auth/factotum/fs.c - 664 sys sys 1131289797 10524
+1131291103 126 c sys/src/cmd/auth/factotum/util.c - 664 sys sys 1131289797 18035
+1131291103 127 c sys/src/cmd/mk/arc.c - 664 sys sys 1131289508 826
+1131291103 128 c sys/src/cmd/mk/archive.c - 664 sys sys 1131289509 3071
+1131291103 129 c sys/src/cmd/mk/env.c - 664 sys sys 1131289509 2281
+1131291103 130 c sys/src/cmd/mk/file.c - 664 sys sys 1131289509 1299
+1131291103 131 c sys/src/cmd/mk/graph.c - 664 sys sys 1131289509 5822
+1131291103 132 c sys/src/cmd/mk/mk.c - 664 sys sys 1131289509 5330
+1131291103 133 c sys/src/cmd/mk/mk.h - 664 sys sys 1131289508 3765
+1131291103 134 c sys/src/cmd/mk/plan9.c - 664 sys sys 1131289511 6941
+1131291103 135 c sys/src/cmd/mk/recipe.c - 664 sys sys 1131289510 2543
+1131291103 136 c sys/src/cmd/mk/rule.c - 664 sys sys 1131289510 1946
+1131291103 137 c sys/src/cmd/mk/run.c - 664 sys sys 1131289510 5063
+1131291103 138 c sys/src/cmd/mk/symtab.c - 664 sys sys 1131289510 1581
+1131291103 139 c sys/src/cmd/mk/var.c - 664 sys sys 1131289510 530
+1131291103 140 c sys/src/cmd/mk/varsub.c - 664 sys sys 1131289511 4425
+1131291103 141 c sys/src/cmd/rdbfs.c - 664 sys sys 1131289483 7964
+1131291103 142 d sys/src/9/pc/sd53c8xx.i - 664 sys sys 1045063730 0
+1131291103 143 d sys/src/9/pc/reboot.h - 664 sys sys 1015014522 0
+1131292903 0 c sys/src/cmd/db/command.c - 664 sys sys 1131292957 4376
+1131292903 1 c sys/src/cmd/db/defs.h - 664 sys sys 1131292957 1700
+1131292903 2 c sys/src/cmd/db/expr.c - 664 sys sys 1131292957 5441
+1131292903 3 c sys/src/cmd/db/fns.h - 664 sys sys 1131292957 2078
+1131292903 4 c sys/src/cmd/db/format.c - 664 sys sys 1131292958 6874
+1131292903 5 c sys/src/cmd/db/print.c - 664 sys sys 1131292958 5959
+1131292903 6 c sys/src/cmd/db/regs.c - 664 sys sys 1131292958 1993
+1131292903 7 c sys/src/cmd/db/trcrun.c - 664 sys sys 1131292958 4434
+1131292903 8 c sys/src/cmd/vi/mips.h - 664 sys sys 1131292943 4837
+1131292903 9 c sys/src/cmd/nm.c - 664 sys sys 1131292928 4914
+1131292903 10 c sys/src/libmach/elf.h - 664 sys sys 1131292881 2301
+1131292903 11 c sys/src/libmach/obj.h - 664 sys sys 1131292890 604
+1131294703 0 c sys/include/a.out.h - 664 sys sys 1131293220 1407
+1131294703 1 c sys/man/1/strip - 664 sys sys 1131293239 523
+1131294703 2 c sys/man/4/factotum - 664 sys sys 1131294573 14841
+1131294703 3 c sys/man/8/plan9.ini - 664 sys sys 1131294569 22077
+1131294703 4 c sys/src/9/pc/apbootstrap.s - 664 sys sys 1131293655 3037
+1131294703 5 c sys/src/9/pc/sdscsi.c - 664 sys sys 1131293342 7133
+1131294703 6 a sys/src/9/pc/realmode.c - 664 sys sys 1131294602 2658
+1131294703 7 c sys/src/9/port/sysproc.c - 664 sys sys 1131293739 15150
+1131294703 8 c sys/src/cmd/9nfs/listalloc.c - 664 sys sys 1131293679 275
+1131294703 9 c sys/src/cmd/9nfs/nfs.c - 664 sys sys 1131293679 9526
+1131294703 10 c sys/src/cmd/9nfs/xfile.c - 664 sys sys 1131293680 1894
+1131294703 11 c sys/src/cmd/cc/lex.c - 664 sys sys 1131293446 23883
+1131294703 12 c sys/src/cmd/cc/lexbody - 664 sys sys 1131293457 9188
+1131294703 13 c sys/src/cmd/ktrace.c - 664 sys sys 1131293224 5885
+1131294703 14 c sys/src/cmd/tbl/t6.c - 664 sys sys 1131293512 7295
+1131294703 15 c sys/src/cmd/tbl/t8.c - 664 sys sys 1131293517 9041
+1131294703 16 c sys/src/cmd/tbl/tc.c - 664 sys sys 1131293494 1274
+1131294703 17 c sys/src/cmd/upas/smtp/mxdial.c - 664 sys sys 1131293478 6420
+1131294703 18 c sys/src/cmd/ar.c - 664 sys sys 1131293258 23778
+1131294703 19 c sys/src/cmd/strip.c - 664 sys sys 1131293244 2502
+1131294703 20 c sys/src/games/music/playlistfs/boilerplate.c - 664 sys sys 1131293384 1547
+1131296504 0 c sys/src/9/pc/mkfile - 664 sys sys 1131294850 3580
+1131298304 0 c 386/bin/8c - 775 sys sys 1131296671 358395
+1131298304 1 c 386/bin/acid - 775 sys sys 1131296672 400034
+1131298304 2 c 386/bin/ar - 775 sys sys 1131296672 111983
+1131298304 3 c 386/bin/file - 775 sys sys 1131296674 121021
+1131298304 4 c 386/bin/kprof - 775 sys sys 1131296675 105507
+1131298304 5 c 386/bin/ktrace - 775 sys sys 1131296675 121949
+1131298304 6 c 386/bin/nm - 775 sys sys 1131296675 125784
+1131298304 7 c 386/bin/prof - 775 sys sys 1131296676 110924
+1131298304 8 c 386/bin/size - 775 sys sys 1131296676 78794
+1131298304 9 c 386/bin/strip - 775 sys sys 1131296676 80766
+1131298304 10 c 386/bin/auth/factotum - 775 sys sys 1131296673 313125
+1131298304 11 c 386/bin/aux/ms2 - 775 sys sys 1131296673 87464
+1131298304 12 c 386/bin/aux/nfsserver - 775 sys sys 1131296673 185439
+1131298304 13 c 386/bin/aux/pcnfsd - 775 sys sys 1131296674 129365
+1131298304 14 c 386/bin/aux/portmapper - 775 sys sys 1131296674 128251
+1131298304 15 c 386/bin/tprof - 775 sys sys 1131296677 297344
+1131298304 16 c 386/lib/libmach.a - 664 sys sys 1131296679 782950
+1131298304 17 c sys/src/cmd/db/command.c - 664 sys sys 1131297926 4377
+1131298304 18 c sys/src/cmd/db/fns.h - 664 sys sys 1131297926 2014
+1131298304 19 c sys/src/cmd/db/format.c - 664 sys sys 1131297926 6868
+1131298304 20 c sys/src/cmd/db/print.c - 664 sys sys 1131297926 5949
+1131298304 21 c sys/src/cmd/db/regs.c - 664 sys sys 1131297926 1998
+1131298304 22 c sys/src/cmd/db/trcrun.c - 664 sys sys 1131297926 4433
+1131298818 0 c sys/src/9/port/chan.c - 664 sys sys 1131298713 33663
+1131298818 1 c sys/src/9/port/segment.c - 664 sys sys 1131298540 13722
+1131298818 2 c sys/src/9/port/sysproc.c - 664 sys sys 1131298541 15159
+1131300105 0 c sys/src/9/pc/pcdisk - 664 sys sys 1131299995 1446
+1131300105 1 c sys/src/9/pc/pcf - 664 sys sys 1131299996 1504
+1131300105 2 c sys/src/9/pc/pccpuf - 664 sys sys 1131299996 1486
+1131300105 3 c sys/src/9/pc/pcflop - 664 sys sys 1131299996 1473
+1131301905 0 c sys/man/3/vga - 664 sys sys 1131301005 4957
+1131301905 1 c sys/man/8/vga - 664 sys sys 1131301001 3864
+1131303706 0 c 386/bin/db - 775 sys sys 1131302428 345503
+1131303706 1 c 386/bin/snap - 775 sys sys 1131302429 310917
+1131303706 2 c 386/bin/snapfs - 775 sys sys 1131302430 380175
+1131303706 3 c 386/bin/mk - 775 sys sys 1131302428 144690
+1131303706 4 c 386/bin/tbl - 775 sys sys 1131302431 113308
+1131307305 0 c sys/src/9/pc/trap.c - 664 sys sys 1131306249 21180
+1131318109 0 c 386/9load - 775 sys sys 1131317303 216948
+1131318109 1 c 386/9loaddebug - 775 sys sys 1131317308 311884
+1131318109 2 c 386/9loadlite - 775 sys sys 1131317306 135668
+1131318109 3 c 386/9loadlitedebug - 775 sys sys 1131317312 200131
+1131318109 4 c 386/9pc - 775 sys sys 1131317330 1881476
+1131318109 5 c 386/9pc.gz - 664 sys sys 1131317332 658770
+1131318109 6 c 386/9pccpu - 775 sys sys 1131317349 1555752
+1131318109 7 c 386/9pccpu.gz - 664 sys sys 1131317351 552557
+1131318109 8 c 386/9pcdisk - 775 sys sys 1131317356 2072467
+1131318109 9 c 386/9pcdisk.gz - 664 sys sys 1131317358 746873
+1131318109 10 c 386/9pcf - 775 sys sys 1131317362 2415556
+1131318109 11 c 386/9pcf.gz - 664 sys sys 1131317364 900937
+1131318109 12 c 386/9pxeload - 775 sys sys 1131317321 216948
+1131318109 13 c 386/init - 775 sys sys 1131317332 101212
+1131318109 14 c 386/ld.com - 775 sys sys 1131317344 72524
+1131318109 15 c 386/mbr - 775 sys sys 1131317338 407
+1131318109 16 c 386/pbs - 775 sys sys 1131317339 494
+1131318109 17 c 386/pbslba - 775 sys sys 1131317342 507
+1131318109 18 c sys/man/8/statusbar - 664 sys sys 1131317865 1251
+1131326298 0 c sys/src/9/pc/mmu.c - 664 sys sys 1131326224 19739
+1131326298 1 c sys/src/9/pc/mp.c - 664 sys sys 1131326235 17157
+1131327235 0 c 386/9pc - 775 sys sys 1131327135 1881573
+1131327235 1 c 386/9pc.gz - 664 sys sys 1131327137 658788
+1131327235 2 c 386/9pccpu - 775 sys sys 1131327140 1555849
+1131327235 3 c 386/9pccpu.gz - 664 sys sys 1131327141 552578
+1131327235 4 c 386/9pcdisk - 775 sys sys 1131327146 2072564
+1131327235 5 c 386/9pcdisk.gz - 664 sys sys 1131327148 746868
+1131327235 6 c 386/9pcf - 775 sys sys 1131327153 2415653
+1131327235 7 c 386/9pcf.gz - 664 sys sys 1131327156 900998

+ 22 - 19
sys/include/a.out.h

@@ -11,31 +11,34 @@ struct	Exec
 	long	pcsz;		/* size of pc/line number table */
 };
 
-#define	_MAGIC(b)	((((4*b)+0)*b)+7)
-#define	A_MAGIC		_MAGIC(8)	/* 68020 */
-#define	I_MAGIC		_MAGIC(11)	/* intel 386 */
-#define	J_MAGIC		_MAGIC(12)	/* intel 960 (retired) */
-#define	K_MAGIC		_MAGIC(13)	/* sparc */
-#define	V_MAGIC		_MAGIC(16)	/* mips 3000 BE */
-#define	X_MAGIC		_MAGIC(17)	/* att dsp 3210 (retired) */
-#define	M_MAGIC		_MAGIC(18)	/* mips 4000 BE */
-#define	D_MAGIC		_MAGIC(19)	/* amd 29000 (retired) */
-#define	E_MAGIC		_MAGIC(20)	/* arm */
-#define	Q_MAGIC		_MAGIC(21)	/* powerpc */
-#define	N_MAGIC		_MAGIC(22)	/* mips 4000 LE */
-#define	L_MAGIC		_MAGIC(23)	/* dec alpha */
-#define	P_MAGIC		_MAGIC(24)	/* mips 3000 LE */
-#define	U_MAGIC		_MAGIC(25)	/* sparc64 */
-#define	S_MAGIC		_MAGIC(26)	/* amd64 */
+#define HDR_MAGIC	0x00008000		/* header expansion */
+
+#define	_MAGIC(f, b)	((f)|((((4*(b))+0)*(b))+7))
+#define	A_MAGIC		_MAGIC(0, 8)		/* 68020 */
+#define	I_MAGIC		_MAGIC(0, 11)		/* intel 386 */
+#define	J_MAGIC		_MAGIC(0, 12)		/* intel 960 (retired) */
+#define	K_MAGIC		_MAGIC(0, 13)		/* sparc */
+#define	V_MAGIC		_MAGIC(0, 16)		/* mips 3000 BE */
+#define	X_MAGIC		_MAGIC(0, 17)		/* att dsp 3210 (retired) */
+#define	M_MAGIC		_MAGIC(0, 18)		/* mips 4000 BE */
+#define	D_MAGIC		_MAGIC(0, 19)		/* amd 29000 (retired) */
+#define	E_MAGIC		_MAGIC(0, 20)		/* arm */
+#define	Q_MAGIC		_MAGIC(0, 21)		/* powerpc */
+#define	N_MAGIC		_MAGIC(0, 22)		/* mips 4000 LE */
+#define	L_MAGIC		_MAGIC(0, 23)		/* dec alpha */
+#define	P_MAGIC		_MAGIC(0, 24)		/* mips 3000 LE */
+#define	U_MAGIC		_MAGIC(0, 25)		/* sparc64 */
+#define	S_MAGIC		_MAGIC(HDR_MAGIC, 26)	/* amd64 */
+
 #define	MIN_MAGIC	8
-#define	MAX_MAGIC	26
+#define	MAX_MAGIC	26			/* <= 90 */
 
-#define	DYN_MAGIC	0x80000000	/* or'd in for dynamically loaded modules */
+#define	DYN_MAGIC	0x80000000		/* dlm */
 
 typedef	struct	Sym	Sym;
 struct	Sym
 {
-	long	value;
+	vlong	value;
 	char	type;
 	char	*name;
 };

+ 59 - 55
sys/include/mach.h

@@ -119,9 +119,9 @@ struct Map {
 		int	fd;		/* file descriptor */
 		int	inuse;		/* in use - not in use */
 		int	cache;		/* should cache reads? */
-		ulong	b;		/* base */
-		ulong	e;		/* end */
-		ulong	f;		/* offset within file */
+		uvlong	b;		/* base */
+		uvlong	e;		/* end */
+		vlong	f;		/* offset within file */
 	} seg[1];			/* actually n of these */
 };
 
@@ -169,8 +169,8 @@ struct Mach{
 	char	*name;
 	int	mtype;			/* machine type code */
 	Reglist *reglist;		/* register set */
-	ulong	regsize;		/* sizeof registers in bytes*/
-	ulong	fpregsize;		/* sizeof fp registers in bytes*/
+	long	regsize;		/* sizeof registers in bytes */
+	long	fpregsize;		/* sizeof fp registers in bytes */
 	char	*pc;			/* pc name */
 	char	*sp;			/* sp name */
 	char	*link;			/* link register name */
@@ -179,6 +179,7 @@ struct Mach{
 	int	pgsize;			/* page size */
 	uvlong	kbase;			/* kernel base address */
 	uvlong	ktmask;			/* ktzero = kbase & ~ktmask */
+	uvlong	utop;			/* user stack top */
 	int	pcquant;		/* quantization of pc */
 	int	szaddr;			/* sizeof(void*) */
 	int	szreg;			/* sizeof(register) */
@@ -188,26 +189,26 @@ struct Mach{
 
 extern	Mach	*mach;			/* Current machine */
 
-typedef vlong	(*Rgetter)(Map*, char*);
-typedef	void	(*Tracer)(Map*, ulong, ulong, Symbol*);
+typedef uvlong	(*Rgetter)(Map*, char*);
+typedef	void	(*Tracer)(Map*, uvlong, uvlong, Symbol*);
 
 struct	Machdata {		/* Machine-dependent debugger support */
 	uchar	bpinst[4];			/* break point instr. */
 	short	bpsize;				/* size of break point instr. */
 
-	ushort	(*swab)(ushort);		/* short to local byte order */
-	long	(*swal)(long);			/* long to local byte order */
-	vlong	(*swav)(vlong);			/* vlong to local byte order */
-	int	(*ctrace)(Map*, ulong, ulong, ulong, Tracer); /* C traceback */
-	ulong	(*findframe)(Map*, ulong, ulong, ulong, ulong);/* frame finder */
+	ushort	(*swab)(ushort);		/* ushort to local byte order */
+	ulong	(*swal)(ulong);			/* ulong to local byte order */
+	uvlong	(*swav)(uvlong);		/* uvlong to local byte order */
+	int	(*ctrace)(Map*, uvlong, uvlong, uvlong, Tracer); /* C traceback */
+	uvlong	(*findframe)(Map*, uvlong, uvlong, uvlong, uvlong);/* frame finder */
 	char*	(*excep)(Map*, Rgetter);	/* last exception */
-	ulong	(*bpfix)(ulong);		/* breakpoint fixup */
+	ulong	(*bpfix)(uvlong);		/* breakpoint fixup */
 	int	(*sftos)(char*, int, void*);	/* single precision float */
 	int	(*dftos)(char*, int, void*);	/* double precision float */
-	int	(*foll)(Map*, ulong, Rgetter, ulong*);	/* follow set */
-	int	(*das)(Map*, ulong, char, char*, int);	/* symbolic disassembly */
-	int	(*hexinst)(Map*, ulong, char*, int); 	/* hex disassembly */
-	int	(*instsize)(Map*, ulong);	/* instruction size */
+	int	(*foll)(Map*, uvlong, Rgetter, uvlong*);/* follow set */
+	int	(*das)(Map*, uvlong, char, char*, int);	/* symbolic disassembly */
+	int	(*hexinst)(Map*, uvlong, char*, int); 	/* hex disassembly */
+	int	(*instsize)(Map*, uvlong);	/* instruction size */
 };
 
 /*
@@ -216,23 +217,24 @@ struct	Machdata {		/* Machine-dependent debugger support */
 typedef struct Fhdr
 {
 	char	*name;		/* identifier of executable */
-	short	type;		/* file type - see codes above*/
-	short	hdrsz;		/* size of this header */
+	uchar	type;		/* file type - see codes above*/
+	uchar	hdrsz;		/* header size */
+	uchar	spare[2];
 	long	magic;		/* magic number */
-	long	txtaddr;	/* text address */
-	long	entry;		/* entry point */
+	uvlong	txtaddr;	/* text address */
+	vlong	txtoff;		/* start of text in file */
+	uvlong	dataddr;	/* start of data segment */
+	vlong	datoff;		/* offset to data seg in file */
+	vlong	symoff;		/* offset of symbol table in file */
+	uvlong	entry;		/* entry point */
+	vlong	sppcoff;	/* offset of sp-pc table in file */
+	vlong	lnpcoff;	/* offset of line number-pc table in file */
 	long	txtsz;		/* text size */
-	long	txtoff;		/* start of text in file */
-	long	dataddr;	/* start of data segment */
 	long	datsz;		/* size of data seg */
-	long	datoff;		/* offset to data seg in file */
 	long	bsssz;		/* size of bss */
 	long	symsz;		/* size of symbol table */
-	long	symoff;		/* offset of symbol table in file */
 	long	sppcsz;		/* size of sp-pc table */
-	long	sppcoff;	/* offset of sp-pc table in file */
 	long	lnpcsz;		/* size of line number-pc table */
-	long	lnpcoff;	/* size of line number-pc table */
 } Fhdr;
 
 extern	int	asstype;	/* dissembler type - machdata.c */
@@ -243,24 +245,25 @@ int		beieee80ftos(char*, int, void*);
 int		beieeesftos(char*, int, void*);
 int		beieeedftos(char*, int, void*);
 ushort		beswab(ushort);
-long		beswal(long);
-vlong		beswav(vlong);
-int		cisctrace(Map*, ulong, ulong, ulong, Tracer);
-ulong		ciscframe(Map*, ulong, ulong, ulong, ulong);
+ulong		beswal(ulong);
+uvlong		beswav(uvlong);
+uvlong		ciscframe(Map*, uvlong, uvlong, uvlong, uvlong);
+int		cisctrace(Map*, uvlong, uvlong, uvlong, Tracer);
 int		crackhdr(int fd, Fhdr*);
-long		file2pc(char*, ulong);
+uvlong		file2pc(char*, long);
 int		fileelem(Sym**, uchar *, char*, int);
-int		fileline(char*, int, ulong);
+long		fileline(char*, int, uvlong);
 int		filesym(int, char*, int);
 int		findlocal(Symbol*, char*, Symbol*);
 int		findseg(Map*, char*);
-int		findsym(long, int, Symbol *);
-int		fnbound(long, ulong*);
+int		findsym(uvlong, int, Symbol *);
+int		fnbound(uvlong, uvlong*);
 int		fpformat(Map*, Reglist*, char*, int, int);
-int		get1(Map*, ulong, uchar*, int);
-int		get2(Map*, ulong, ushort*);
-int		get4(Map*, ulong, long*);
-int		get8(Map*, ulong, vlong*);
+int		get1(Map*, uvlong, uchar*, int);
+int		get2(Map*, uvlong, ushort*);
+int		get4(Map*, uvlong, ulong*);
+int		get8(Map*, uvlong, uvlong*);
+int		geta(Map*, uvlong, uvlong*);
 int		getauto(Symbol*, int, int, Symbol*);
 Sym*		getsym(int);
 int		globalsym(Symbol *, int);
@@ -272,11 +275,11 @@ int		leieee80ftos(char*, int, void*);
 int		leieeesftos(char*, int, void*);
 int		leieeedftos(char*, int, void*);
 ushort		leswab(ushort);
-long		leswal(long);
-vlong		leswav(vlong);
-long		line2addr(ulong, ulong, ulong);
+ulong		leswal(ulong);
+uvlong		leswav(uvlong);
+uvlong		line2addr(long, uvlong, uvlong);
 Map*		loadmap(Map*, int, Fhdr*);
-int		localaddr(Map*, char*, char*, long*, Rgetter);
+int		localaddr(Map*, char*, char*, uvlong*, Rgetter);
 int		localsym(Symbol*, int);
 int		lookup(char*, char*, Symbol*);
 void		machbytype(int);
@@ -285,20 +288,21 @@ int		nextar(Biobuf*, int, char*);
 Map*		newmap(Map*, int);
 void		objtraverse(void(*)(Sym*, void*), void*);
 int		objtype(Biobuf*, char**);
-long		pc2sp(ulong);
-long		pc2line(ulong);
-int		put1(Map*, ulong, uchar*, int);
-int		put2(Map*, ulong, ushort);
-int		put4(Map*, ulong, long);
-int		put8(Map*, ulong, vlong);
-int		readar(Biobuf*, int, int, int);
+uvlong		pc2sp(uvlong);
+long		pc2line(uvlong);
+int		put1(Map*, uvlong, uchar*, int);
+int		put2(Map*, uvlong, ushort);
+int		put4(Map*, uvlong, ulong);
+int		put8(Map*, uvlong, uvlong);
+int		puta(Map*, uvlong, uvlong);
+int		readar(Biobuf*, int, vlong, int);
 int		readobj(Biobuf*, int);
-ulong		riscframe(Map*, ulong, ulong, ulong, ulong);
-int		risctrace(Map*, ulong, ulong, ulong, Tracer);
-int		setmap(Map*, int, ulong, ulong, ulong, char*);
+uvlong		riscframe(Map*, uvlong, uvlong, uvlong, uvlong);
+int		risctrace(Map*, uvlong, uvlong, uvlong, Tracer);
+int		setmap(Map*, int, uvlong, uvlong, vlong, char*);
 Sym*		symbase(long*);
 int		syminit(int, Fhdr*);
-int		symoff(char*, int, long, int);
-void		textseg(ulong, Fhdr*);
+int		symoff(char*, int, uvlong, int);
+void		textseg(uvlong, Fhdr*);
 int		textsym(Symbol*, int);
 void		unusemap(Map*, int);

+ 21 - 5
sys/lib/acid/leak

@@ -83,28 +83,44 @@ dumprange(s, e, type)
 	print("range ", type, " ", s\X, " ", e\X, "\n");
 	x = s;
 	while x < e do {
-		y = *x;
+		y = *(x\X);
 		if isptr(y) then print("data ", x\X, " ", y\X, " ", type, "\n");
 		x = x + 4;
 	}
 }
 
+defn
+stacktop()
+{
+	local e, m;
+	
+	m = map();
+	while m != {} do {
+		e = head m;
+		if e[0] == "*data" then
+			return e[2];
+		m = tail m;
+	}
+	return 0x7ffff000;
+}
+			
 defn
 dumpmem()
 {
-	local s;
+	local s, top;
 
 	xbloc = *bloc;
 	// assume map()[1] is "data" 
 	dumprange(map()[1][1], end, "bss");	// bss
 	dumprange(end, xbloc, "alloc");	// allocated
 
-	if 0x7efff000 < *SP && *SP < 0x7ffff000 then 
+	top = stacktop() - 8;
+	if top-0x01000000 < *SP && *SP < top then
 		s = *SP;
 	else
-		s = 0x7fff7000;	// 32 k
+		s = top-32*1024;
 
-	dumprange(s, 0x7ffff000, "stack");
+	dumprange(s, top, "stack");
 }
 
 defn

+ 17 - 5
sys/man/1/strip

@@ -3,16 +3,28 @@
 strip \- remove symbols from binary files
 .SH SYNOPSIS
 .B strip
-[
 .I file ...
-]
+.PP
+.B strip
+.B -o
+.I ofile
+.I file
 .SH DESCRIPTION
 .I Strip
-removes symbol table segments from executable files, rewriting the files in place.
+removes symbol table segments from executable files,
+rewriting the files in place.
 Stripping a file requires write permission of the file
 and the directory it is in.
-If no file is given, 
-standard input is stripped and the result written to standard output.
+.PP
+If the
+.B -o
+flag is given, 
+the single input file
+.I file
+is stripped and the result written to
+.IR ofile .
+.I File
+is unchanged.
 .SH SOURCE
 .B /sys/src/cmd/strip.c
 .SH "SEE ALSO"

+ 6 - 3
sys/man/3/vga

@@ -5,11 +5,10 @@ vga \- VGA controller device
 .nf
 .B bind #v /dev
 
+.B /dev/vgabios
 .B /dev/vgactl
-
-.B /dev/vgaovlctl
-
 .B /dev/vgaovl
+.B /dev/vgaovlctl
 .fi
 .SH DESCRIPTION
 The VGA device allows configuration of a graphics controller
@@ -24,6 +23,10 @@ it is used to implement configuration and setup of VGA controller cards.
 This is usually performed by
 .IR vga (8).
 .PP
+.B Vgabios
+provides read-only access to the low 640kB of memory,
+where the VGA and other BIOS ROMs are located.
+.PP
 Writing strings to 
 .B vgactl
 configures the VGA device.

+ 9 - 1
sys/man/4/factotum

@@ -4,7 +4,7 @@ factotum, fgui \- authentication agent
 .SH SYNOPSIS
 .B auth/factotum
 [
-.B -DdkSun
+.B -DdknpuS
 ] [
 .B -a asaddr
 ] [
@@ -211,6 +211,14 @@ and
 .BR \-S .
 This option is typically used by
 the kernel at boot time.
+.TP
+.B \-p
+causes the agent not to mark itself `private'
+via 
+.IR proc (3),
+so that it can be debugged.
+It is implied by
+.BR \-d .
 .PD
 .PP
 .I Fgui

+ 14 - 0
sys/man/8/plan9.ini

@@ -515,6 +515,12 @@ partition, the definition might read
 See
 .IR boot (8)
 for more.
+.SS \fLdebugfactotum=\fP
+Causes
+.IR boot (8)
+to start factotum with the
+.B -p
+flag, so that it can be debugged.
 .SS \fLventi=value\fP
 When booting from a local fossil server backed by a local
 or remote venti server,
@@ -551,6 +557,13 @@ A value of
 consults only the first table,
 .B old
 only the second.
+.SS \fL*norealmode=\fP
+The kernel switches the processor to 16-bit real mode 
+to run BIOS interrupts, for example to find the memory map or to enable VESA. 
+This variable disables such switches.
+.SS \fL*noe820scan=\fP
+When available, the kernel uses the BIOS E820 memory map
+to size memory.  This variable disables the scan.
 .SS \fL*maxmem=value\fP
 This defines the maximum physical address that the system will scan when sizing memory.
 By default the operating system will scan up to 768 megabytes, but setting
@@ -561,6 +574,7 @@ If the system has more than 768 megabytes, you must set
 for the kernel to find it.
 .B *maxmem
 must be less than 1.75 gigabytes.
+This variable is not consulted if using the E820 memory map.
 .SS \fL*kernelpercent=value\fP
 This defines what percentage of available memory is reserved for the kernel allocation pool.
 The remainder is left for user processes.  The default

+ 13 - 10
sys/man/8/statusbar

@@ -46,22 +46,25 @@ set the coordinates of the statusbar window created
 .PD
 .SH EXAMPLE
 The
-.B -d
-options to
-.IR hget(1),
-.IR venti/fmtarenas ,
-and
-.I venti/fmtisect
-(see
-.IR ventiaux (8))
-cause them to print status lines suitable for
+.B -v
+option to
+.IR hget(1)
+.\" and the 
+.\" .B -d
+.\" option to
+.\" .IR venti/fmtarenas
+.\" and
+.\" .I venti/fmtisect
+.\" (see
+,\" .IR ventiaux (8))
+causes it to print status lines suitable for
 input to
 .IR statusbar .
 .PP
 Monitor a long download:
 .IP
 .EX
-hget -d -o bigfile http://server.com/bigfile | 
+hget -v -o bigfile http://server.com/bigfile | 
   aux/statusbar 'big file download'
 .EE
 .SH SOURCE

+ 0 - 1
sys/man/8/vga

@@ -59,7 +59,6 @@ dump the BIOS memory (in hex) to standard output and exit.
 .TP
 .B -c
 disable the use of the hardware graphics cursor.
-(Since there is no software cursor, this disables the cursor entirely.)
 .TP
 .B -d
 include the color palette in whatever actions are performed,

+ 1 - 1
sys/src/9/alphapc/apc

@@ -36,7 +36,7 @@ misc
 	arch164
 
 	sdata		pci sdscsi
-	sd53c8xx	pci sdscsi
+#	sd53c8xx	pci sdscsi
 
 	uarti8250
 

+ 11 - 4
sys/src/9/alphapc/dat.h

@@ -1,4 +1,5 @@
 typedef struct Conf	Conf;
+typedef struct Confmem	Confmem;
 typedef struct FPsave	FPsave;
 typedef struct ISAConf	ISAConf;
 typedef struct Label	Label;
@@ -32,6 +33,7 @@ struct Lock
 	ulong	sr;
 	ulong	pc;
 	Proc	*p;
+	Mach	*m;
 	ulong	pid;
 	ushort	isilock;
 };
@@ -63,15 +65,20 @@ struct	FPsave
 	long	fpstatus;
 };
 
+struct Confmem
+{
+	ulong	base;
+	ulong	npage;
+	ulong	kbase;
+	ulong	klimit;
+};
+
 struct Conf
 {
 	ulong	nmach;		/* processors */
 	ulong	nproc;		/* processes */
-	ulong	npage0;		/* total physical pages of memory */
-	ulong	npage1;		/* total physical pages of memory */
+	Confmem	mem[2];
 	ulong	npage;		/* total physical pages of memory */
-	ulong	base0;		/* base of bank 0 */
-	ulong	base1;		/* base of bank 1 */
 	ulong	upages;		/* user page pool */
 	ulong	nimage;		/* number of page cache image headers */
 	ulong	nswap;		/* number of swap pages */

+ 1 - 4
sys/src/9/alphapc/devvga.c

@@ -130,10 +130,7 @@ vgaread(Chan* c, void* a, long n, vlong off)
 		len += snprint(p+len, READSTR-len, "blanktime %lud\n", blanktime);
 		len += snprint(p+len, READSTR-len, "hwaccel %s\n", hwaccel ? "on" : "off");
 		len += snprint(p+len, READSTR-len, "hwblank %s\n", hwblank ? "on" : "off");
-		if(scr->pciaddr)
-			snprint(p+len, READSTR-len, "addr 0x%lux\n", scr->pciaddr);
-		else
-			snprint(p+len, READSTR-len, "addr 0x%lux\n", scr->aperture);
+		snprint(p+len, READSTR-len, "addr 0x%lux\n", scr->paddr);
 		n = readstr(offset, a, n, p);
 		poperror();
 		free(p);

+ 3 - 1
sys/src/9/alphapc/fns.h

@@ -98,11 +98,13 @@ void	tlbflush(int, ulong);
 void	touser(void*);
 void	trapinit(void);
 void	unaligned(void);
-ulong	upamalloc(ulong, int, int);
+ulong	upaalloc(int, int);
 void	upafree(ulong, int);
 #define	userureg(ur) ((ur)->status & UMODE)
+void*	vmap(ulong, int);
 void	wrent(int, void*);
 void	wrvptptr(uvlong);
+void	vunmap(void*, int);
 
 #define	waserror()	(up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
 #define KADDR(a)	((void*)((ulong)(a)|KZERO))

+ 7 - 7
sys/src/9/alphapc/main.c

@@ -454,17 +454,17 @@ confinit(void)
 	 * allocating low memory pages from bank 0 for any peripherals
 	 * which only have a 24bit address counter.
 	 */
-	conf.npage0 = (8*1024*1024)/BY2PG;
-	conf.base0 = 0;
+	conf.mem[0].npage = (8*1024*1024)/BY2PG;
+	conf.mem[0].base = 0;
 
-	conf.npage1 = (b->max-8*1024*1024)/BY2PG;
-	conf.base1 = 8*1024*1024;
+	conf.mem[1].npage = (b->max-8*1024*1024)/BY2PG;
+	conf.mem[1].base = 8*1024*1024;
 
-	conf.npage = conf.npage0+conf.npage1;
+	conf.npage = conf.mem[0].npage+conf.mem[1].npage;
 	conf.upages = (conf.npage*70)/100;
 
-	conf.npage0 -= ktop/BY2PG;
-	conf.base0 += ktop;
+	conf.mem[0].npage -= ktop/BY2PG;
+	conf.mem[0].base += ktop;
 	conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
 
 	/*

+ 21 - 7
sys/src/9/alphapc/mmu.c

@@ -224,8 +224,8 @@ flushmmu(void)
 
 }
 
-ulong
-upamalloc(ulong pa, int size, int align)
+void*
+vmap(ulong pa, int size)
 {
 	void *va;
 
@@ -234,17 +234,16 @@ upamalloc(ulong pa, int size, int align)
 	 */
 	if(pa == 0)
 		return 0;
-	USED(align);
 	va = kmapv(((uvlong)0x88<<32LL)|pa, size);
 	if(va == nil)
 		return 0;
-	return PADDR(va);
+	return (void*)va;
 }
 
 void
-upafree(ulong, int)
+vunmap(void*, int)
 {
-	print("upafree: virtual mapping not freed\n");
+	print("vunmap: virtual mapping not freed\n");
 }
 
 void
@@ -263,4 +262,19 @@ mmudump(void)
 	}
 }
 
-void checkmmu(ulong, ulong) { }
+ulong
+upaalloc(int, int)
+{
+	return 0;
+}
+
+void
+upafree(ulong, int)
+{
+}
+
+void
+checkmmu(ulong, ulong)
+{
+}
+

+ 20 - 7
sys/src/9/alphapc/screen.h

@@ -68,7 +68,7 @@ struct VGAdev {
 	void	(*enable)(VGAscr*);
 	void	(*disable)(VGAscr*);
 	void	(*page)(VGAscr*, int);
-	ulong	(*linear)(VGAscr*, int*, int*);
+	void	(*linear)(VGAscr*, int, int);
 	void	(*drawinit)(VGAscr*);
 	int	(*fill)(VGAscr*, Rectangle, ulong);
 	void (*flush)(VGAscr*, Rectangle);
@@ -91,6 +91,7 @@ struct VGAcur {
 struct VGAscr {
 	Lock	devlock;
 	VGAdev*	dev;
+	Pcidev*	pci;
 
 	VGAcur*	cur;
 	ulong	storage;
@@ -98,17 +99,16 @@ struct VGAscr {
 
 	int	useflush;
 
-	ulong	aperture;			/* physical address, kernel */
-	ulong	pciaddr;			/* physical address, user */
-	int	isupamem;
+	ulong	paddr;		/* frame buffer */
+	void*	vaddr;
 	int	apsize;
 
 	ulong	io;				/* device specific registers */
-
+	ulong	*mmio;
+	
 	ulong	colormap[Pcolours][3];
 	int	palettedepth;
 
-	ulong	*mmio;
 	Memimage* gscreen;
 	Memdata* gscreendata;
 	Memsubfont* memdefont;
@@ -142,14 +142,27 @@ extern int	screenaperture(int, int);
 extern Rectangle physgscreenr;	/* actual monitor size */
 extern void	blankscreen(int);
 
+extern VGAcur swcursor;
+extern void swcursorinit(void);
+extern void swcursorhide(void);
+extern void swcursoravoid(Rectangle);
+extern void swcursorunhide(void);
+
 /* devdraw.c */
 extern void	deletescreenimage(void);
 extern int	drawhasclients(void);
 extern ulong	blanktime;
+extern QLock	drawlock;
+
 /* vga.c */
 extern void	vgascreenwin(VGAscr*);
 extern void	vgaimageinit(ulong);
-extern ulong	vgapcilinear(VGAscr*, int*, int*, int, int);
+extern void	vgalinearpciid(VGAscr*, int, int);
+extern void	vgalinearpci(VGAscr*);
+extern void	vgalinearaddr(VGAscr*, ulong, int);
 
 extern void	drawblankscreen(int);
 extern void	vgablank(VGAscr*, int);
+
+extern Lock	vgascreenlock;
+

+ 0 - 2
sys/src/9/alphapc/sd53c8xx.c

@@ -1817,8 +1817,6 @@ static Variant variant[] = {
 { SYM_1010_DID,  0xff, "SYM53C1010",	Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
 };
 
-#define offsetof(s, t) ((ulong)&((s *)0)->t)
-
 static int
 xfunc(Controller *c, enum na_external x, unsigned long *v)
 {

+ 12 - 4
sys/src/9/bitsy/dat.h

@@ -1,5 +1,6 @@
 typedef struct Cisdat 		Cisdat;
 typedef struct Conf		Conf;
+typedef struct Confmem	Confmem;
 typedef struct FPU		FPU;
 typedef struct FPenv		FPenv;
 typedef struct FPsave		FPsave;
@@ -37,6 +38,7 @@ struct Lock
 	ulong	sr;
 	ulong	pc;
 	Proc	*p;
+	Mach	*m;
 	ushort	isilock;
 };
 
@@ -62,19 +64,25 @@ struct	FPsave
 	ulong	regs[8][3];	/* emulated fp */	
 };
 
+struct Confmem
+{
+	ulong	base;
+	ulong	npage;
+	ulong	limit;
+	ulong	kbase;
+	ulong	klimit;
+};
+
 struct Conf
 {
 	ulong	nmach;		/* processors */
 	ulong	nproc;		/* processes */
-	ulong	npage0;		/* total physical pages of memory */
-	ulong	npage1;		/* total physical pages of memory */
+	Confmem	mem[2];
 	ulong	npage;		/* total physical pages of memory */
 	ulong	upages;		/* user page pool */
 	ulong	nimage;		/* number of page cache image headers */
 	ulong	nswap;		/* number of swap pages */
 	int	nswppo;		/* max # of pageouts per segment pass */
-	ulong	base0;		/* base of bank 0 */
-	ulong	base1;		/* base of bank 1 */
 	ulong	copymode;	/* 0 is copy on write, 1 is copy on reference */
 	int	monitor;
 	ulong	ialloc;		/* bytes available for interrupt time allocation */

+ 19 - 1
sys/src/9/bitsy/devpenmouse.c

@@ -53,6 +53,8 @@ struct Mouseinfo
 	Lock;
 	Mousestate;
 	ulong	lastcounter;	/* value when /dev/mouse read */
+	ulong	resize;
+	ulong	lastresize;
 	Rendez	r;
 	Ref;
 	QLock;
@@ -285,6 +287,10 @@ penmouseread(Chan *c, void *va, long n, vlong)
 		mouse.lastcounter = m.counter;
 		if(n > 1+4*12)
 			n = 1+4*12;
+		if(mouse.lastresize != mouse.resize){
+			mouse.lastresize = mouse.resize;
+			buf[0] = 'r';
+		}
 		memmove(va, buf, n);
 		return n;
 	}
@@ -481,7 +487,8 @@ penmousetrack(int b, int x, int y)
 int
 penmousechanged(void*)
 {
-	return mouse.lastcounter != mouse.counter;
+	return mouse.lastcounter != mouse.counter ||
+		mouse.lastresize != mouse.resize;
 }
 
 Point
@@ -489,3 +496,14 @@ penmousexy(void)
 {
 	return mouse.xy;
 }
+
+/*
+ * notify reader that screen has been resized (ha!)
+ */
+void
+mouseresize(void)
+{
+	mouse.resize++;
+	wakeup(&mouse.r);
+}
+

+ 38 - 49
sys/src/9/bitsy/main.c

@@ -268,19 +268,18 @@ rdb(void)
 int
 probemem(ulong addr)
 {
+	int i;
 	ulong *p;
 	ulong a;
 
 	addr += OneMeg - sizeof(ulong);
 	p = (ulong*)addr;
 	*p = addr;
-	for(a = conf.base0+OneMeg-sizeof(ulong); a < conf.npage0; a += OneMeg){
-		p = (ulong*)a;
-		*p = 0;
-	}
-	for(a = conf.base1+OneMeg-sizeof(ulong); a < conf.npage1; a += OneMeg){
-		p = (ulong*)a;
-		*p = 0;
+	for(i=0; i<nelem(conf.mem); i++){
+		for(a = conf.mem[i].base+OneMeg-sizeof(ulong); a < conf.mem[i].limit; a += OneMeg){
+			p = (ulong*)a;
+			*p = 0;
+		}
 	}
 	p = (ulong*)addr;
 	if(*p != addr)
@@ -295,57 +294,47 @@ probemem(ulong addr)
 void
 confinit(void)
 {
-	int i;
+	int i, j;
 	ulong addr;
 	ulong ktop;
 
 	/* find first two contiguous sections of available memory */
 	addr = PHYSDRAM0;
-	conf.base0 = conf.npage0 = addr;
-	conf.base1 = conf.npage1 = addr;
-	for(i = 0; i < 512; i++){
-		if(probemem(addr) == 0)
-			break;
-		addr += OneMeg;
+	for(i=0; i<nelem(conf.mem); i++){
+		conf.mem[i].base = addr;
+		conf.mem[i].limit = addr;
 	}
-	for(; i < 512; i++){
-		if(probemem(addr) < 0)
-			break;
-		addr += OneMeg;
-		conf.npage0 = addr;
-	}
-
-	conf.base1 = conf.npage1 = addr;
-	for(; i < 512; i++){
-		if(probemem(addr) == 0)
-			break;
-		addr += OneMeg;
+	for(j=0; j<nelem(conf.mem); j++){
+		conf.mem[j].base = addr;
+		conf.mem[j].limit = addr;
+		
+		for(i = 0; i < 512; i++){
+			if(probemem(addr) == 0)
+				break;
+			addr += OneMeg;
+		}
+		for(; i < 512; i++){
+			if(probemem(addr) < 0)
+				break;
+			addr += OneMeg;
+			conf.mem[j].limit = addr;
+		}
 	}
-	for(; i < 512; i++){
-		if(probemem(addr) < 0)
-			break;
-		addr += OneMeg;
-		conf.npage1 = addr;
+	
+	conf.npage = 0;
+	for(i=0; i<nelem(conf.mem); i++){
+		/* take kernel out of allocatable space */
+		ktop = PGROUND((ulong)end);
+		if(ktop >= conf.mem[i].base && ktop <= conf.mem[i].limit)
+			conf.mem[i].base = ktop;
+		
+		/* zero memory */
+		memset((void*)conf.mem[i].base, 0, conf.mem[i].limit - conf.mem[i].base);
+
+		conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
+		conf.npage += conf.mem[i].npage;
 	}
 
-	/* take kernel out of allocatable space */
-	ktop = PGROUND((ulong)end);
-	if(ktop >= conf.base0 && ktop <= conf.npage0)
-		conf.base0 = ktop;
-	else if(ktop >= conf.base1 && ktop <= conf.npage1)
-		conf.base1 = ktop;
-	else
-		iprint("kernel not in allocatable space\n");
-
-	/* zero memory */
-	memset((void*)conf.base0, 0, conf.npage0 - conf.base0);
-	memset((void*)conf.base1, 0, conf.npage1 - conf.base1);
-
-	/* make npage the right thing */
-	conf.npage0 = (conf.npage0 - conf.base0)/BY2PG;
-	conf.npage1 = (conf.npage1 - conf.base1)/BY2PG;
-	conf.npage = conf.npage0+conf.npage1;
-
 	if(conf.npage > 16*MB/BY2PG){
 		conf.upages = (conf.npage*60)/100;
 		imagmem->minarena = 4*1024*1024;

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

@@ -104,7 +104,7 @@ init.h:	../port/initcode.c init9.s
 	$AS init9.s
 	$LD -l -R1 -o init.out init9.$O initcode.$O /arm/lib/libc.a
 	{echo 'uchar initcode[]={'
-	 strip < init.out | xd -1x |
+	 strip -o /fd/1 init.out | xd -1x |
 		sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
 	 echo '};'} > init.h
 

+ 1 - 21
sys/src/9/bitsy/sdata.c

@@ -742,6 +742,7 @@ tryedd1:
 
 	sdev->ifc = &sdataifc;
 	sdev->ctlr = ctlr;
+	sdev->idno = 'C';
 	sdev->nunit = 1;
 	ctlr->sdev = sdev;
 
@@ -1571,26 +1572,6 @@ atalegacy(int port, int irq)
 	return ataprobe(port, port+0x204, irq);
 }
 
-static SDev*
-ataid(SDev* sdev)
-{
-	int i;
-
-	if(sdev == nil)
-		return nil;
-	i = 0;
-	while(sdev){
-		if(sdev->ifc == &sdataifc){
-			sdev->idno = 'C'+i;
-			i++;
-			snprint(sdev->name, KNAMELEN, "sd%c", sdev->idno);
-		}
-		sdev = sdev->next;
-	}
-
-	return nil;
-}
-
 static int ataitype;
 static int atairq;
 static int
@@ -2089,7 +2070,6 @@ SDifc sdataifc = {
 
 	nil,				/* pnp */
 	atalegacy,			/* legacy */
-	ataid,				/* id */
 	ataenable,			/* enable */
 	nil,				/* disable */
 

+ 3 - 1
sys/src/9/boot/bootauth.c

@@ -22,7 +22,9 @@ authentication(int cpuflag)
 	ac = 0;
 	av = argv;
 	av[ac++] = "factotum";
-//av[ac++] = "-d";
+	if(getenv("debugfactotum"))
+		av[ac++] = "-p";
+//av[ac++] = "-d";	//debug traces
 //av[ac++] = "-D";	//9p messages
 	if(cpuflag)
 		av[ac++] = "-S";

+ 11 - 5
sys/src/9/mtx/dat.h

@@ -1,4 +1,5 @@
 typedef struct Conf	Conf;
+typedef struct Confmem	Confmem;
 typedef struct FPsave	FPsave;
 typedef struct ISAConf	ISAConf;
 typedef struct Label	Label;
@@ -33,7 +34,7 @@ struct Lock
 	ulong	sr;
 	ulong	pc;
 	Proc	*p;
-	ulong	pid;
+	Mach	*m;
 	ushort	isilock;
 };
 
@@ -68,15 +69,20 @@ struct	FPsave
 	};
 };
 
+struct Confmem
+{
+	ulong	base;
+	ulong	npage;
+	ulong	kbase;
+	ulong	klimit;
+};
+
 struct Conf
 {
 	ulong	nmach;		/* processors */
 	ulong	nproc;		/* processes */
-	ulong	npage0;		/* total physical pages of memory */
-	ulong	npage1;		/* total physical pages of memory */
+	Confmem	mem[1];
 	ulong	npage;		/* total physical pages of memory */
-	ulong	base0;		/* base of bank 0 */
-	ulong	base1;		/* base of bank 1 */
 	ulong	upages;		/* user page pool */
 	ulong	nimage;		/* number of page cache image headers */
 	ulong	nswap;		/* number of swap pages */

+ 3 - 7
sys/src/9/mtx/main.c

@@ -288,13 +288,9 @@ confinit(void)
 
 	pa = PGROUND(PADDR(end));
 
-	conf.npage0 = memsize/BY2PG;
-	conf.base0 = pa;
-	
-	conf.npage1 = 0;
-	conf.base1 = pa;
-
-	conf.npage = conf.npage0 + conf.npage1;
+	conf.mem[0].npage = memsize/BY2PG;
+	conf.mem[0].base = pa;
+	conf.npage = conf.mem[0].npage;
 
 	conf.nmach = 1;
 	conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;

+ 10 - 10
sys/src/9/pc/apbootstrap.s

@@ -1,3 +1,13 @@
+/*
+ * Start an Application Processor. This must be placed on a 4KB boundary
+ * somewhere in the 1st MB of conventional memory (APBOOTSTRAP). However,
+ * due to some shortcuts below it's restricted further to within the 1st
+ * 64KB. The AP starts in real-mode, with
+ *   CS selector set to the startup memory address/16;
+ *   CS base set to startup memory address;
+ *   CS limit set to 64KB;
+ *   CPL and IP set to 0.
+ */
 #include "mem.h"
 
 #define NOP		BYTE $0x90		/* NOP */
@@ -23,16 +33,6 @@
 #define PDO(a)		(((((a))>>22) & 0x03FF)<<2)
 #define PTO(a)		(((((a))>>12) & 0x03FF)<<2)
 
-/*
- * Start an Application Processor. This must be placed on a 4KB boundary
- * somewhere in the 1st MB of conventional memory (APBOOTSTRAP). However,
- * due to some shortcuts below it's restricted further to within the 1st
- * 64KB. The AP starts in real-mode, with
- *   CS selector set to the startup memory address/16;
- *   CS base set to startup memory address;
- *   CS limit set to 64KB;
- *   CPL and IP set to 0.
- */
 TEXT apbootstrap(SB), $0
 	FARJUMP16(0, _apbootstrap(SB))
 TEXT _apvector(SB), $0				/* address APBOOTSTRAP+0x08 */

+ 13 - 0
sys/src/9/pc/apic.c

@@ -376,3 +376,16 @@ lapicclock(Ureg *u, void*)
 {
 	timerintr(u, 0);
 }
+
+void
+lapicintron(void)
+{
+	lapicw(LapicTPR, 0);
+}
+
+void
+lapicintroff(void)
+{
+	lapicw(LapicTPR, 0xFF);
+}
+

+ 2 - 0
sys/src/9/pc/apm.c

@@ -103,6 +103,8 @@ apmlink(void)
 	if(isaconfig("apm", 0, &isa) == 0)
 		return;
 
+/* XXX use realmode() */
+
 	/*
 	 * APM info passed from boot loader.
 	 * Now we need to set up the GDT entries for APM.

+ 2 - 0
sys/src/9/pc/archmp.c

@@ -62,6 +62,8 @@ PCArch archmp = {
 .reset=		mpshutdown,
 .intrinit=	mpinit,
 .intrenable=	mpintrenable,
+.intron=	lapicintron,
+.introff=	lapicintroff,
 .fastclock=	i8253read,
 .timerset=	lapictimerset,
 };

+ 19 - 7
sys/src/9/pc/dat.h

@@ -1,4 +1,5 @@
 typedef struct Conf	Conf;
+typedef struct Confmem	Confmem;
 typedef struct FPsave	FPsave;
 typedef struct ISAConf	ISAConf;
 typedef struct Label	Label;
@@ -32,6 +33,7 @@ struct Lock
 	ulong	sr;
 	ulong	pc;
 	Proc	*p;
+	Mach	*m;
 	ushort	isilock;
 };
 
@@ -73,13 +75,20 @@ struct	FPsave
 	uchar	regs[80];	/* floating point registers */
 };
 
+struct Confmem
+{
+	ulong	base;
+	ulong	npage;
+	ulong	kbase;
+	ulong	klimit;
+};
+
 struct Conf
 {
 	ulong	nmach;		/* processors */
 	ulong	nproc;		/* processes */
 	ulong	monitor;	/* has monitor? */
-	ulong	npage0;		/* total physical pages of memory */
-	ulong	npage1;		/* total physical pages of memory */
+	Confmem	mem[4];		/* physical memory */
 	ulong	npage;		/* total physical pages of memory */
 	ulong	upages;		/* user page pool */
 	ulong	nimage;		/* number of page cache image headers */
@@ -102,6 +111,7 @@ struct PMMU
 	Page*	mmupdb;			/* page directory base */
 	Page*	mmufree;		/* unused page table pages */
 	Page*	mmuused;		/* used page table pages */
+	uint	lastkmap;		/* last entry used by kmap */
 };
 
 /*
@@ -212,12 +222,12 @@ struct Mach
 };
 
 /*
- * Fake kmap
+ * KMap the structure doesn't exist, but the functions do.
  */
-typedef void		KMap;
-#define	VA(k)		((ulong)(k))
-#define	kmap(p)		(KMap*)((p)->pa|KZERO)
-#define	kunmap(k)
+typedef struct KMap		KMap;
+#define	VA(k)		((void*)(k))
+KMap*	kmap(Page*);
+void	kunmap(KMap*);
 
 struct
 {
@@ -243,6 +253,8 @@ struct PCArch
 	int	(*intrenable)(Vctl*);
 	int	(*intrvecno)(int);
 	int	(*intrdisable)(int);
+	void	(*introff)(void);
+	void	(*intron)(void);
 
 	void	(*clockenable)(void);
 	uvlong	(*fastclock)(uvlong*);

+ 2 - 0
sys/src/9/pc/devarch.c

@@ -520,6 +520,8 @@ PCArch archgeneric = {
 .intrenable=	i8259enable,
 .intrvecno=	i8259vecno,
 .intrdisable=	i8259disable,
+.intron=		i8259on,
+.introff=		i8259off,
 
 .clockenable=	i8253enable,
 .fastclock=	i8253read,

+ 4 - 5
sys/src/9/pc/devether.c

@@ -416,7 +416,7 @@ etherprobe(int cardno, int ctlrno)
 	i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %d",
 		ctlrno, cards[cardno].type, ether->mbps, ether->port, ether->irq);
 	if(ether->mem)
-		i += sprint(buf+i, " addr 0x%luX", PADDR(ether->mem));
+		i += sprint(buf+i, " addr 0x%luX", ether->mem);
 	if(ether->size)
 		i += sprint(buf+i, " size 0x%luX", ether->size);
 	i += sprint(buf+i, ": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
@@ -425,16 +425,15 @@ etherprobe(int cardno, int ctlrno)
 	sprint(buf+i, "\n");
 	print(buf);
 
-	if (ether->mbps >= 1000) {
+	if(ether->mbps >= 1000){
 		netifinit(ether, name, Ntypes, 512*1024);
 		if(ether->oq == 0)
 			ether->oq = qopen(512*1024, Qmsg, 0, 0);
-	} else if(ether->mbps >= 100){
+	}else if(ether->mbps >= 100){
 		netifinit(ether, name, Ntypes, 256*1024);
 		if(ether->oq == 0)
 			ether->oq = qopen(256*1024, Qmsg, 0, 0);
-	}
-	else{
+	}else{
 		netifinit(ether, name, Ntypes, 128*1024);
 		if(ether->oq == 0)
 			ether->oq = qopen(128*1024, Qmsg, 0, 0);

+ 5 - 3
sys/src/9/pc/devlml.c

@@ -127,6 +127,7 @@ lmlreset(void)
 {
 	Physseg segbuf;
 	ulong regpa;
+	void *regva;
 	ISAConf isa;
 	char name[32];
 	Pcidev *pcidev;
@@ -157,12 +158,13 @@ lmlreset(void)
 
 		print("zr36067 found at 0x%.8lux", pcidev->mem[0].bar & ~0x0F);
 
-		regpa = upamalloc(pcidev->mem[0].bar & ~0x0F, pcidev->mem[0].size, 0);
-		if (regpa == 0) {
+		regpa = pcidev->mem[0].bar & ~0x0F;
+		regva = vmap(regpa, pcidev->mem[0].size, 0);
+		if (regva == 0) {
 			print("lml: failed to map registers\n");
 			return;
 		}
-		lml->pciBaseAddr = (ulong)KADDR(regpa);
+		lml->pciBaseAddr = (ulong)regva;
 		print(", mapped at 0x%.8lux\n", lml->pciBaseAddr);
 
 		memset(&segbuf, 0, sizeof(segbuf));

+ 8 - 6
sys/src/9/pc/devpccard.c

@@ -515,6 +515,7 @@ devpccardlink(void)
 	int i;
 	uchar intl;
 	char *p;
+	void *baddrva;
 
 	if (initialized) 
 		return;
@@ -623,14 +624,15 @@ devpccardlink(void)
 		intl = pci->intl;
 
 		if ((baddr = pcicfgr32(cb->pci, PciBAR0)) == 0) {
-			int align = (pci->did == Ricoh_478_did)? 0x10000: 0x1000;
+			int size = (pci->did == Ricoh_478_did)? 0x10000: 0x1000;
 
-			baddr = upamalloc(baddr, align, align);
+			baddr = upaalloc(size, size);
+			baddrva = vmap(baddr, size);
 			pcicfgw32(cb->pci, PciBAR0, baddr);
-			cb->regs = (ulong *)KADDR(baddr);
+			cb->regs = (ulong *)baddrva;
 		}
 		else
-			cb->regs = (ulong *)KADDR(upamalloc(baddr, 4096, 0));
+			cb->regs = (ulong *)vmap(baddr, 4096);
 		cb->state = SlotEmpty;
 
 		/* Don't really know what to do with this... */
@@ -810,7 +812,7 @@ configure(Cardbus *cb)
 				continue;
 			}
 
-			bar = upamalloc(0, pci->mem[i].size, BY2PG);
+			bar = upaalloc(pci->mem[i].size, BY2PG);
 			pci->mem[i].bar = bar | (pci->mem[i].bar & 0x80);
 			pcicfgw32(pci, PciBAR0 + i * sizeof(ulong), pci->mem[i].bar);
 			pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, bar);
@@ -834,7 +836,7 @@ configure(Cardbus *cb)
 				print("#Y%ld: WARNING: Too many memory spaces, not mapping ROM space\n",
 					cb - cbslots);
 			else {
-				pci->rom.bar = upamalloc(0, size, BY2PG);
+				pci->rom.bar = upaalloc(size, BY2PG);
 				pci->rom.size = size;
 
 				pcicfgw32(pci, PciEBAR0, pci->rom.bar);

+ 13 - 13
sys/src/9/pc/devtv.c

@@ -557,7 +557,7 @@ tvinit(void)
 		tv = &tvs[ntvs++];
 		tv->variant = &variant[i];
 		tv->pci = pci;
-		tv->bt848 = (Bt848 *)upamalloc(pci->mem[0].bar & ~0x0F, 4 * K, K);
+		tv->bt848 = (Bt848 *)vmap(pci->mem[0].bar & ~0x0F, 4 * K);
 		if (tv->bt848 == nil)
 			panic("#V: Cannot allocate memory for Bt848");
 		bt848 = tv->bt848;
@@ -591,7 +591,7 @@ tvinit(void)
 				panic("#V: Unsupported Hauppage board");
 
 			tv->bt878 = bt878 = 
-				(Bt848 *)upamalloc(pci878->mem[0].bar & ~0x0F, 4 * K, K);
+				(Bt848 *)vmap(pci878->mem[0].bar & ~0x0F, 4 * K);
 			if (bt878 == nil)
 				panic("#V: Cannot allocate memory for the Bt878");
 
@@ -1206,7 +1206,7 @@ i2cwrite(Tv *tv, uchar addr, uchar sub, uchar data, int both)
 }
 
 static ulong *
-riscpacked(ulong paddr, int fnum, int w, int h, int stride, ulong **lastjmp)
+riscpacked(ulong pa, int fnum, int w, int h, int stride, ulong **lastjmp)
 {
 	ulong *p, *pbase;
 	int i;
@@ -1224,7 +1224,7 @@ riscpacked(ulong paddr, int fnum, int w, int h, int stride, ulong **lastjmp)
 
 	for (i = 0; i != h / 2; i++) {
 		*p++ = riscwrite | w | riscwrite_sol | riscwrite_eol;
-		*p++ = paddr + i * 2 * stride;
+		*p++ = pa + i * 2 * stride;
 	}
 
 	*p++ = riscsync | riscsync_resync | riscsync_vro;
@@ -1235,7 +1235,7 @@ riscpacked(ulong paddr, int fnum, int w, int h, int stride, ulong **lastjmp)
 
 	for (i = 0; i != h / 2; i++) {
 		*p++ = riscwrite | w | riscwrite_sol | riscwrite_eol;
-		*p++ = paddr + (i * 2 + 1) * stride;
+		*p++ = pa + (i * 2 + 1) * stride;
 	}
 
 	// reset status.  you really need two instructions ;-(.
@@ -1248,7 +1248,7 @@ riscpacked(ulong paddr, int fnum, int w, int h, int stride, ulong **lastjmp)
 }
 
 static ulong *
-riscplanar411(ulong paddr, int fnum, int w, int h, ulong **lastjmp)
+riscplanar411(ulong pa, int fnum, int w, int h, ulong **lastjmp)
 {
 	ulong *p, *pbase, Cw, Yw, Ch;
 	uchar *Ybase, *Cbbase, *Crbase;
@@ -1260,7 +1260,7 @@ riscplanar411(ulong paddr, int fnum, int w, int h, ulong **lastjmp)
 	assert(p);
 
 	Yw = w;
-	Ybase = (uchar *)paddr;
+	Ybase = (uchar *)pa;
 	Cw = w >> 1;
 	Ch = h >> 1;
 	Cbbase = Ybase + Yw * h;
@@ -1302,7 +1302,7 @@ riscplanar411(ulong paddr, int fnum, int w, int h, ulong **lastjmp)
 }
 
 static ulong *
-riscplanar422(ulong paddr, int fnum, int w, int h, ulong **lastjmp)
+riscplanar422(ulong pa, int fnum, int w, int h, ulong **lastjmp)
 {
 	ulong *p, *pbase, Cw, Yw;
 	uchar *Ybase, *Cbbase, *Crbase;
@@ -1314,7 +1314,7 @@ riscplanar422(ulong paddr, int fnum, int w, int h, ulong **lastjmp)
 	assert(p);
 
 	Yw = w;
-	Ybase = (uchar *)paddr;
+	Ybase = (uchar *)pa;
 	Cw = w >> 1;
 	Cbbase = Ybase + Yw * h;
 	Crbase = Cbbase + Cw * h;
@@ -1357,7 +1357,7 @@ riscplanar422(ulong paddr, int fnum, int w, int h, ulong **lastjmp)
 }
 
 static ulong *
-riscaudio(ulong paddr, int nblocks, int bsize)
+riscaudio(ulong pa, int nblocks, int bsize)
 {
 	ulong *p, *pbase;
 	int i;
@@ -1372,7 +1372,7 @@ riscaudio(ulong paddr, int nblocks, int bsize)
 		*p++ = riscwrite | riscwrite_sol | riscwrite_eol | bsize | riscirq |
 				((i & 0xf) << risclabelshift_set) | 
 				((~i & 0xf) << risclabelshift_reset);
-		*p++ = paddr + i * bsize;
+		*p++ = pa + i * bsize;
 	}
 
 	*p++ = riscsync | riscsync_vro;
@@ -1556,7 +1556,7 @@ astop(Tv *tv)
 }
 
 static void
-vgastart(Tv *tv, ulong paddr, int stride)
+vgastart(Tv *tv, ulong pa, int stride)
 {
 	Frame *frame;
 
@@ -1568,7 +1568,7 @@ vgastart(Tv *tv, ulong paddr, int stride)
 	}
 
 	frame->fbase = nil;
-	frame->fstart = riscpacked(paddr, 0, ntsc_hactive * getbitspp(tv) / 8, 
+	frame->fstart = riscpacked(pa, 0, ntsc_hactive * getbitspp(tv) / 8, 
 						   ntsc_vactive, stride * getbitspp(tv) / 8, 
 						   &frame->fjmp);
 	*frame->fjmp = PADDR(frame->fstart);

+ 33 - 5
sys/src/9/pc/devvga.c

@@ -6,6 +6,7 @@
 #include "mem.h"
 #include "dat.h"
 #include "fns.h"
+#include "io.h"
 #include "../port/error.h"
 
 #define	Image	IMAGE
@@ -16,6 +17,7 @@
 
 enum {
 	Qdir,
+	Qvgabios,
 	Qvgactl,
 	Qvgaovl,
 	Qvgaovlctl,
@@ -23,6 +25,7 @@ enum {
 
 static Dirtab vgadir[] = {
 	".",	{ Qdir, 0, QTDIR },		0,	0550,
+	"vgabios",	{ Qvgabios, 0 },	0x100000, 0440,
 	"vgactl",		{ Qvgactl, 0 },		0,	0660,
 	"vgaovl",		{ Qvgaovl, 0 },		0,	0660,
 	"vgaovlctl",	{ Qvgaovlctl, 0 },	0, 	0660,
@@ -40,6 +43,7 @@ enum {
 	CMpalettedepth,
 	CMpanning,
 	CMsize,
+	CMtextmode,
 	CMtype,
 	CMunblank,
 };
@@ -56,6 +60,7 @@ static Cmdtab vgactlmsg[] = {
 	CMpalettedepth,	"palettedepth",	2,
 	CMpanning,	"panning",	2,
 	CMsize,		"size",		3,
+	CMtextmode,	"textmode",	1,
 	CMtype,		"type",		2,
 	CMunblank,	"unblank",	1,
 };
@@ -153,6 +158,14 @@ vgaread(Chan* c, void* a, long n, vlong off)
 	case Qdir:
 		return devdirread(c, a, n, vgadir, nelem(vgadir), devgen);
 
+	case Qvgabios:
+		if(offset >= 0x100000)
+			return 0;
+		if(offset+n >= 0x100000)
+			n = 0x100000 - offset;
+		memmove(a, (uchar*)kaddr(0)+offset, n);
+		return n;
+
 	case Qvgactl:
 		scr = &vgascreen[0];
 
@@ -186,7 +199,9 @@ vgaread(Chan* c, void* a, long n, vlong off)
 		len += snprint(p+len, READSTR-len, "hwaccel %s\n", hwaccel ? "on" : "off");
 		len += snprint(p+len, READSTR-len, "hwblank %s\n", hwblank ? "on" : "off");
 		len += snprint(p+len, READSTR-len, "panning %s\n", panning ? "on" : "off");
-		snprint(p+len, READSTR-len, "addr 0x%lux\n", scr->aperture);
+		len += snprint(p+len, READSTR-len, "addr p 0x%lux v 0x%p size 0x%ux\n", scr->paddr, scr->vaddr, scr->apsize);
+		USED(len);
+
 		n = readstr(offset, a, n, p);
 		poperror();
 		free(p);
@@ -233,7 +248,17 @@ vgactl(Cmdbuf *cb)
 			unlock(&cursor);
 			return;
 		}
-
+		if(strcmp(cb->f[1], "soft") == 0){
+			lock(&cursor);
+			swcursorinit();
+			if(scr->cur && scr->cur->disable)
+				scr->cur->disable(scr);
+			scr->cur = &swcursor;
+			if(scr->cur->enable)
+				scr->cur->enable(scr);
+			unlock(&cursor);
+			return;
+		}
 		for(i = 0; vgacur[i]; i++){
 			if(strcmp(cb->f[1], vgacur[i]->name))
 				continue;
@@ -261,9 +286,11 @@ vgactl(Cmdbuf *cb)
 		}
 		break;
 
+	case CMtextmode:
+		screeninit();
+		return;
+
 	case CMsize:
-		if(drawhasclients())
-			error(Ebusy);
 
 		x = strtoul(cb->f[1], &p, 0);
 		if(x == 0 || x > 2048)
@@ -291,6 +318,7 @@ vgactl(Cmdbuf *cb)
 		if(screensize(x, y, z, chan))
 			error(Egreg);
 		vgascreenwin(scr);
+		resetscreenimage();
 		cursoron(1);
 		return;
 
@@ -337,7 +365,7 @@ vgactl(Cmdbuf *cb)
 			align = 0;
 		else
 			align = strtoul(cb->f[2], 0, 0);
-		if(screenaperture(size, align))
+		if(screenaperture(size, align) < 0)
 			error("not enough free address space");
 		return;
 /*	

+ 3 - 4
sys/src/9/pc/dma.c

@@ -140,10 +140,9 @@ dmasetup(int chan, void *va, long len, int isread)
 	 *  if this isn't kernel memory or crossing 64k boundary or above 16 meg
 	 *  use the bounce buffer.
 	 */
-	pa = PADDR(va);
-	if((((ulong)va)&0xF0000000) != KZERO
-	|| (pa&0xFFFF0000) != ((pa+len)&0xFFFF0000)
-	|| pa >= 16*MB) {
+	if((ulong)va < KZERO 
+	|| ((pa=PADDR(va))&0xFFFF0000) != ((pa+len)&0xFFFF0000)
+	|| pa >= 16*MB){
 		if(xp->bva == nil)
 			return -1;
 		if(len > xp->blen)

+ 0 - 3
sys/src/9/pc/ether79c970.c

@@ -522,7 +522,6 @@ reset(Ether* ether)
 		ctlr->iow = io32w;
 	}else{
 		print("#l%d: card doesn't talk right\n", ether->ctlrno);
-iprint("#l%d: card doesn't talk right\n", ether->ctlrno);
 		iunlock(ctlr);
 		return -1;
 	}
@@ -539,8 +538,6 @@ iprint("#l%d: card doesn't talk right\n", ether->ctlrno);
 	default:
 		print("#l%d: unknown PCnet card version %.7ux\n",
 			ether->ctlrno, x&0xFFFFFFF);
-iprint("#l%d: unknown PCnet card version %.7ux\n",
-			ether->ctlrno, x&0xFFFFFFF);
 		iunlock(ctlr);
 		return -1;
 	}

+ 17 - 17
sys/src/9/pc/ether8139.c

@@ -243,7 +243,7 @@ rtl8139ifstat(Ether* edev, void* a, long n, ulong offset)
 
 	ctlr = edev->ctlr;
 	p = malloc(READSTR);
-	l = snprint(p, READSTR, "rcr %8.8uX\n", ctlr->rcr);
+	l = snprint(p, READSTR, "rcr %#8.8ux\n", ctlr->rcr);
 	l += snprint(p+l, READSTR-l, "ierrs %d\n", ctlr->ierrs);
 	l += snprint(p+l, READSTR-l, "etxth %d\n", ctlr->etxth);
 	l += snprint(p+l, READSTR-l, "taligned %d\n", ctlr->taligned);
@@ -255,20 +255,20 @@ rtl8139ifstat(Ether* edev, void* a, long n, ulong offset)
 	ctlr->rec += csr16r(ctlr, Rec);
 	l += snprint(p+l, READSTR-l, "rec %d\n", ctlr->rec);
 
-	l += snprint(p+l, READSTR-l, "Tcr %8.8luX\n", csr32r(ctlr, Tcr));
-	l += snprint(p+l, READSTR-l, "Config0 %2.2uX\n", csr8r(ctlr, Config0));
-	l += snprint(p+l, READSTR-l, "Config1 %2.2uX\n", csr8r(ctlr, Config1));
-	l += snprint(p+l, READSTR-l, "Msr %2.2uX\n", csr8r(ctlr, Msr));
-	l += snprint(p+l, READSTR-l, "Config3 %2.2uX\n", csr8r(ctlr, Config3));
-	l += snprint(p+l, READSTR-l, "Config4 %2.2uX\n", csr8r(ctlr, Config4));
-
-	l += snprint(p+l, READSTR-l, "Bmcr %4.4uX\n", csr16r(ctlr, Bmcr));
-	l += snprint(p+l, READSTR-l, "Bmsr %4.4uX\n", csr16r(ctlr, Bmsr));
-	l += snprint(p+l, READSTR-l, "Anar %4.4uX\n", csr16r(ctlr, Anar));
-	l += snprint(p+l, READSTR-l, "Anlpar %4.4uX\n", csr16r(ctlr, Anlpar));
-	l += snprint(p+l, READSTR-l, "Aner %4.4uX\n", csr16r(ctlr, Aner));
-	l += snprint(p+l, READSTR-l, "Nwaytr %4.4uX\n", csr16r(ctlr, Nwaytr));
-	snprint(p+l, READSTR-l, "Cscr %4.4uX\n", csr16r(ctlr, Cscr));
+	l += snprint(p+l, READSTR-l, "Tcr %#8.8lux\n", csr32r(ctlr, Tcr));
+	l += snprint(p+l, READSTR-l, "Config0 %#2.2ux\n", csr8r(ctlr, Config0));
+	l += snprint(p+l, READSTR-l, "Config1 %#2.2ux\n", csr8r(ctlr, Config1));
+	l += snprint(p+l, READSTR-l, "Msr %#2.2ux\n", csr8r(ctlr, Msr));
+	l += snprint(p+l, READSTR-l, "Config3 %#2.2ux\n", csr8r(ctlr, Config3));
+	l += snprint(p+l, READSTR-l, "Config4 %#2.2ux\n", csr8r(ctlr, Config4));
+
+	l += snprint(p+l, READSTR-l, "Bmcr %#4.4ux\n", csr16r(ctlr, Bmcr));
+	l += snprint(p+l, READSTR-l, "Bmsr %#4.4ux\n", csr16r(ctlr, Bmsr));
+	l += snprint(p+l, READSTR-l, "Anar %#4.4ux\n", csr16r(ctlr, Anar));
+	l += snprint(p+l, READSTR-l, "Anlpar %#4.4ux\n", csr16r(ctlr, Anlpar));
+	l += snprint(p+l, READSTR-l, "Aner %#4.4ux\n", csr16r(ctlr, Aner));
+	l += snprint(p+l, READSTR-l, "Nwaytr %#4.4ux\n", csr16r(ctlr, Nwaytr));
+	snprint(p+l, READSTR-l, "Cscr %#4.4ux\n", csr16r(ctlr, Cscr));
 	n = readstr(offset, a, n, p);
 	free(p);
 
@@ -589,7 +589,7 @@ rtl8139interrupt(Ureg*, void* arg)
 		 * other than try to reinitialise the chip?
 		 */
 		if((isr & (Serr|Timerbit)) != 0){
-			iprint("rtl8139interrupt: imr %4.4uX isr %4.4uX\n",
+			iprint("rtl8139interrupt: imr %#4.4ux isr %#4.4ux\n",
 				csr16r(ctlr, Imr), isr);
 			if(isr & Timerbit)
 				csr32w(ctlr, TimerInt, 0);
@@ -621,7 +621,7 @@ rtl8139match(Ether* edev, int id)
 			continue;
 
 		if(ioalloc(port, p->mem[0].size, 0, "rtl8139") < 0){
-			print("rtl8139: port 0x%uX in use\n", port);
+			print("rtl8139: port %#ux in use\n", port);
 			continue;
 		}
 

+ 8 - 7
sys/src/9/pc/ether8169.c

@@ -357,7 +357,8 @@ rtl8169mii(Ctlr* ctlr)
 		ctlr->mii = nil;
 		return -1;
 	}
-	print("oui %X phyno %d\n", phy->oui, phy->phyno);
+	USED(phy);
+	// print("oui %X phyno %d\n", phy->oui, phy->phyno);
 
 	miiane(ctlr->mii, ~0, ~0, ~0);
 
@@ -451,8 +452,8 @@ rtl8169ifstat(Ether* edev, void* a, long n, ulong offset)
 	l += snprint(p+l, READSTR-l, "punlc: %ud\n", ctlr->punlc);
 	l += snprint(p+l, READSTR-l, "fovw: %ud\n", ctlr->fovw);
 
-	l += snprint(p+l, READSTR-l, "tcr: %8.8uX\n", ctlr->tcr);
-	l += snprint(p+l, READSTR-l, "rcr: %8.8uX\n", ctlr->rcr);
+	l += snprint(p+l, READSTR-l, "tcr: %#8.8ux\n", ctlr->tcr);
+	l += snprint(p+l, READSTR-l, "rcr: %#8.8ux\n", ctlr->rcr);
 
 	if(ctlr->mii != nil && ctlr->mii->curphy != nil){
 		l += snprint(p+l, READSTR, "phy:   ");
@@ -460,7 +461,7 @@ rtl8169ifstat(Ether* edev, void* a, long n, ulong offset)
 			if(i && ((i & 0x07) == 0))
 				l += snprint(p+l, READSTR-l, "\n       ");
 			r = miimir(ctlr->mii, i);
-			l += snprint(p+l, READSTR-l, " %4.4uX", r);
+			l += snprint(p+l, READSTR-l, " %4.4ux", r);
 		}
 		snprint(p+l, READSTR-l, "\n");
 	}
@@ -811,7 +812,7 @@ rtl8169receive(Ether* edev)
 		else{
 			/*
 			 * Error stuff here.
-			print("control %8.8uX\n", control);
+			print("control %#8.8ux\n", control);
 			 */
 		}
 		d->control &= Eor;
@@ -865,7 +866,7 @@ rtl8169interrupt(Ureg*, void* arg)
 		 * Some of the reserved bits get set sometimes...
 		 */
 		if(isr & (Serr|Timeout|Tdu|Fovw|Punlc|Rdu|Ter|Tok|Rer|Rok))
-			panic("rtl8169interrupt: imr %4.4uX isr %4.4uX\n",
+			panic("rtl8169interrupt: imr %#4.4ux isr %#4.4ux\n",
 				csr16r(ctlr, Imr), isr);
 	}
 }
@@ -892,7 +893,7 @@ rtl8169match(Ether* edev, int id)
 			continue;
 
 		if(ioalloc(port, p->mem[0].size, 0, "rtl8169") < 0){
-			print("rtl8169: port 0x%uX in use\n", port);
+			print("rtl8169: port %#ux in use\n", port);
 			continue;
 		}
 

+ 6 - 6
sys/src/9/pc/ether82543gc.c

@@ -1243,7 +1243,8 @@ gc82543watchdog(void* arg)
 static void
 gc82543pci(void)
 {
-	int port, cls;
+	int cls;
+	void *mem;
 	Pcidev *p;
 	Ctlr *ctlr;
 
@@ -1262,8 +1263,8 @@ gc82543pci(void)
 			break;
 		}
 
-		port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
-		if(port == 0){
+		mem = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);
+		if(mem == 0){
 			print("gc82543: can't map %8.8luX\n", p->mem[0].bar);
 			continue;
 		}
@@ -1280,11 +1281,10 @@ gc82543pci(void)
 					cls*4);
 		}
 		ctlr = malloc(sizeof(Ctlr));
-		ctlr->port = port;
+		ctlr->port = p->mem[0].bar & ~0x0F;
 		ctlr->pcidev = p;
 		ctlr->id = (p->did<<16)|p->vid;
-
-		ctlr->nic = KADDR(ctlr->port);
+		ctlr->nic = mem;
 
 		if(gc82543reset(ctlr)){
 			free(ctlr);

+ 10 - 10
sys/src/9/pc/ether82557.c

@@ -290,7 +290,7 @@ command(Ctlr* ctlr, int c, int v)
 	if(timeo >= 100){
 		ctlr->command = -1;
 		iunlock(&ctlr->rlock);
-		iprint("i82557: command 0x%uX %uX timeout\n", c, v);
+		iprint("i82557: command %#ux %#ux timeout\n", c, v);
 		return;
 	}
 
@@ -462,7 +462,7 @@ ifstat(Ether* ether, void* a, long n, ulong offset)
 	for(i = 0; i < (1<<ctlr->eepromsz); i++){
 		if(i && ((i & 0x07) == 0))
 			len += snprint(p+len, READSTR-len, "\n       ");
-		len += snprint(p+len, READSTR-len, " %4.4uX", ctlr->eeprom[i]);
+		len += snprint(p+len, READSTR-len, " %4.4ux", ctlr->eeprom[i]);
 	}
 
 	if((ctlr->eeprom[6] & 0x1F00) && !(ctlr->eeprom[6] & 0x8000)){
@@ -471,7 +471,7 @@ ifstat(Ether* ether, void* a, long n, ulong offset)
 		for(i = 0; i < 6; i++){
 			static int miir(Ctlr*, int, int);
 
-			len += snprint(p+len, READSTR-len, " %4.4uX",
+			len += snprint(p+len, READSTR-len, " %4.4ux",
 				miir(ctlr, phyaddr, i));
 		}
 	}
@@ -523,7 +523,7 @@ txstart(Ether* ether)
 			ctlr->action = 0;
 		}
 		else{
-			print("#l%d: action 0x%uX\n", ether->ctlrno, ctlr->action);
+			print("#l%d: action %#ux\n", ether->ctlrno, ctlr->action);
 			ctlr->action = 0;
 			break;
 		}
@@ -630,14 +630,14 @@ receive(Ether* ether)
 			pbp = nil;
 			count = rfd->count & 0x3FFF;
 			if((count < ETHERMAXTU/4) && (pbp = iallocb(count))){
-				memmove(pbp->rp, bp->rp+sizeof(Rfd)-sizeof(rfd->data), count);
+				memmove(pbp->rp, bp->rp+offsetof(Rfd, data[0]), count);
 				pbp->wp = pbp->rp + count;
 
 				rfd->count = 0;
 				rfd->field = 0;
 			}
 			else if(xbp = rfdalloc(rfd->link)){
-				bp->rp += sizeof(Rfd)-sizeof(rfd->data);
+				bp->rp += offsetof(Rfd, data[0]);
 				bp->wp = bp->rp + count;
 
 				xbp->next = bp->next;
@@ -748,7 +748,7 @@ interrupt(Ureg*, void* arg)
 		}
 
 		if(status & (StatCX|StatFR|StatCNA|StatRNR|StatMDI|StatSWI))
-			panic("#l%d: status %uX\n", ether->ctlrno, status);
+			panic("#l%d: status %#ux\n", ether->ctlrno, status);
 	}
 }
 
@@ -955,7 +955,7 @@ i82557pci(void)
 		 */
 		port = p->mem[1].bar & ~0x01;
 		if(ioalloc(port, p->mem[1].size, 0, "i82557") < 0){
-			print("i82557: port 0x%uX in use\n", port);
+			print("i82557: port %#ux in use\n", port);
 			continue;
 		}
 
@@ -997,7 +997,7 @@ scanphy(Ctlr* ctlr)
 		oui <<= 6;
 		x = miir(ctlr, i, 3);
 		oui |= x>>10;
-		//print("phy%d: oui %uX reg1 %uX\n", i, oui, miir(ctlr, i, 1));
+		//print("phy%d: oui %#ux reg1 %#ux\n", i, oui, miir(ctlr, i, 1));
 
 		ctlr->eeprom[6] = i;
 		if(oui == 0xAA00)
@@ -1093,7 +1093,7 @@ reset(Ether* ether)
 		sum += x;
 	}
 	if(sum != 0xBABA)
-		print("#l%d: EEPROM checksum - 0x%4.4uX\n", ether->ctlrno, sum);
+		print("#l%d: EEPROM checksum - %#4.4ux\n", ether->ctlrno, sum);
 
 	/*
 	 * Eeprom[6] indicates whether there is a PHY and whether

+ 2 - 0
sys/src/9/pc/ether83815.c

@@ -81,6 +81,7 @@ enum {	/* cmdsts */
 
 enum {				/* Variants */
 	Nat83815	= (0x0020<<16)|0x100B,
+	Sis900 = (0x0630<<16)|0x1039,	/* untested */
 };
 
 typedef struct Ctlr Ctlr;
@@ -841,6 +842,7 @@ scanpci83815(void)
 			continue;
 
 		case Nat83815:
+		case Sis900:
 			break;
 		}
 

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

@@ -400,7 +400,7 @@ receive(Ether* ether)
 		 */
 		if(hdr.next < ctlr->pstart || hdr.next >= ctlr->pstop
 		  || len < 60 || len > sizeof(Etherpkt)){
-			print("dp8390: H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%lud\n",
+			print("dp8390: H%2.2ux+%2.2ux+%2.2ux+%2.2ux,%lud\n",
 				hdr.status, hdr.next, hdr.len0, hdr.len1, len);
 			regw(ctlr, Cr, Page0|RdABORT|Stp);
 			ringinit(ctlr);
@@ -588,7 +588,7 @@ interrupt(Ureg*, void* arg)
 		if(isr & (Txe|Ptx)){
 			r = regr(ctlr, Tsr);
 			if((isr & Txe) && (r & (Cdh|Fu|Crs|Abt))){
-				print("dp8390: Tsr#%2.2ux|", r);
+				print("dp8390: Tsr %#2.2ux", r);
 				ether->oerrs++;
 			}
 
@@ -686,7 +686,7 @@ multicast(void* arg, uchar *addr, int on)
 	if(reverse[1] == 0){
 		for(i = 0; i < 64; i++)
 			reverse[i] = ((i&1)<<5) | ((i&2)<<3) | ((i&4)<<1)
-					| ((i&8)>>1) | ((i&16)>>3) | ((i&32)>>5);
+				   | ((i&8)>>1) | ((i&16)>>3) | ((i&32)>>5);
 	}
 
 	/*

+ 5 - 5
sys/src/9/pc/etherdp83820.c

@@ -1114,7 +1114,7 @@ print("cfg %8.8uX pcicfg %8.8uX\n", ctlr->cfg, pcicfgr32(ctlr->pcidev, PciPCR));
 static void
 dp83820pci(void)
 {
-	int port;
+	void *mem;
 	Pcidev *p;
 	Ctlr *ctlr;
 
@@ -1130,18 +1130,18 @@ dp83820pci(void)
 			break;
 		}
 
-		port = upamalloc(p->mem[1].bar & ~0x0F, p->mem[1].size, 0);
-		if(port == 0){
+		mem = vmap(p->mem[1].bar & ~0x0F, p->mem[1].size);
+		if(mem == 0){
 			print("DP83820: can't map %8.8luX\n", p->mem[1].bar);
 			continue;
 		}
 
 		ctlr = malloc(sizeof(Ctlr));
-		ctlr->port = port;
+		ctlr->port = p->mem[1].bar & ~0x0F;
 		ctlr->pcidev = p;
 		ctlr->id = (p->did<<16)|p->vid;
 
-		ctlr->nic = KADDR(ctlr->port);
+		ctlr->nic = mem;
 		if(dp83820reset(ctlr)){
 			free(ctlr);
 			continue;

+ 4 - 4
sys/src/9/pc/etherelnk3.c

@@ -1485,15 +1485,15 @@ tcm59Xpci(void)
 			break;
 		case 0x5157:
 			ctlr->eepromcmd = EepromRead8bRegister;
-			ctlr->cbfnpa = upamalloc(p->mem[2].bar, p->mem[2].size, 0);
+			ctlr->cbfnpa = p->mem[2].bar&~0x0F;
+			ctlr->cbfn = vmap(p->mem[2].bar&~0x0F, p->mem[2].size);
 			break;
 		case 0x6056:
 			ctlr->eepromcmd = EepromReadOffRegister;
-			ctlr->cbfnpa = upamalloc(p->mem[2].bar, p->mem[2].size, 0);
+			ctlr->cbfnpa = p->mem[2].bar&~0x0F;
+			ctlr->cbfn = vmap(p->mem[2].bar&~0x0F, p->mem[2].size);
 			break;
 		}
-		if(ctlr->cbfnpa != 0)
-			ctlr->cbfn = KADDR(ctlr->cbfnpa);
 		pcisetbme(p);
 	}
 }

+ 6 - 6
sys/src/9/pc/etherga620.c

@@ -758,7 +758,7 @@ ga620init(Ether* edev)
 	 * memory it is accessed via the Local Memory Window; with a send
 	 * ring size of 128 the window covers the whole ring and then need
 	 * only be set once:
-	 *	ctlr->sr = KADDR(ctlr->port+Lmw);
+	 *	ctlr->sr = (uchar*)ctlr->nic+Lmw;
 	 *	ga620lmw(ctlr, Sr, nil, sizeof(Sbd)*Nsr);
 	 *	ctlr->gib->srcb.addr.lo = Sr;
 	 * There is nowhere in the Sbd to hold the Block* associated
@@ -1114,7 +1114,7 @@ ga620reset(Ctlr* ctlr)
 static void
 ga620pci(void)
 {
-	int port;
+	void *mem;
 	Pcidev *p;
 	Ctlr *ctlr;
 
@@ -1135,18 +1135,18 @@ ga620pci(void)
 			break;
 		}
 
-		port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
-		if(port == 0){
+		mem = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);
+		if(mem == 0){
 			print("ga620: can't map %8.8luX\n", p->mem[0].bar);
 			continue;
 		}
 
 		ctlr = malloc(sizeof(Ctlr));
-		ctlr->port = port;
+		ctlr->port = p->mem[0].bar & ~0x0F;
 		ctlr->pcidev = p;
 		ctlr->id = (p->did<<16)|p->vid;
 
-		ctlr->nic = KADDR(ctlr->port);
+		ctlr->nic = mem;
 		if(ga620reset(ctlr)){
 			free(ctlr);
 			continue;

+ 10 - 8
sys/src/9/pc/etherigbe.c

@@ -439,7 +439,7 @@ enum {
 
 typedef struct Ctlr Ctlr;
 typedef struct Ctlr {
-	int	port;
+	ulong	port;
 	Pcidev*	pcidev;
 	Ctlr*	next;
 	int	active;
@@ -1468,7 +1468,8 @@ igbemii(Ctlr* ctlr)
 		ctlr->mii = nil;
 		return -1;
 	}
-	print("oui %X phyno %d\n", phy->oui, phy->phyno);
+	USED(phy);
+	// print("oui %X phyno %d\n", phy->oui, phy->phyno);
 
 	/*
 	 * 8254X-specific PHY registers not in 802.3:
@@ -1848,10 +1849,11 @@ igbereset(Ctlr* ctlr)
 static void
 igbepci(void)
 {
-	int port, cls;
+	int cls;
 	Pcidev *p;
 	Ctlr *ctlr;
-
+	void *mem;
+	
 	p = nil;
 	while(p = pcimatch(p, 0, 0)){
 		if(p->ccrb != 0x02 || p->ccru != 0)
@@ -1874,8 +1876,8 @@ igbepci(void)
 			break;
 		}
 
-		port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
-		if(port == 0){
+		mem = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);
+		if(mem == nil){
 			print("igbe: can't map %8.8luX\n", p->mem[0].bar);
 			continue;
 		}
@@ -1893,11 +1895,11 @@ igbepci(void)
 				break;
 		}
 		ctlr = malloc(sizeof(Ctlr));
-		ctlr->port = port;
+		ctlr->port = p->mem[0].bar & ~0x0F;
 		ctlr->pcidev = p;
 		ctlr->id = (p->did<<16)|p->vid;
 		ctlr->cls = cls*4;
-		ctlr->nic = KADDR(ctlr->port);
+		ctlr->nic = mem;
 
 		if(igbereset(ctlr)){
 			free(ctlr);

+ 1 - 1
sys/src/9/pc/ethervt6102.c

@@ -925,7 +925,7 @@ vt6102reset(Ctlr* ctlr)
 		ctlr->mii = nil;
 		return -1;
 	}
-	print("oui %X phyno %d\n", phy->oui, phy->phyno);
+	// print("oui %X phyno %d\n", phy->oui, phy->phyno);
 
 	//miiane(ctlr->mii, ~0, ~0, ~0);
 

+ 6 - 5
sys/src/9/pc/etherwavelan.c

@@ -87,6 +87,7 @@ static struct {
 	int did;
 } wavelanpci[] = {
 	0x1260, 0x3873,	/* Intersil Prism2.5 */
+	0x1737,	0x0019,	/* Linksys WPC-11 untested */
 };
 
 static Ctlr *ctlrhead, *ctlrtail;
@@ -95,7 +96,7 @@ static void
 wavelanpciscan(void)
 {
 	int i;
-	ulong pa;
+	void *mem;
 	Pcidev *p;
 	Ctlr *ctlr;
 
@@ -117,13 +118,13 @@ wavelanpciscan(void)
 
 		ctlr = malloc(sizeof(Ctlr));
 		ctlr->pcidev = p;
-		pa = upamalloc(p->mem[0].bar&~0xF, p->mem[0].size, 0);
-		if(pa == 0){
-			print("wavelanpci: %.4ux %.4ux: upamalloc 0x%.8lux %d failed\n", p->vid, p->did, p->mem[0].bar&~0xF, p->mem[0].size);
+		mem = vmap(p->mem[0].bar&~0xF, p->mem[0].size);
+		if(mem == nil){
+			print("wavelanpci: %.4ux %.4ux: vmap 0x%.8lux %d failed\n", p->vid, p->did, p->mem[0].bar&~0xF, p->mem[0].size);
 			free(ctlr);
 			continue;
 		}
-		ctlr->mmb = (ushort*)KADDR(pa);
+		ctlr->mmb = mem;
 		if(ctlrhead != nil)
 			ctlrtail->next = ctlr;
 		else

+ 24 - 10
sys/src/9/pc/fns.h

@@ -3,9 +3,7 @@
 void	aamloop(int);
 Dirtab*	addarchfile(char*, int, long(*)(Chan*,void*,long,vlong), long(*)(Chan*,void*,long,vlong));
 void	archinit(void);
-void	bootargs(ulong);
-int	cistrcmp(char*, char*);
-int	cistrncmp(char*, char*, int);
+void	bootargs(void*);
 void	clockintr(Ureg*, void*);
 void	(*coherence)(void);
 void	cpuid(char*, int*, int*);
@@ -46,11 +44,13 @@ void	i8253init(void);
 void	i8253link(void);
 uvlong	i8253read(uvlong*);
 void	i8253timerset(uvlong);
+int	i8259disable(int);
+int	i8259enable(Vctl*);
 void	i8259init(void);
 int	i8259isr(int);
-int	i8259enable(Vctl*);
+void	i8259on(void);
+void	i8259off(void);
 int	i8259vecno(int);
-int	i8259disable(int);
 void	idle(void);
 void	idlehands(void);
 int	inb(int);
@@ -61,6 +61,9 @@ ulong	inl(int);
 void	insl(int, void*, int);
 int	intrdisable(int, void (*)(Ureg *, void *), void*, int, char*);
 void	intrenable(int, void (*)(Ureg*, void*), void*, int, char*);
+void	introff(void);
+void	intron(void);
+void	invlpg(ulong);
 void	iofree(int);
 void	ioinit(void);
 int	iounused(int, int);
@@ -68,6 +71,7 @@ int	ioalloc(int, int, int, char*);
 int	ioreserve(int, int, int, char*);
 int	iprint(char*, ...);
 int	isaconfig(char*, int, ISAConf*);
+void*	kaddr(ulong);
 void	kbdenable(void);
 void	kbdinit(void);
 #define	kmapinval()
@@ -82,10 +86,9 @@ void	mathinit(void);
 void	mb386(void);
 void	mb586(void);
 void	meminit(void);
+void	memorysummary(void);
 #define mmuflushtlb(pdb) putcr3(pdb)
 void	mmuinit(void);
-ulong	mmukmap(ulong, ulong, int);
-int	mmukmapsync(ulong);
 ulong*	mmuwalk(ulong*, ulong, int, int);
 uchar	nvramread(int);
 void	nvramwrite(int, uchar);
@@ -95,6 +98,7 @@ void	outs(int, ushort);
 void	outss(int, void*, int);
 void	outl(int, ulong);
 void	outsl(int, void*, int);
+ulong	paddr(void*);
 int	pciscan(int, Pcidev**);
 ulong	pcibarsize(Pcidev*, int);
 int	pcicfgr8(Pcidev*, int);
@@ -122,33 +126,43 @@ int	(*_pcmspecial)(char *, ISAConf *);
 void	pcmspecialclose(int);
 void	(*_pcmspecialclose)(int);
 void	pcmunmap(int, PCMmap*);
+int	pdbmap(ulong*, ulong, ulong, int);
 void	procrestore(Proc*);
 void	procsave(Proc*);
 void	procsetup(Proc*);
 void	putcr3(ulong);
 void	putcr4(ulong);
+void*	rampage(void);
 void	rdmsr(int, vlong*);
+void	realmode(Ureg*);
 void	screeninit(void);
 void	(*screenputs)(char*, int);
 void	syncclock(void);
+void*	tmpmap(Page*);
+void	tmpunmap(void*);
 void	touser(void*);
 void	trapenable(int, void (*)(Ureg*, void*), void*, char*);
 void	trapinit(void);
+void	trapinit0(void);
 int	tas(void*);
 uvlong	tscticks(uvlong*);
 ulong	umbmalloc(ulong, int, int);
 void	umbfree(ulong, int);
 ulong	umbrwmalloc(ulong, int, int);
 void	umbrwfree(ulong, int);
-ulong	upamalloc(ulong, int, int);
+ulong	upaalloc(int, int);
 void	upafree(ulong, int);
+void	upareserve(ulong, int);
 #define	userureg(ur) (((ur)->cs & 0xFFFF) == UESEL)
 void	vectortable(void);
+void*	vmap(ulong, int);
+int	vmapsync(ulong);
+void	vunmap(void*, int);
 void	wrmsr(int, vlong);
 int	xchgw(ushort*, int);
 
 #define	waserror()	(up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
-#define KADDR(a)	((void*)((ulong)(a)|KZERO))
-#define PADDR(a)	((ulong)(a)&~KZERO)
+#define	KADDR(a)	kaddr(a)
+#define PADDR(a)	paddr((void*)(a))
 
 #define	dcflush(a, b)

+ 15 - 0
sys/src/9/pc/i8259.c

@@ -197,3 +197,18 @@ i8259disable(int irq)
 	iunlock(&i8259lock);
 	return 0;
 }
+
+void
+i8259on(void)
+{
+	outb(Int0aux, i8259mask&0xFF);
+	outb(Int1aux, (i8259mask>>8)&0xFF);
+}
+
+void
+i8259off(void)
+{
+	outb(Int0aux, 0xFF);
+	outb(Int1aux, 0xFF);
+}
+

+ 269 - 21
sys/src/9/pc/l.s

@@ -1,4 +1,6 @@
 #include "mem.h"
+#include "/sys/src/boot/pc/x16.h"
+#undef DELAY
 
 #define PADDR(a)	((a) & ~KZERO)
 #define KADDR(a)	(KZERO|(a))
@@ -13,6 +15,7 @@
 #define RDTSC 		BYTE $0x0F; BYTE $0x31	/* RDTSC, result in AX/DX (lo/hi) */
 #define RDMSR		BYTE $0x0F; BYTE $0x32	/* RDMSR, result in AX/DX (lo/hi) */
 #define HLT		BYTE $0xF4
+#define INVLPG	BYTE $0x0F; BYTE $0x01; BYTE $0x39	/* INVLPG (%ecx) */
 
 /*
  * Macros for calculating offsets within the page directory base
@@ -27,8 +30,8 @@
  * 9load currently sets up the mmu, however the first 16MB of memory is identity
  * mapped, so behave as if the mmu was not setup
  */
-TEXT _start0x80100020(SB), $0
-	MOVL	$_start0x00100020(SB), AX
+TEXT _startKADDR(SB), $0
+	MOVL	$_startPADDR(SB), AX
 	ANDL	$~KZERO, AX
 	JMP*	AX
 
@@ -40,10 +43,10 @@ TEXT _multibootheader(SB), $0
 	LONG	$0x00010003			/* flags */
 	LONG	$-(0x1BADB002 + 0x00010003)	/* checksum */
 	LONG	$_multibootheader-KZERO(SB)	/* header_addr */
-	LONG	$_start0x80100020-KZERO(SB)	/* load_addr */
+	LONG	$_startKADDR-KZERO(SB)		/* load_addr */
 	LONG	$edata-KZERO(SB)		/* load_end_addr */
 	LONG	$end-KZERO(SB)			/* bss_end_addr */
-	LONG	$_start0x80100020-KZERO(SB)	/* entry_addr */
+	LONG	$_startKADDR-KZERO(SB)		/* entry_addr */
 	LONG	$0				/* mode_type */
 	LONG	$0				/* width */
 	LONG	$0				/* height */
@@ -51,7 +54,7 @@ TEXT _multibootheader(SB), $0
 
 /*
  * In protected mode with paging turned off and segment registers setup to linear map all memory.
- * Entered via a jump to 0x00100020, the physical address of the virtual kernel entry point of 0x80100020
+ * Entered via a jump to PADDR(entry), the physical address of the virtual kernel entry point of KADDR(entry)
  * Make the basic page tables for processor 0. Four pages are needed for the basic set:
  * a page directory, a page table for mapping the first 4MB of physical memory to KZERO,
  * and virtual and physical pages for mapping the Mach structure.
@@ -60,7 +63,7 @@ TEXT _multibootheader(SB), $0
  * identity mapping is removed once the MMU is going and the JMP has been made
  * to virtual memory.
  */
-TEXT _start0x00100020(SB), $0
+TEXT _startPADDR(SB), $0
 	CLI					/* make sure interrupts are off */
 
 	/* set up the gdt so we have sane plan 9 style gdts. */
@@ -109,10 +112,21 @@ TEXT tgdt(SB), $0
  *  that's needed as we start executing in physical addresses. 
  */
 TEXT tgdtptr(SB), $0
-
 	WORD	$(3*8)
 	LONG	$tgdt-KZERO(SB)
 
+TEXT m0rgdtptr(SB), $0
+	WORD	$(NGDT*8-1)
+	LONG	$(CPU0GDT-KZERO)
+
+TEXT m0gdtptr(SB), $0
+	WORD	$(NGDT*8-1)
+	LONG	$CPU0GDT
+
+TEXT m0idtptr(SB), $0
+	WORD $(256*8-1)
+	LONG $IDTADDR
+
 TEXT mode32bit(SB), $0
 	/* At this point, the GDT setup is done. */
 
@@ -126,7 +140,7 @@ TEXT mode32bit(SB), $0
 
 	MOVL	$PADDR(CPU0PDB), AX
 	ADDL	$PDO(KZERO), AX			/* page directory offset for KZERO */
-	MOVL	$PADDR(CPU0PTE), (AX)		/* PTE's for 0x80000000 */
+	MOVL	$PADDR(CPU0PTE), (AX)		/* PTE's for KZERO */
 	MOVL	$(PTEWRITE|PTEVALID), BX	/* page permissions */
 	ORL	BX, (AX)
 
@@ -211,6 +225,234 @@ _idle:
 	HLT
 	JMP	_idle
 
+/*
+ * Save registers.
+ */
+TEXT saveregs(SB), $0
+	/* appease 8l */
+	SUBL $32, SP
+	POPL AX
+	POPL AX
+	POPL AX
+	POPL AX
+	POPL AX
+	POPL AX
+	POPL AX
+	POPL AX
+	
+	PUSHL	AX
+	PUSHL	BX
+	PUSHL	CX
+	PUSHL	DX
+	PUSHL	BP
+	PUSHL	DI
+	PUSHL	SI
+	PUSHFL
+
+	XCHGL	32(SP), AX	/* swap return PC and saved flags */
+	XCHGL	0(SP), AX
+	XCHGL	32(SP), AX
+	RET
+
+TEXT restoreregs(SB), $0
+	/* appease 8l */
+	PUSHL	AX
+	PUSHL	AX
+	PUSHL	AX
+	PUSHL	AX
+	PUSHL	AX
+	PUSHL	AX
+	PUSHL	AX
+	PUSHL	AX
+	ADDL	$32, SP
+	
+	XCHGL	32(SP), AX	/* swap return PC and saved flags */
+	XCHGL	0(SP), AX
+	XCHGL	32(SP), AX
+
+	POPFL
+	POPL	SI
+	POPL	DI
+	POPL	BP
+	POPL	DX
+	POPL	CX
+	POPL	BX
+	POPL	AX
+	RET
+
+/*
+ * Assumed to be in protected mode at time of call.
+ * Switch to real mode, execute an interrupt, and
+ * then switch back to protected mode.  
+ *
+ * Assumes:
+ *
+ *	- no device interrupts are going to come in
+ *	- 0-16MB is identity mapped in page tables
+ *	- realmode() has copied us down from 0x100000 to 0x8000
+ *	- can use code segment 0x0800 in real mode
+ *		to get at l.s code
+ *	- l.s code is less than 1 page
+ */
+#define RELOC	(RMCODE-KTZERO)
+
+TEXT realmodeidtptr(SB), $0
+	WORD	$(4*256-1)
+	LONG	$0
+
+TEXT realmode0(SB), $0
+	CALL	saveregs(SB)
+
+	/* switch to low code address */
+	LEAL	physcode-KZERO(SB), AX
+	JMP *AX
+
+TEXT physcode(SB), $0
+
+	/* switch to low stack */
+	MOVL	SP, AX
+	MOVL	$0x7C00, SP
+	PUSHL	AX
+
+	/* change gdt to physical pointer */
+	MOVL	m0rgdtptr-KZERO(SB), GDTR
+
+	/* load IDT with real-mode version*/
+	MOVL	realmodeidtptr-KZERO(SB), IDTR
+
+	/* edit INT $0x00 instruction below */
+	MOVL	$(RMUADDR-KZERO+48), AX	/* &rmu.trap */
+	MOVL	(AX), AX
+	MOVB	AX, realmodeintrinst+(-KZERO+1+RELOC)(SB)
+
+	/* disable paging */
+	MOVL	CR0, AX
+	ANDL	$0x7FFFFFFF, AX
+	MOVL	AX, CR0
+	/* JMP .+2 to clear prefetch queue*/
+	BYTE $0xEB; BYTE $0x00
+
+	/* jump to 16-bit code segment */
+/*	JMPFAR	SELECTOR(KESEG16, SELGDT, 0):$again16bit(SB) /**/
+	 BYTE	$0xEA
+	 LONG	$again16bit-KZERO(SB)
+	 WORD	$SELECTOR(KESEG16, SELGDT, 0)
+
+TEXT again16bit(SB), $0
+	/*
+	 * Now in 16-bit compatibility mode.
+	 * These are 32-bit instructions being interpreted
+	 * as 16-bit instructions.  I'm being lazy and
+	 * not using the macros because I know when
+	 * the 16- and 32-bit instructions look the same
+	 * or close enough.
+	 */
+
+	/* disable protected mode and jump to real mode cs */
+	OPSIZE; MOVL CR0, AX
+	OPSIZE; XORL BX, BX
+	OPSIZE; INCL BX
+	OPSIZE; XORL BX, AX
+	OPSIZE; MOVL AX, CR0
+
+	/* JMPFAR 0x0800:now16real */
+	 BYTE $0xEA
+	 WORD	$now16real-KZERO(SB)
+	 WORD	$0x0800
+
+TEXT now16real(SB), $0
+	/* copy the registers for the bios call */
+	LWI(0x0000, rAX)
+	MOVW	AX,SS
+	LWI(RMUADDR, rBP)
+	
+	/* offsets are in Ureg */
+	LXW(44, xBP, rAX)
+	MOVW	AX, DS
+	LXW(40, xBP, rAX)
+	MOVW	AX, ES
+
+	OPSIZE; LXW(0, xBP, rDI)
+	OPSIZE; LXW(4, xBP, rSI)
+	OPSIZE; LXW(16, xBP, rBX)
+	OPSIZE; LXW(20, xBP, rDX)
+	OPSIZE; LXW(24, xBP, rCX)
+	OPSIZE; LXW(28, xBP, rAX)
+
+	CLC
+
+TEXT realmodeintrinst(SB), $0
+	INT $0x00
+
+	/* save the registers after the call */
+
+	LWI(0x7bfc, rSP)
+	OPSIZE; PUSHFL
+	OPSIZE; PUSHL AX
+
+	LWI(0, rAX)
+	MOVW	AX,SS
+	LWI(RMUADDR, rBP)
+	
+	OPSIZE; SXW(rDI, 0, xBP)
+	OPSIZE; SXW(rSI, 4, xBP)
+	OPSIZE; SXW(rBX, 16, xBP)
+	OPSIZE; SXW(rDX, 20, xBP)
+	OPSIZE; SXW(rCX, 24, xBP)
+	OPSIZE; POPL AX
+	OPSIZE; SXW(rAX, 28, xBP)
+
+	MOVW	DS, AX
+	OPSIZE; SXW(rAX, 44, xBP)
+	MOVW	ES, AX
+	OPSIZE; SXW(rAX, 40, xBP)
+
+	OPSIZE; POPL AX
+	OPSIZE; SXW(rAX, 64, xBP)	/* flags */
+
+	/* re-enter protected mode and jump to 32-bit code */
+	OPSIZE; MOVL $1, AX
+	OPSIZE; MOVL AX, CR0
+	
+/*	JMPFAR	SELECTOR(KESEG, SELGDT, 0):$again32bit(SB) /**/
+	 OPSIZE
+	 BYTE $0xEA
+	 LONG	$again32bit-KZERO(SB)
+	 WORD	$SELECTOR(KESEG, SELGDT, 0)
+
+TEXT again32bit(SB), $0
+	MOVW	$SELECTOR(KDSEG, SELGDT, 0),AX
+	MOVW	AX,DS
+	MOVW	AX,SS
+	MOVW	AX,ES
+	MOVW	AX,FS
+	MOVW	AX,GS
+
+	/* enable paging and jump to kzero-address code */
+	MOVL	CR0, AX
+	ORL	$0x80000000, AX
+	MOVL	AX, CR0
+	LEAL	again32kzero(SB), AX
+	JMP*	AX
+
+TEXT again32kzero(SB), $0
+	/* breathe a sigh of relief - back in 32-bit protected mode */
+
+	/* switch to old stack */	
+	PUSHL	AX	/* match popl below for 8l */
+	MOVL	$0x7BFC, SP
+	POPL	SP
+
+	/* restore idt */
+	MOVL	m0idtptr(SB),IDTR
+
+	/* restore gdt */
+	MOVL	m0gdtptr(SB), GDTR
+
+	CALL	restoreregs(SB)
+	RET
+
+/*
 /*
  * Port I/O.
  *	in[bsl]		input a byte|short|long
@@ -347,6 +589,12 @@ TEXT putcr4(SB), $0
 	MOVL	AX, CR4
 	RET
 
+TEXT invlpg(SB), $0
+	/* 486+ only */
+	MOVL	va+0(FP), CX
+	INVLPG
+	RET
+
 TEXT _cycles(SB), $0				/* time stamp counter */
 	RDTSC
 	MOVL	vlong+0(FP), CX			/* &vlong */
@@ -442,21 +690,21 @@ _aamloop:
  * FNxxx variations) so WAIT instructions must be explicitly placed in the
  * code as necessary.
  */
-#define	FPOFF(l)							;\
-	MOVL	CR0, AX 					 	;\
-	ANDL	$0xC, AX			/* EM, TS */	 	;\
-	CMPL	AX, $0x8					 	;\
-	JEQ 	l						 	;\
-	WAIT							 	;\
-l:								 	;\
-	MOVL	CR0, AX							;\
-	ANDL	$~0x4, AX			/* EM=0 */		;\
-	ORL	$0x28, AX			/* NE=1, TS=1 */	;\
+#define	FPOFF(l)						 ;\
+	MOVL	CR0, AX 					 ;\
+	ANDL	$0xC, AX			/* EM, TS */	 ;\
+	CMPL	AX, $0x8					 ;\
+	JEQ 	l						 ;\
+	WAIT							 ;\
+l:								 ;\
+	MOVL	CR0, AX						 ;\
+	ANDL	$~0x4, AX			/* EM=0 */	 ;\
+	ORL	$0x28, AX			/* NE=1, TS=1 */ ;\
 	MOVL	AX, CR0
 
-#define	FPON								;\
-	MOVL	CR0, AX							;\
-	ANDL	$~0xC, AX			/* EM=0, TS=0 */	;\
+#define	FPON							 ;\
+	MOVL	CR0, AX						 ;\
+	ANDL	$~0xC, AX			/* EM=0, TS=0 */ ;\
 	MOVL	AX, CR0
 	
 TEXT fpoff(SB), $0				/* disable */

+ 42 - 17
sys/src/9/pc/main.c

@@ -29,6 +29,7 @@ char *confname[MAXCONF];
 char *confval[MAXCONF];
 int nconf;
 uchar *sp;	/* user stack of init proc */
+int delaylink;
 
 static void
 options(void)
@@ -69,6 +70,7 @@ options(void)
 	}
 }
 
+void mmuinit0(void);
 void
 main(void)
 {
@@ -81,6 +83,9 @@ main(void)
 
 	print("\nPlan 9\n");
 
+	trapinit0();
+	mmuinit0();
+
 	kbdinit();
 	i8253init();
 	cpuidentify();
@@ -101,7 +106,11 @@ main(void)
 		arch->clockenable();
 	procinit0();
 	initseg();
-	links();
+	if(delaylink){
+		bootlinks();
+		pcimatch(0, 0, 0);
+	}else
+		links();
 	conf.monitor = 1;
 	chandevreset();
 	pageinit();
@@ -194,9 +203,9 @@ init0(void)
 void
 userinit(void)
 {
+	void *v;
 	Proc *p;
 	Segment *s;
-	KMap *k;
 	Page *pg;
 
 	p = newproc();
@@ -226,14 +235,18 @@ userinit(void)
 
 	/*
 	 * User Stack
+	 *
+	 * N.B. cannot call newpage() with clear=1, because pc kmap
+	 * requires up != nil.  use tmpmap instead.
 	 */
 	s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
 	p->seg[SSEG] = s;
-	pg = newpage(1, 0, USTKTOP-BY2PG);
+	pg = newpage(0, 0, USTKTOP-BY2PG);
+	v = tmpmap(pg);
+	memset(v, 0, BY2PG);
 	segpage(s, pg);
-	k = kmap(pg);
-	bootargs(VA(k));
-	kunmap(k);
+	bootargs(v);
+	tmpunmap(v);
 
 	/*
 	 * Text
@@ -241,12 +254,13 @@ userinit(void)
 	s = newseg(SG_TEXT, UTZERO, 1);
 	s->flushme++;
 	p->seg[TSEG] = s;
-	pg = newpage(1, 0, UTZERO);
+	pg = newpage(0, 0, UTZERO);
 	memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
 	segpage(s, pg);
-	k = kmap(s->map[0]->pages[0]);
-	memmove((ulong*)VA(k), initcode, sizeof initcode);
-	kunmap(k);
+	v = tmpmap(pg);
+	memset(v, 0, BY2PG);
+	memmove(v, initcode, sizeof initcode);
+	tmpunmap(v);
 
 	ready(p);
 }
@@ -263,7 +277,7 @@ pusharg(char *p)
 }
 
 void
-bootargs(ulong base)
+bootargs(void *base)
 {
  	int i, ac;
 	uchar *av[32];
@@ -295,9 +309,9 @@ bootargs(ulong base)
 	sp -= (ac+1)*sizeof(sp);
 	lsp = (uchar**)sp;
 	for(i = 0; i < ac; i++)
-		*lsp++ = av[i] + ((USTKTOP - BY2PG) - base);
+		*lsp++ = av[i] + ((USTKTOP - BY2PG) - (ulong)base);
 	*lsp = 0;
-	sp += (USTKTOP - BY2PG) - base - sizeof(ulong);
+	sp += (USTKTOP - BY2PG) - (ulong)base - sizeof(ulong);
 }
 
 char*
@@ -344,7 +358,7 @@ void
 confinit(void)
 {
 	char *p;
-	int userpcnt;
+	int i, userpcnt;
 	ulong kpages;
 
 	if(p = getconf("*kernelpercent"))
@@ -352,7 +366,9 @@ confinit(void)
 	else
 		userpcnt = 0;
 
-	conf.npage = conf.npage0 + conf.npage1;
+	conf.npage = 0;
+	for(i=0; i<nelem(conf.mem); i++)
+		conf.npage += conf.mem[i].npage;
 
 	conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
 	if(cpuserver)
@@ -397,6 +413,14 @@ confinit(void)
 		if(conf.npage*BY2PG < 16*MB)
 			imagmem->minarena = 4*1024*1024;
 	}
+
+	/*
+	 * can't go past the end of virtual memory
+	 * (ulong)-KZERO is 2^32 - KZERO
+	 */
+	if(kpages > ((ulong)-KZERO)/BY2PG)
+		kpages = ((ulong)-KZERO)/BY2PG;
+
 	conf.upages = conf.npage - kpages;
 	conf.ialloc = (kpages/2)*BY2PG;
 
@@ -493,7 +517,7 @@ matherror(Ureg *ur, void*)
  *  math coprocessor emulation fault
  */
 static void
-mathemu(Ureg*, void*)
+mathemu(Ureg *ureg, void*)
 {
 	if(up->fpstate & FPillegal){
 		/* someone did floating point in a note handler */
@@ -521,7 +545,8 @@ mathemu(Ureg*, void*)
 		up->fpstate = FPactive;
 		break;
 	case FPactive:
-		panic("math emu");
+		panic("math emu pid %ld %s pc 0x%lux", 
+			up->pid, up->text, ureg->pc);
 		break;
 	}
 }

+ 36 - 25
sys/src/9/pc/mem.h

@@ -11,6 +11,7 @@
 #define	BY2V		8			/* bytes per double word */
 #define	BY2PG		4096			/* bytes per page */
 #define	WD2PG		(BY2PG/BY2WD)		/* words per page */
+#define	BY2XPG		(4096*1024)	/* bytes per big page */
 #define	PGSHIFT		12			/* log(BY2PG) */
 #define	ROUND(s, sz)	(((s)+((sz)-1))&~((sz)-1))
 #define	PGROUND(s)	ROUND(s, BY2PG)
@@ -26,40 +27,48 @@
 #define	MS2HZ		(1000/HZ)		/* millisec per clock tick */
 #define	TK2SEC(t)	((t)/HZ)		/* ticks to seconds */
 
-/*
- * Fundamental addresses
- */
-#define	IDTADDR		0x80000800		/* idt */
-#define	REBOOTADDR	0x00001000		/* reboot code - physical address */
-#define	APBOOTSTRAP	0x80001000		/* AP bootstrap code */
-#define	CONFADDR	0x80001200		/* info passed from boot loader */
-#define	CPU0PDB		0x80002000		/* bootstrap processor PDB */
-#define	CPU0PTE		0x80003000		/* bootstrap processor PTE's for 0-4MB */
-#define	CPU0GDT		0x80004000		/* bootstrap processor GDT */
-#define	MACHADDR	0x80005000		/* as seen by current processor */
-#define	CPU0MACH	0x80006000		/* Mach for bootstrap processor */
-#define	MACHSIZE	BY2PG
-/*
- * N.B.  ramscan knows that CPU0MACH+BY2PG is the end of reserved data
- * N.B.  _start0x00100020 knows that CPU0PDB is the first reserved page
- * and that there are 5 of them.
- */
-
 /*
  *  Address spaces
- *
- *  User is at 0-2GB
- *  Kernel is at 2GB-4GB
  */
+#define	KZERO		0xF0000000		/* base of kernel address space */
+#define	KTZERO		(KZERO+0x100000)		/* first address in kernel text - 9load sits below */
+#define	VPT			(KZERO-VPTSIZE)
+#define	VPTSIZE		BY2XPG
+#define	NVPT		(VPTSIZE/BY2WD)
+#define	KMAP		(VPT-KMAPSIZE)
+#define	KMAPSIZE	BY2XPG
+#define	VMAP		(KMAP-VMAPSIZE)
+#define	VMAPSIZE	(0x10000000-VPTSIZE-KMAPSIZE)
 #define	UZERO		0			/* base of user address space */
 #define	UTZERO		(UZERO+BY2PG)		/* first address in user text */
-#define	KZERO		0x80000000		/* base of kernel address space */
-#define	KTZERO		0x80100000		/* first address in kernel text */
-#define	USTKTOP		(KZERO-BY2PG)		/* byte just beyond user stack */
+#define	USTKTOP		(VMAP-BY2PG)		/* byte just beyond user stack */
 #define	USTKSIZE	(16*1024*1024)		/* size of user stack */
 #define	TSTKTOP		(USTKTOP-USTKSIZE)	/* end of new stack in sysexec */
 #define	TSTKSIZ 	100
 
+/*
+ * Fundamental addresses - bottom 64kB saved for return to real mode
+ */
+#define	CONFADDR	(KZERO+0x1200)		/* info passed from boot loader */
+#define	TMPADDR		(KZERO+0x2000)		/* used for temporary mappings */
+#define	APBOOTSTRAP	(KZERO+0x3000)		/* AP bootstrap code */
+#define	RMUADDR		(KZERO+0x7C00)		/* real mode Ureg */
+#define	RMCODE		(KZERO+0x8000)		/* copy of first page of KTEXT */
+#define	RMBUF		(KZERO+0x9000)		/* buffer for user space - known to vga */
+#define	IDTADDR		(KZERO+0x10800)		/* idt */
+#define	REBOOTADDR	(KZERO+0x11000)		/* reboot code - physical address */
+#define	CPU0PDB		(KZERO+0x12000)		/* bootstrap processor PDB */
+#define	CPU0PTE		(KZERO+0x13000)		/* bootstrap processor PTE's for 0-4MB */
+#define	CPU0GDT		(KZERO+0x14000)		/* bootstrap processor GDT */
+#define	MACHADDR	(KZERO+0x15000)		/* as seen by current processor */
+#define	CPU0MACH	(KZERO+0x16000)		/* Mach for bootstrap processor */
+#define	MACHSIZE	BY2PG
+/*
+ * N.B.  ramscan knows that CPU0MACH+BY2PG is the end of reserved data
+ * N.B.  _startPADDR knows that CPU0PDB is the first reserved page
+ * and that there are 5 of them.
+ */
+
 /*
  *  known x86 segments (in GDT) and their selectors
  */
@@ -72,6 +81,7 @@
 #define	APMCSEG		6	/* APM code segment */
 #define	APMCSEG16	7	/* APM 16-bit code segment */
 #define	APMDSEG		8	/* APM data segment */
+#define	KESEG16		9	/* kernel executable 16-bit */
 #define	NGDT		10	/* number of GDT entries required */
 /* #define	APM40SEG	8	/* APM segment 0x40 */
 
@@ -141,3 +151,4 @@
 #define	PTX(va)		((((ulong)(va))>>12) & 0x03FF)
 
 #define	getpgcolor(a)	0
+

+ 364 - 88
sys/src/9/pc/memory.c

@@ -8,6 +8,7 @@
 #include "dat.h"
 #include "fns.h"
 #include "io.h"
+#include "ureg.h"
 
 #define MEMDEBUG	0
 
@@ -15,19 +16,20 @@ enum {
 	MemUPA		= 0,		/* unbacked physical address */
 	MemRAM		= 1,		/* physical memory */
 	MemUMB		= 2,		/* upper memory block (<16MB) */
-	NMemType	= 3,
+	MemReserved	= 3,
+	NMemType	= 4,
 
 	KB		= 1024,
 
 	MemMinMB	= 4,		/* minimum physical memory (<=4MB) */
-	MemMaxMB	= 768,		/* maximum physical memory to check */
+	MemMaxMB	= 3*1024+768,		/* maximum physical memory to check */
 
 	NMemBase	= 10,
 };
 
 typedef struct Map Map;
 struct Map {
-	int	size;
+	ulong	size;
 	ulong	addr;
 };
 
@@ -40,6 +42,9 @@ struct RMap {
 	Lock;
 };
 
+/* 
+ * Memory allocation tracking.
+ */
 static Map mapupa[16];
 static RMap rmapupa = {
 	"unallocated unbacked physical memory",
@@ -82,7 +87,7 @@ mapprint(RMap *rmap)
 
 	print("%s\n", rmap->name);	
 	for(mp = rmap->map; mp->size; mp++)
-		print("\t%8.8luX %8.8uX %8.8luX\n", mp->addr, mp->size, mp->addr+mp->size);
+		print("\t%8.8luX %8.8luX (%lud)\n", mp->addr, mp->addr+mp->size, mp->size);
 }
 
 
@@ -91,9 +96,6 @@ memdebug(void)
 {
 	ulong maxpa, maxpa1, maxpa2;
 
-	if(MEMDEBUG == 0)
-		return;
-
 	maxpa = (nvramread(0x18)<<8)|nvramread(0x17);
 	maxpa1 = (nvramread(0x31)<<8)|nvramread(0x30);
 	maxpa2 = (nvramread(0x16)<<8)|nvramread(0x15);
@@ -209,6 +211,21 @@ mapalloc(RMap* rmap, ulong addr, int size, int align)
 	return 0;
 }
 
+/*
+ * Allocate from the ram map directly to make page tables.
+ * Called by mmuwalk during e820scan.
+ */
+void*
+rampage(void)
+{
+	ulong m;
+	
+	m = mapalloc(&rmapram, 0, BY2PG, BY2PG);
+	if(m == 0)
+		return nil;
+	return KADDR(m);
+}
+
 static void
 umbscan(void)
 {
@@ -269,18 +286,11 @@ umbscan(void)
 }
 
 static void
-ramscan(ulong maxmem)
+lowraminit(void)
 {
-	ulong *k0, kzero, map, maxpa, pa, *pte, *table, *va, x, n;
-	int nvalid[NMemType];
+	ulong n, pa, x;
 	uchar *bda;
 
-	/*
-	 * The bootstrap code has has created a prototype page
-	 * table which maps the first MemMinMB of physical memory to KZERO.
-	 * The page directory is at m->pdb and the first page of
-	 * free memory is after the per-processor MMU information.
-	 */
 	/*
 	 * Initialise the memory bank information for conventional memory
 	 * (i.e. less than 640KB). The base is the first location after the
@@ -297,6 +307,21 @@ ramscan(ulong maxmem)
 	pa = MemMinMB*MB;
 	mapfree(&rmapram, x, pa-x);
 	memset(KADDR(x), 0, pa-x);		/* keep us honest */
+}
+
+static void
+ramscan(ulong maxmem)
+{
+	ulong *k0, kzero, map, maxkpa, maxpa, pa, *pte, *table, *va, vbase, x;
+	int nvalid[NMemType];
+
+	/*
+	 * The bootstrap code has has created a prototype page
+	 * table which maps the first MemMinMB of physical memory to KZERO.
+	 * The page directory is at m->pdb and the first page of
+	 * free memory is after the per-processor MMU information.
+	 */
+	pa = MemMinMB*MB;
 
 	/*
 	 * Check if the extended memory size can be obtained from the CMOS.
@@ -314,10 +339,9 @@ ramscan(ulong maxmem)
 			maxpa = MB+x*KB;
 		if(maxpa < 24*MB)
 			maxpa = 24*MB;
-		maxmem = MemMaxMB*MB;
-	}
-	else
+	}else
 		maxpa = maxmem;
+	maxkpa = (u32int)-KZERO;	/* 2^32 - KZERO */
 
 	/*
 	 * March up memory from MemMinMB to maxpa 1MB at a time,
@@ -330,15 +354,24 @@ ramscan(ulong maxmem)
 	map = 0;
 	x = 0x12345678;
 	memset(nvalid, 0, sizeof(nvalid));
+	
+	/*
+	 * Can't map memory to KADDR(pa) when we're walking because
+	 * can only use KADDR for relatively low addresses.  Instead,
+	 * map each 4MB we scan to the virtual address range 4MB-8MB
+	 * while we are scanning.
+	 */
+	vbase = 4*MB;
 	while(pa < maxpa){
 		/*
 		 * Map the page. Use mapalloc(&rmapram, ...) to make
 		 * the page table if necessary, it will be returned to the
-		 * pool later if it isn't needed.
+		 * pool later if it isn't needed.  Map in a fixed range (the second 4M)
+		 * because high physical addresses cannot be passed to KADDR.
 		 */
-		va = KADDR(pa);
+		va = (void*)(vbase + pa%(4*MB));
 		table = &m->pdb[PDX(va)];
-		if(*table == 0){
+		if(pa%(4*MB) == 0){
 			if(map == 0 && (map = mapalloc(&rmapram, 0, BY2PG, BY2PG)) == 0)
 				break;
 			memset(KADDR(map), 0, BY2PG);
@@ -350,10 +383,9 @@ ramscan(ulong maxmem)
 
 		*pte = pa|PTEWRITE|PTEUNCACHED|PTEVALID;
 		mmuflushtlb(PADDR(m->pdb));
-
 		/*
 		 * Write a pattern to the page and write a different
-		 * pattern to a possible mirror at KZER0. If the data
+		 * pattern to a possible mirror at KZERO. If the data
 		 * reads back correctly the chunk is some type of RAM (possibly
 		 * a linearly-mapped VGA framebuffer, for instance...) and
 		 * can be cleared and added to the memory pool. If not, the
@@ -389,7 +421,6 @@ ramscan(ulong maxmem)
 			*pte = 0;
 			pa += MB;
 		}
-
 		/*
 		 * Done with this 4MB chunk, review the options:
 		 * 1) not physical memory and >=16MB - invalidate the PDB entry;
@@ -399,46 +430,284 @@ ramscan(ulong maxmem)
 		 * 4) mixed or no 4MB page extension - commit the already
 		 *    initialised space for the page table.
 		 */
-		if((pa % (4*MB)) == 0){
-			table = &m->pdb[PDX(va)];
+		if(pa%(4*MB) == 0 && pa >= 32*MB && nvalid[MemUPA] == (4*MB)/BY2PG){
+			/*
+			 * If we encounter a 4MB chunk of missing memory
+			 * at a sufficiently high offset, call it the end of
+			 * memory.  Otherwise we run the risk of thinking
+			 * that video memory is real RAM.
+			 */
+			break;
+		}
+		if(pa <= maxkpa && pa%(4*MB) == 0){
+			table = &m->pdb[PDX(KADDR(pa - 4*MB))];
 			if(nvalid[MemUPA] == (4*MB)/BY2PG)
 				*table = 0;
 			else if(nvalid[MemRAM] == (4*MB)/BY2PG && (m->cpuiddx & 0x08))
 				*table = (pa - 4*MB)|PTESIZE|PTEWRITE|PTEVALID;
 			else if(nvalid[MemUMB] == (4*MB)/BY2PG && (m->cpuiddx & 0x08))
 				*table = (pa - 4*MB)|PTESIZE|PTEWRITE|PTEUNCACHED|PTEVALID;
-			else
+			else{
+				*table = map|PTEWRITE|PTEVALID;
 				map = 0;
+			}
 		}
-
 		mmuflushtlb(PADDR(m->pdb));
 		x += 0x3141526;
 	}
-
 	/*
 	 * If we didn't reach the end of the 4MB chunk, that part won't
 	 * be mapped.  Commit the already initialised space for the page table.
 	 */
-	if(pa % (4*MB))
+	if(pa % (4*MB) && pa <= maxkpa){
+		m->pdb[PDX(KADDR(pa))] = map|PTEWRITE|PTEVALID;
 		map = 0;
-
+	}
 	if(map)
 		mapfree(&rmapram, map, BY2PG);
-	if(pa < maxmem)
-		mapfree(&rmapupa, pa, maxmem-pa);
-	if(maxmem < 0xFFE00000)
-		mapfree(&rmapupa, maxmem, 0x00000000-maxmem);
-	if(MEMDEBUG)
-		print("maxmem %luX %luX\n", maxmem, 0x00000000-maxmem);
+
+	m->pdb[PDX(vbase)] = 0;
+	mmuflushtlb(PADDR(m->pdb));
+
+	mapfree(&rmapupa, pa, (u32int)-pa);
 	*k0 = kzero;
 }
 
+/*
+ * BIOS Int 0x15 E820 memory map.
+ */
+enum
+{
+	SMAP = ('S'<<24)|('M'<<16)|('A'<<8)|'P',
+	Ememory = 1,
+	Ereserved = 2,
+	Carry = 1,
+};
+
+typedef struct Emap Emap;
+struct Emap
+{
+	uvlong base;
+	uvlong len;
+	ulong type;
+};
+static Emap emap[16];
+int nemap;
+
+static char *etypes[] =
+{
+	"type=0",
+	"memory",
+	"reserved",
+	"acpi reclaim",
+	"acpi nvs",
+};
+
+static int
+emapcmp(const void *va, const void *vb)
+{
+	Emap *a, *b;
+	
+	a = (Emap*)va;
+	b = (Emap*)vb;
+	if(a->base < b->base)
+		return -1;
+	if(a->base > b->base)
+		return 1;
+	if(a->len < b->len)
+		return -1;
+	if(a->len > b->len)
+		return 1;
+	return a->type - b->type;
+}
+
+static void
+map(ulong base, ulong len, int type)
+{
+	ulong e, n;
+	ulong *table, flags, maxkpa;
+	
+	/*
+	 * Split any call crossing 4*MB to make below simpler.
+	 */
+	if(base < 4*MB && len > 4*MB-base){
+		n = 4*MB - base;
+		map(base, n, type);
+		map(4*MB, len-n, type);
+	}
+	
+	/*
+	 * Let lowraminit and umbscan hash out the low 4MB.
+	 */
+	if(base < 4*MB)
+		return;
+
+	/*
+	 * Any non-memory below 16*MB is used as upper mem blocks.
+	 */
+	if(type == MemUPA && base < 16*MB && base+len > 16*MB){
+		map(base, 16*MB-base, MemUMB);
+		map(16*MB, len-(16*MB-base), MemUPA);
+		return;
+	}
+	
+	/*
+	 * Memory below CPU0MACH is reserved for the kernel
+	 * and already mapped.
+	 */
+	if(base < PADDR(CPU0MACH)+BY2PG){
+		n = PADDR(CPU0MACH)+BY2PG - base;
+		if(len <= n)
+			return;
+		map(PADDR(CPU0MACH), len-n, type);
+		return;
+	}
+	
+	/*
+	 * Memory between KTZERO and end is the kernel itself
+	 * and is already mapped.
+	 */
+	if(base < PADDR(KTZERO) && base+len > PADDR(KTZERO)){
+		map(base, PADDR(KTZERO)-base, type);
+		return;
+	}
+	if(PADDR(KTZERO) < base && base < PADDR(PGROUND((ulong)end))){
+		n = PADDR(PGROUND((ulong)end));
+		if(len <= n)
+			return;
+		map(PADDR(PGROUND((ulong)end)), len-n, type);
+		return;
+	}
+	
+	/*
+	 * Now we have a simple case.
+	 */
+	// print("map %.8lux %.8lux %d\n", base, base+len, type);
+	switch(type){
+	case MemRAM:
+		mapfree(&rmapram, base, len);
+		flags = PTEWRITE;
+		break;
+	case MemUMB:
+		mapfree(&rmapumb, base, len);
+		flags = PTEWRITE|PTEUNCACHED;
+		break;
+	case MemUPA:
+		mapfree(&rmapupa, base, len);
+		/* don't need to map this but will anyway */
+		flags = PTEWRITE|PTEUNCACHED;
+		break;
+	default:
+	case MemReserved:
+		/* don't put in any pools but still map it. */
+		flags = PTEWRITE|PTEUNCACHED;
+		break;
+	}
+	
+	/*
+	 * bottom 4MB is already mapped - just twiddle flags.
+	 * (not currently used - see above)
+	 */
+	if(base < 4*MB){
+		table = KADDR(PPN(m->pdb[PDX(base)]));
+		e = base+len;
+		base = PPN(base);
+		for(; base<e; base+=BY2PG)
+			table[PTX(base)] |= flags;
+		return;
+	}
+	
+	/*
+	 * Only map from KZERO to 2^32.
+	 */
+	maxkpa = -KZERO;
+	if(base >= maxkpa)
+		return;
+	if(len > maxkpa-base)
+		len = maxkpa - base;
+	pdbmap(m->pdb, base|flags, base+KZERO, len);
+}
+
+static int
+e820scan(void)
+{
+	int i;
+	Ureg u;
+	ulong cont, base, last, len;
+	Emap *e;
+
+	if(getconf("*norealmode") || getconf("*noe820scan"))
+		return -1;
+
+	cont = 0;
+	for(i=0; i<nelem(emap); i++){
+		memset(&u, 0, sizeof u);
+		u.ax = 0xE820;
+		u.bx = cont;
+		u.cx = 20;
+		u.dx = SMAP;
+		u.es = (PADDR(RMBUF)>>4)&0xF000;
+		u.di = PADDR(RMBUF)&0xFFFF;
+		u.trap = 0x15;
+		realmode(&u);
+		cont = u.bx;
+		if((u.flags&Carry) || u.ax != SMAP || u.cx != 20)
+			break;
+		e = &emap[nemap++];
+		*e = *(Emap*)RMBUF;
+		if(u.bx == 0)
+			break;
+	}
+	if(nemap == 0)
+		return -1;
+	
+	qsort(emap, nemap, sizeof emap[0], emapcmp);
+	
+	for(i=0; i<nemap; i++){
+		e = &emap[i];
+		print("E820: %.8llux %.8llux ", e->base, e->base+e->len);
+		if(e->type < nelem(etypes))
+			print("%s\n", etypes[e->type]);
+		else
+			print("type=%lud\n", e->type);
+	}
+
+	last = 0;
+	for(i=0; i<nemap; i++){	
+		e = &emap[i];
+		/*
+		 * pull out the info but only about the low 32 bits...
+		 */
+		if(e->base >= (1LL<<32))
+			break;
+		base = e->base;
+		if(base+e->len > (1LL<<32))
+			len = -base;
+		else
+			len = e->len;
+		/*
+		 * If the map skips addresses, mark them available.
+		 */
+		if(last < e->base)
+			map(last, e->base-last, MemUPA);
+		last = base+len;
+		if(e->type == Ememory)
+			map(base, len, MemRAM);
+		else
+			map(base, len, MemReserved);
+	}
+	
+	return 0;
+}
+
 void
 meminit(void)
 {
-	Map *mp, *xmp;
+	int i;
+	Map *mp;
+	Confmem *cm;
 	ulong pa, *pte;
-	ulong maxmem;
+	ulong maxmem, lost;
 	char *p;
 
 	if(p = getconf("*maxmem"))
@@ -463,31 +732,33 @@ meminit(void)
 	mmuflushtlb(PADDR(m->pdb));
 
 	umbscan();
-	ramscan(maxmem);
+	lowraminit();
+	if(e820scan() < 0)
+		ramscan(maxmem);
 
 	/*
-	 * Set the conf entries describing two banks of allocatable memory.
-	 * Grab the first and largest entries in rmapram as left by ramscan().
-	 *
-	 * It would be nice to have more than 2 memory banks describable in conf.
+	 * Set the conf entries describing banks of allocatable memory.
 	 */
-	mp = rmapram.map;
-	conf.base0 = mp->addr;
-	conf.npage0 = mp->size/BY2PG;
-	mp++;
-	for(xmp = 0; mp->size; mp++){
-		if(xmp == 0 || mp->size > xmp->size)
-			xmp = mp;
+	for(i=0; i<nelem(mapram) && i<nelem(conf.mem); i++){
+		mp = &rmapram.map[i];
+		cm = &conf.mem[i];
+		cm->base = mp->addr;
+		cm->npage = mp->size/BY2PG;
 	}
+	
+	lost = 0;
+	for(; i<nelem(mapram); i++)
+		lost += rmapram.map[i].size;
+	if(lost)
+		print("meminit - lost %lud bytes\n", lost);
 
-	if(xmp){		
-		conf.base1 = xmp->addr;
-		conf.npage1 = xmp->size/BY2PG;
-	}
 	if(MEMDEBUG)
 		memdebug();
 }
 
+/*
+ * Allocate memory from the upper memory blocks.
+ */
 ulong
 umbmalloc(ulong addr, int size, int align)
 {
@@ -536,47 +807,52 @@ umbrwfree(ulong addr, int size)
 	mapfree(&rmapumbrw, PADDR(addr), size);
 }
 
+/*
+ * Give out otherwise-unused physical address space
+ * for use in configuring devices.  Note that unlike upamalloc
+ * before it, upaalloc does not map the physical address
+ * into virtual memory.  Call vmap to do that.
+ */
 ulong
-upamalloc(ulong pa, int size, int align)
+upaalloc(int size, int align)
 {
-	ulong a, ae;
-
-	if(a = mapalloc(&xrmapupa, pa, size, align))
-		return a;
+	ulong a;
 
-	if((a = mapalloc(&rmapupa, pa, size, align)) == 0){
-		memdebug();
-		return 0;
+	a = mapalloc(&rmapupa, 0, size, align);
+	if(a == 0){
+		print("out of physical address space allocating %d\n", size);
+		mapprint(&rmapupa);
 	}
-
-	/*
-	 * Upamalloc is a request to map a range of physical addresses.
-	 * Therefore, if pa is 0 mapalloc will choose the base address.
-	 * Note, however, mmukmap is always asked to give a 1-to-1 mapping
-	 * of va to pa.
-	ae = mmukmap(a, a, size);
-	 * ...but for the moment go back to the old scheme for VLB cards.
-	 */
-	ae = mmukmap(a, 0, size);
-
-	/*
-	 * Should check here that it was all delivered
-	 * and put it back and barf if not.
-	 */
-	USED(ae);
-
-	/*
-	 * Be very careful this returns a PHYSICAL address
-	 * mapped 1-to-1 with the virtual address.
-	 * If a < KZERO it's probably not a good idea to
-	 * try KADDR(a)...
-	 */
 	return a;
 }
 
 void
 upafree(ulong pa, int size)
 {
-	mapfree(&xrmapupa, pa, size);
+	mapfree(&rmapupa, pa, size);
+}
+
+void
+upareserve(ulong pa, int size)
+{
+	ulong a;
+	
+	a = mapalloc(&rmapupa, pa, size, 0);
+	if(a != pa){
+		/*
+		 * This can happen when we're using the E820
+		 * map, which might have already reserved some
+		 * of the regions claimed by the pci devices.
+		 */
+	//	print("upareserve: cannot reserve pa=%#.8lux size=%d\n", pa, size);
+		if(a != 0)
+			mapfree(&rmapupa, a, size);
+	}
+}
+
+void
+memorysummary(void)
+{
+	memdebug();
 }
 

+ 38 - 17
sys/src/9/pc/mkfile

@@ -1,11 +1,18 @@
 CONF=pc
 CONFLIST=pc pccpu pcf pccpuf pcdisk pcauth
-CRAPLIST=pccd pccpud pccpusape pcext pcf pcflop pcglenda pcgr pclml pcmartha pcsape pcblast
+CRAPLIST=pccd pcflop pcmartha
+EXTRACOPIES=
+#EXTRACOPIES=lookout boundary	# copy to these servers on install
 
 objtype=386
 </$objtype/mkfile
 p=9
 
+# must match mem.h
+
+APBOOTSTRAP=0xF0003000
+KTZERO=0xF0100020
+
 DEVS=`{rc ../port/mkdevlist $CONF}
 
 PORT=\
@@ -16,9 +23,9 @@ PORT=\
 	cache.$O\
 	chan.$O\
 	dev.$O\
+	edf.$O\
 	fault.$O\
 	latin1.$O\
-	edf.$O\
 	page.$O\
 	parse.$O\
 	pgrp.$O\
@@ -27,6 +34,7 @@ PORT=\
 	proc.$O\
 	qio.$O\
 	qlock.$O\
+	rdb.$O\
 	rebootcmd.$O\
 	segment.$O\
 	swap.$O\
@@ -47,7 +55,6 @@ OBJ=\
 	memory.$O\
 	mmu.$O\
 	random.$O\
-	rdb.$O\
 	trap.$O\
 	$CONF.root.$O\
 	$CONF.rootc.$O\
@@ -67,15 +74,16 @@ SDEV=`{echo devsd.c sd*.c | sed 's/\.c/.'$O'/g'}
 
 $p$CONF:	$CONF.c $OBJ $LIB
 	$CC $CFLAGS '-DKERNDATE='`{date -n} $CONF.c
-	$LD -o $target -T0x80100020 -l $OBJ $CONF.$O $LIB
+	$LD -o $target -T$KTZERO -l $OBJ $CONF.$O $LIB
 	size $target
 
-$p$CONF.gz: $p$CONF
-	strip < $p$CONF | gzip -9 > $p$CONF.gz
+$p$CONF.gz:	$p$CONF
+	strip -o /fd/1 $p$CONF | gzip -9 > $p$CONF.gz
 
-install:V: $p$CONF $p$CONF.gz
+install:V:	$p$CONF $p$CONF.gz
 	cp $p$CONF $p$CONF.gz /$objtype/
-	# import lookout / /n/lookout && cp $p$CONF $p$CONF.gz /n/lookout/$objtype/
+	for(i in $EXTRACOPIES)
+		import $i / /n/$i && cp $p$CONF $p$CONF.gz /n/$i/$objtype/
 
 <../boot/bootmkfile
 <../port/portmkfile
@@ -90,20 +98,21 @@ apic.$O archmp.$O mp.$O:	mp.h
 $SDEV:				../port/sd.h
 sd53c8xx.$O:			sd53c8xx.i
 main.$O:			init.h reboot.h
-wavelan.$O:	wavelan.c ../pc/wavelan.c ../pc/wavelan.h
-etherwavelan.$O:	etherwavelan.c  ../pc/wavelan.h
-devusb.$O usbuhci.$O usbohci.$O:	usb.h
-trap.$O:	/sys/include/tos.h
+wavelan.$O:			wavelan.c ../pc/wavelan.c ../pc/wavelan.h
+etherwavelan.$O:		etherwavelan.c ../pc/wavelan.h
+devusb.$O usbuhci.$O usbohci.$O: usb.h
+trap.$O:			/sys/include/tos.h
 
 sd53c8xx.i:	sd53c8xx.n
 	aux/na $prereq > $target
 
-init.h:	../port/initcode.c init9.c
+init.h:		../port/initcode.c init9.c
 	$CC ../port/initcode.c
 	$CC init9.c
 	$LD -l -R1 -o init.out init9.$O initcode.$O /386/lib/libc.a
+	strip init.out
 	{echo 'uchar initcode[]={'
-	 strip < init.out | xd -1x |
+	 cat init.out | xd -1x |
 		sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
 	 echo '};'} > init.h
 
@@ -117,14 +126,14 @@ reboot.h:	rebootcode.s
 
 apbootstrap.h:	apbootstrap.s mem.h
 	$AS $prereq
-	$LD -o apbootstrap.out -T0x80001000 -R4 -l -s apbootstrap.$O
+	$LD -o apbootstrap.out -T$APBOOTSTRAP -R4 -l -s apbootstrap.$O
 	{echo 'uchar apbootstrap[]={'
 	 xd -1x apbootstrap.out |
 		sed -e '1,2d' -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
 	 echo '};'} > $target
 
 acid:V:
-	8c -a -w -I. ../port/qio.c>acid
+	8c -a -w -I. i8253.c>acid
 
 %.checkether:VQ:
 	for (i in ether*.c){
@@ -148,4 +157,16 @@ checkdist:VQ:
 		mk $i.$j
 
 %.clean:V:
-	rm -f $stem.c [9bz]$stem [9bz]$stem.gz boot$stem.*
+	rm -f $stem.c [9bz]$stem [9bz]$stem.gz boot$stem.* reboot.h apbootstrap.h init.h
+
+# testing
+9load:D: /usr/rsc/boot/$O.load 9pcload
+	cat $prereq >$target
+
+9load.flp: 9load
+	disk/format -b /386/pbs -df $target $prereq
+
+$p$CONF.flp: /386/9load plan9.ini $p$CONF.gz
+	disk/format -b /386/pbs -df $target $prereq
+
+

+ 656 - 282
sys/src/9/pc/mmu.c

@@ -1,3 +1,37 @@
+/*
+ * Memory mappings.  Life was easier when 2G of memory was enough.
+ *
+ * The kernel memory starts at KZERO, with the text loaded at KZERO+1M
+ * (9load sits under 1M during the load).  The memory from KZERO to the
+ * top of memory is mapped 1-1 with physical memory, starting at physical
+ * address 0.  All kernel memory and data structures (i.e., the entries stored
+ * into conf.mem) must sit in this physical range: if KZERO is at 0xF0000000,
+ * then the kernel can only have 256MB of memory for itself.
+ * 
+ * The 256M below KZERO comprises three parts.  The lowest 4M is the
+ * virtual page table, a virtual address representation of the current 
+ * page table tree.  The second 4M is used for temporary per-process
+ * mappings managed by kmap and kunmap.  The remaining 248M is used
+ * for global (shared by all procs and all processors) device memory
+ * mappings and managed by vmap and vunmap.  The total amount (256M)
+ * could probably be reduced somewhat if desired.  The largest device
+ * mapping is that of the video card, and even though modern video cards
+ * have embarrassing amounts of memory, the video drivers only use one
+ * frame buffer worth (at most 16M).  Each is described in more detail below.
+ *
+ * The VPT is a 4M frame constructed by inserting the pdb into itself.
+ * This short-circuits one level of the page tables, with the result that 
+ * the contents of second-level page tables can be accessed at VPT.  
+ * We use the VPT to edit the page tables (see mmu) after inserting them
+ * into the page directory.  It is a convenient mechanism for mapping what
+ * might be otherwise-inaccessible pages.  The idea was borrowed from
+ * the Exokernel.
+ *
+ * The VPT doesn't solve all our problems, because we still need to 
+ * prepare page directories before we can install them.  For that, we
+ * use tmpmap/tmpunmap, which map a single page at TMPADDR.
+ */
+
 #include	"u.h"
 #include	"../port/lib.h"
 #include	"mem.h"
@@ -5,8 +39,12 @@
 #include	"fns.h"
 #include	"io.h"
 
+/*
+ * Simple segment descriptors with no translation.
+ */
 #define	DATASEGM(p) 	{ 0xFFFF, SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(p)|SEGDATA|SEGW }
 #define	EXECSEGM(p) 	{ 0xFFFF, SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(p)|SEGEXEC|SEGR }
+#define	EXEC16SEGM(p) 	{ 0xFFFF, SEGG|(0xF<<16)|SEGP|SEGPL(p)|SEGEXEC|SEGR }
 #define	TSSSEGM(b,p)	{ ((b)<<16)|sizeof(Tss),\
 			  ((b)&0xFF000000)|(((b)>>16)&0xFF)|SEGTSS|SEGPL(p)|SEGP }
 
@@ -18,63 +56,21 @@ Segdesc gdt[NGDT] =
 [UDSEG]		DATASEGM(3),		/* user data/stack */
 [UESEG]		EXECSEGM(3),		/* user code */
 [TSSSEG]	TSSSEGM(0,0),		/* tss segment */
+[KESEG16]		EXEC16SEGM(0),	/* kernel code 16-bit */
 };
 
-static void
-taskswitch(ulong pdb, ulong stack)
-{
-	Tss *tss;
+static int didmmuinit;
+static void taskswitch(ulong, ulong);
+static void memglobal(void);
 
-	tss = m->tss;
-	tss->ss0 = KDSEL;
-	tss->esp0 = stack;
-	tss->ss1 = KDSEL;
-	tss->esp1 = stack;
-	tss->ss2 = KDSEL;
-	tss->esp2 = stack;
-	tss->cr3 = pdb;
-	putcr3(pdb);
-}
+#define	vpt ((ulong*)VPT)
+#define	VPTX(va)		(((ulong)(va))>>12)
+#define	vpd (vpt+VPTX(VPT))
 
-/* 
- * On processors that support it, we set the PTEGLOBAL bit in
- * page table and page directory entries that map kernel memory.
- * Doing this tells the processor not to bother flushing them
- * from the TLB when doing the TLB flush associated with a 
- * context switch (write to CR3).  Since kernel memory mappings
- * are never removed, this is safe.  (If we ever remove kernel memory
- * mappings, we can do a full flush by turning off the PGE bit in CR4,
- * writing to CR3, and then turning the PGE bit back on.) 
- *
- * See also mmukmap below.
- * 
- * Processor support for the PTEGLOBAL bit is enabled in devarch.c.
- */
-static void
-memglobal(void)
+void
+mmuinit0(void)
 {
-	int i, j;
-	ulong *pde, *pte;
-
-	/* only need to do this once, on bootstrap processor */
-	if(m->machno != 0)
-		return;
-
-	if(!m->havepge)
-		return;
-
-	pde = m->pdb;
-	for(i=512; i<1024; i++){	/* 512: start at entry for virtual 0x80000000 */
-		if(pde[i] & PTEVALID){
-			pde[i] |= PTEGLOBAL;
-			if(!(pde[i] & PTESIZE)){
-				pte = KADDR(pde[i]&~(BY2PG-1));
-				for(j=0; j<1024; j++)
-					if(pte[j] & PTEVALID)
-						pte[j] |= PTEGLOBAL;
-			}
-		}
-	}			
+	memmove(m->gdt, gdt, sizeof gdt);
 }
 
 void
@@ -83,8 +79,14 @@ mmuinit(void)
 	ulong x, *p;
 	ushort ptr[3];
 
-	memglobal();
+	didmmuinit = 1;
+
+	if(0) print("vpt=%#.8ux vpd=%#.8lux kmap=%#.8ux\n",
+		VPT, (ulong)vpd, KMAP);
 
+	memglobal();
+	m->pdb[PDX(VPT)] = PADDR(m->pdb)|PTEWRITE|PTEVALID;
+	
 	m->tss = malloc(sizeof(Tss));
 	memset(m->tss, 0, sizeof(Tss));
 	m->tss->iomap = 0xDFFF<<16;
@@ -98,7 +100,6 @@ mmuinit(void)
 	 * than Intels in this regard).  Under VMware it pays off
 	 * a factor of about 10 to 100.
 	 */
-
 	memmove(m->gdt, gdt, sizeof gdt);
 	x = (ulong)m->tss;
 	m->gdt[TSSSEG].d0 = (x<<16)|sizeof(Tss);
@@ -128,6 +129,52 @@ mmuinit(void)
 	ltr(TSSSEL);
 }
 
+/* 
+ * On processors that support it, we set the PTEGLOBAL bit in
+ * page table and page directory entries that map kernel memory.
+ * Doing this tells the processor not to bother flushing them
+ * from the TLB when doing the TLB flush associated with a 
+ * context switch (write to CR3).  Since kernel memory mappings
+ * are never removed, this is safe.  (If we ever remove kernel memory
+ * mappings, we can do a full flush by turning off the PGE bit in CR4,
+ * writing to CR3, and then turning the PGE bit back on.) 
+ *
+ * See also mmukmap below.
+ * 
+ * Processor support for the PTEGLOBAL bit is enabled in devarch.c.
+ */
+static void
+memglobal(void)
+{
+	int i, j;
+	ulong *pde, *pte;
+
+	/* only need to do this once, on bootstrap processor */
+	if(m->machno != 0)
+		return;
+
+	if(!m->havepge)
+		return;
+
+	pde = m->pdb;
+	for(i=PDX(KZERO); i<1024; i++){
+		if(pde[i] & PTEVALID){
+			pde[i] |= PTEGLOBAL;
+			if(!(pde[i] & PTESIZE)){
+				pte = KADDR(pde[i]&~(BY2PG-1));
+				for(j=0; j<1024; j++)
+					if(pte[j] & PTEVALID)
+						pte[j] |= PTEGLOBAL;
+			}
+		}
+	}			
+}
+
+/*
+ * Flush all the user-space and device-mapping mmu info
+ * for this process, because something has been deleted.
+ * It will be paged back in on demand.
+ */
 void
 flushmmu(void)
 {
@@ -139,23 +186,106 @@ flushmmu(void)
 	splx(s);
 }
 
+/*
+ * Flush a single page mapping from the tlb.
+ */
+void
+flushpg(ulong va)
+{
+	if(X86FAMILY(m->cpuidax) >= 4)
+		invlpg(va);
+	else
+		putcr3(m->tss->cr3);
+}
+	
+/*
+ * Allocate a new page for a page directory. 
+ * We keep a small cache of pre-initialized
+ * page directories in each mach.
+ */
+static Page*
+mmupdballoc(void)
+{
+	int s;
+	Page *page;
+	ulong *pdb;
+
+	s = splhi();
+	if(m->pdbpool == 0){
+		spllo();
+		page = newpage(0, 0, 0);
+		page->va = (ulong)vpd;
+		splhi();
+		pdb = tmpmap(page);
+		memmove(pdb, m->pdb, BY2PG);
+		pdb[PDX(VPT)] = page->pa|PTEWRITE|PTEVALID;	/* set up VPT */
+		tmpunmap(pdb);
+	}else{
+		page = m->pdbpool;
+		m->pdbpool = page->next;
+		m->pdbcnt--;
+	}
+	splx(s);
+	return page;
+}
+
+static void
+mmupdbfree(Proc *proc, Page *p)
+{
+	if(islo())
+		panic("mmupdbfree: islo");
+	if(m->pdbcnt >= 10){
+		p->next = proc->mmufree;
+		proc->mmufree = p;
+	}else{
+		p->next = m->pdbpool;
+		m->pdbpool = p;
+	}
+}
+
+/*
+ * A user-space memory segment has been deleted, or the
+ * process is exiting.  Clear all the pde entries for user-space
+ * memory mappings and device mappings.  Any entries that
+ * are needed will be paged back in as necessary.
+ */
 static void
 mmuptefree(Proc* proc)
 {
+	int s;
 	ulong *pdb;
 	Page **last, *page;
 
-	if(proc->mmupdb && proc->mmuused){
-		pdb = (ulong*)proc->mmupdb->va;
-		last = &proc->mmuused;
-		for(page = *last; page; page = page->next){
-			pdb[page->daddr] = 0;
-			last = &page->next;
-		}
-		*last = proc->mmufree;
-		proc->mmufree = proc->mmuused;
-		proc->mmuused = 0;
+	if(proc->mmupdb == nil || proc->mmuused == nil)
+		return;
+	s = splhi();
+	pdb = tmpmap(proc->mmupdb);
+	last = &proc->mmuused;
+	for(page = *last; page; page = page->next){
+		pdb[page->daddr] = 0;
+		last = &page->next;
 	}
+	tmpunmap(pdb);
+	splx(s);
+	*last = proc->mmufree;
+	proc->mmufree = proc->mmuused;
+	proc->mmuused = 0;
+}
+
+static void
+taskswitch(ulong pdb, ulong stack)
+{
+	Tss *tss;
+
+	tss = m->tss;
+	tss->ss0 = KDSEL;
+	tss->esp0 = stack;
+	tss->ss1 = KDSEL;
+	tss->esp1 = stack;
+	tss->ss2 = KDSEL;
+	tss->esp2 = stack;
+	tss->cr3 = pdb;
+	putcr3(pdb);
 }
 
 void
@@ -169,47 +299,37 @@ mmuswitch(Proc* proc)
 	}
 
 	if(proc->mmupdb){
-		pdb = (ulong*)proc->mmupdb->va;
+		pdb = tmpmap(proc->mmupdb);
 		pdb[PDX(MACHADDR)] = m->pdb[PDX(MACHADDR)];
+		tmpunmap(pdb);
 		taskswitch(proc->mmupdb->pa, (ulong)(proc->kstack+KSTACK));
-	}
-	else
+	}else
 		taskswitch(PADDR(m->pdb), (ulong)(proc->kstack+KSTACK));
 }
 
+/*
+ * Release any pages allocated for a page directory base or page-tables
+ * for this process:
+ *   switch to the prototype pdb for this processor (m->pdb);
+ *   call mmuptefree() to place all pages used for page-tables (proc->mmuused)
+ *   onto the process' free list (proc->mmufree). This has the side-effect of
+ *   cleaning any user entries in the pdb (proc->mmupdb);
+ *   if there's a pdb put it in the cache of pre-initialised pdb's
+ *   for this processor (m->pdbpool) or on the process' free list;
+ *   finally, place any pages freed back into the free pool (palloc).
+ * This routine is only called from sched() with palloc locked.
+ */
 void
 mmurelease(Proc* proc)
 {
 	Page *page, *next;
 
-	/*
-	 * Release any pages allocated for a page directory base or page-tables
-	 * for this process:
-	 *   switch to the prototype pdb for this processor (m->pdb);
-	 *   call mmuptefree() to place all pages used for page-tables (proc->mmuused)
-	 *   onto the process' free list (proc->mmufree). This has the side-effect of
-	 *   cleaning any user entries in the pdb (proc->mmupdb);
-	 *   if there's a pdb put it in the cache of pre-initialised pdb's
-	 *   for this processor (m->pdbpool) or on the process' free list;
-	 *   finally, place any pages freed back into the free pool (palloc).
-	 * This routine is only called from sched() with palloc locked.
-	 */
 	taskswitch(PADDR(m->pdb), (ulong)m + BY2PG);
-	mmuptefree(proc);
-
 	if(proc->mmupdb){
-		if(m->pdbcnt > 10){
-			proc->mmupdb->next = proc->mmufree;
-			proc->mmufree = proc->mmupdb;
-		}
-		else{
-			proc->mmupdb->next = m->pdbpool;
-			m->pdbpool = proc->mmupdb;
-			m->pdbcnt++;
-		}
+		mmuptefree(proc);
+		mmupdbfree(proc, proc->mmupdb);
 		proc->mmupdb = 0;
 	}
-
 	for(page = proc->mmufree; page; page = next){
 		next = page->next;
 		if(--page->ref)
@@ -221,103 +341,90 @@ mmurelease(Proc* proc)
 	proc->mmufree = 0;
 }
 
-static Page*
-mmupdballoc(void)
+/*
+ * Allocate and install pdb for the current process.
+ */
+static void
+upallocpdb(void)
 {
 	int s;
+	ulong *pdb;
 	Page *page;
-
+	
+	page = mmupdballoc();
 	s = splhi();
-	if(m->pdbpool == 0){
-		spllo();
-		page = newpage(0, 0, 0);
-		page->va = VA(kmap(page));
-		memmove((void*)page->va, m->pdb, BY2PG);
-	}
-	else{
-		page = m->pdbpool;
-		m->pdbpool = page->next;
-		m->pdbcnt--;
-	}
+	pdb = tmpmap(page);
+	pdb[PDX(MACHADDR)] = m->pdb[PDX(MACHADDR)];
+	tmpunmap(pdb);
+	up->mmupdb = page;
+	mmuflushtlb(up->mmupdb->pa);
 	splx(s);
-	return page;
 }
-
-void
-checkmmu(ulong va, ulong pa)
-{
-	ulong *pdb, *pte;
-	int pdbx;
 	
-	if(up->mmupdb == 0)
-		return;
-
-	pdb = (ulong*)up->mmupdb->va;
-	pdbx = PDX(va);
-	if(PPN(pdb[pdbx]) == 0){
-		/* okay to be empty - will fault and get filled */
-		return;
-	}
-	
-	pte = KADDR(PPN(pdb[pdbx]));
-	if(pte[PTX(va)] == 0)
-		return;
-	if((pte[PTX(va)]&~4095) != pa)
-		print("%ld %s: va=0x%08lux pa=0x%08lux pte=0x%08lux\n",
-			up->pid, up->text,
-			va, pa, pte[PTX(va)]);
-}
-
+/*
+ * Update the mmu in response to a user fault.  pa may have PTEWRITE set.
+ */
 void
 putmmu(ulong va, ulong pa, Page*)
 {
-	int pdbx;
+	int old;
 	Page *page;
-	ulong *pdb, *pte;
-	int s;
 
-	if(up->mmupdb == 0)
-		up->mmupdb = mmupdballoc();
-	pdb = (ulong*)up->mmupdb->va;
-	pdbx = PDX(va);
-
-	if(PPN(pdb[pdbx]) == 0){
-		if(up->mmufree == 0){
-			page = newpage(1, 0, 0);
-			page->va = VA(kmap(page));
-		}
-		else {
+	if(up->mmupdb == nil)
+		upallocpdb();
+
+	if(!(vpd[PDX(va)]&PTEVALID)){
+		if(up->mmufree == 0)
+			page = newpage(0, 0, 0);
+		else{
 			page = up->mmufree;
 			up->mmufree = page->next;
-			memset((void*)page->va, 0, BY2PG);
 		}
-		pdb[pdbx] = PPN(page->pa)|PTEUSER|PTEWRITE|PTEVALID;
-		page->daddr = pdbx;
+		vpd[PDX(va)] = PPN(page->pa)|PTEUSER|PTEWRITE|PTEVALID;
+		/* page is now mapped into the VPT - clear it */
+		memset((void*)(VPT+PDX(va)*BY2PG), 0, BY2PG);
+		page->daddr = PDX(va);
 		page->next = up->mmuused;
 		up->mmuused = page;
 	}
+	old = vpt[VPTX(va)];
+	vpt[VPTX(va)] = pa|PTEUSER|PTEVALID;
+	if(old&PTEVALID)
+		flushpg(va);
+}
 
-	pte = KADDR(PPN(pdb[pdbx]));
-	pte[PTX(va)] = pa|PTEUSER;
-
-	s = splhi();
-	pdb[PDX(MACHADDR)] = m->pdb[PDX(MACHADDR)];
-	mmuflushtlb(up->mmupdb->pa);
-	splx(s);
+/*
+ * Double-check the user MMU.
+ * Error checking only.
+ */
+void
+checkmmu(ulong va, ulong pa)
+{
+	if(up->mmupdb == 0)
+		return;
+	if(!(vpd[PDX(va)]&PTEVALID) || !(vpt[VPTX(va)]&PTEVALID))
+		return;
+	if(PPN(vpt[VPTX(va)]) != pa)
+		print("%ld %s: va=0x%08lux pa=0x%08lux pte=0x%08lux\n",
+			up->pid, up->text,
+			va, pa, vpt[VPTX(va)]);
 }
 
+/*
+ * Walk the page-table pointed to by pdb and return a pointer
+ * to the entry for virtual address va at the requested level.
+ * If the entry is invalid and create isn't requested then bail
+ * out early. Otherwise, for the 2nd level walk, allocate a new
+ * page-table page and register it in the 1st level.  This is used
+ * only to edit kernel mappings, which use pages from kernel memory,
+ * so it's okay to use KADDR to look at the tables.
+ */
 ulong*
 mmuwalk(ulong* pdb, ulong va, int level, int create)
 {
-	ulong pa, *table;
+	ulong *table;
+	void *map;
 
-	/*
-	 * Walk the page-table pointed to by pdb and return a pointer
-	 * to the entry for virtual address va at the requested level.
-	 * If the entry is invalid and create isn't requested then bail
-	 * out early. Otherwise, for the 2nd level walk, allocate a new
-	 * page-table page and register it in the 1st level.
-	 */
 	table = &pdb[PDX(va)];
 	if(!(*table & PTEVALID) && create == 0)
 		return 0;
@@ -334,163 +441,430 @@ mmuwalk(ulong* pdb, ulong va, int level, int create)
 		if(*table & PTESIZE)
 			panic("mmuwalk2: va %luX entry %luX\n", va, *table);
 		if(!(*table & PTEVALID)){
-			pa = PADDR(xspanalloc(BY2PG, BY2PG, 0));
-			*table = pa|PTEWRITE|PTEVALID;
+			/*
+			 * Have to call low-level allocator from
+			 * memory.c if we haven't set up the xalloc
+			 * tables yet.
+			 */
+			if(didmmuinit)
+				map = xspanalloc(BY2PG, BY2PG, 0);
+			else
+				map = rampage();
+			if(map == nil)
+				panic("mmuwalk xspanalloc failed");
+			*table = PADDR(map)|PTEWRITE|PTEVALID;
 		}
 		table = KADDR(PPN(*table));
-
 		return &table[PTX(va)];
 	}
 }
 
-static Lock mmukmaplock;
-
-int
-mmukmapsync(ulong va)
-{
-	Mach *mach0;
-	ulong entry, *pte;
+/*
+ * Device mappings are shared by all procs and processors and
+ * live in the virtual range VMAP to VMAP+VMAPSIZE.  The master
+ * copy of the mappings is stored in mach0->pdb, and they are
+ * paged in from there as necessary by vmapsync during faults.
+ */
 
-	mach0 = MACHP(0);
+static Lock vmaplock;
 
-	ilock(&mmukmaplock);
+static int findhole(ulong *a, int n, int count);
+static ulong vmapalloc(ulong size);
+static void pdbunmap(ulong*, ulong, int);
 
-	if((pte = mmuwalk(mach0->pdb, va, 1, 0)) == nil){
-		iunlock(&mmukmaplock);
-		return 0;
+/*
+ * Add a device mapping to the vmap range.
+ */
+void*
+vmap(ulong pa, int size)
+{
+	int osize;
+	ulong o, va;
+	
+	/*
+	 * might be asking for less than a page.
+	 */
+	osize = size;
+	o = pa & (BY2PG-1);
+	pa -= o;
+	size += o;
+
+	size = ROUND(size, BY2PG);
+	if(pa == 0){
+		print("vmap pa=0 pc=%#.8lux\n", getcallerpc(&pa));
+		return nil;
 	}
-	if(!(*pte & PTESIZE) && mmuwalk(mach0->pdb, va, 2, 0) == nil){
-		iunlock(&mmukmaplock);
+	ilock(&vmaplock);
+	if((va = vmapalloc(size)) == 0 
+	|| pdbmap(MACHP(0)->pdb, pa|PTEUNCACHED|PTEWRITE, va, size) < 0){
+		iunlock(&vmaplock);
 		return 0;
 	}
-	entry = *pte;
+	iunlock(&vmaplock);
+	/* avoid trap on local processor
+	for(i=0; i<size; i+=4*MB)
+		vmapsync(va+i);
+	*/
+	USED(osize);
+//	print("  vmap %#.8lux %d => %#.8lux\n", pa+o, osize, va+o);
+	return (void*)(va + o);
+}
 
-	if(!(m->pdb[PDX(va)] & PTEVALID))
-		m->pdb[PDX(va)] = entry;
+static int
+findhole(ulong *a, int n, int count)
+{
+	int have, i;
+	
+	have = 0;
+	for(i=0; i<n; i++){
+		if(a[i] == 0)
+			have++;
+		else
+			have = 0;
+		if(have >= count)
+			return i+1 - have;
+	}
+	return -1;
+}
 
-	if(up && up->mmupdb){
-		((ulong*)up->mmupdb->va)[PDX(va)] = entry;
-		mmuflushtlb(up->mmupdb->pa);
+/*
+ * Look for free space in the vmap.
+ */
+static ulong
+vmapalloc(ulong size)
+{
+	int i, n, o;
+	ulong *vpdb;
+	int vpdbsize;
+	
+	vpdb = &MACHP(0)->pdb[PDX(VMAP)];
+	vpdbsize = VMAPSIZE/(4*MB);
+
+	if(size >= 4*MB){
+		n = (size+4*MB-1) / (4*MB);
+		if((o = findhole(vpdb, vpdbsize, n)) != -1)
+			return VMAP + o*4*MB;
+		return VMAP + o;
 	}
-	else
-		mmuflushtlb(PADDR(m->pdb));
+	n = (size+BY2PG-1) / BY2PG;
+	for(i=0; i<vpdbsize; i++)
+		if((vpdb[i]&PTEVALID) && !(vpdb[i]&PTESIZE))
+			if((o = findhole(KADDR(PPN(vpdb[i])), WD2PG, n)) != -1)
+				return VMAP + i*4*MB + o*BY2PG;
+	if((o = findhole(vpdb, vpdbsize, 1)) != -1)
+		return VMAP + o*4*MB;
+		
+	/*
+	 * could span page directory entries, but not worth the trouble.
+	 * not going to be very much contention.
+	 */
+	return 0;
+}
 
-	iunlock(&mmukmaplock);
+/*
+ * Remove a device mapping from the vmap range.
+ * Since pdbunmap does not remove page tables, just entries,
+ * the call need not be interlocked with vmap.
+ */
+void
+vunmap(void *v, int size)
+{
+	int i;
+	ulong va, o;
+	Mach *nm;
+	Proc *p;
+	
+	/*
+	 * might not be aligned
+	 */
+	va = (ulong)v;
+	o = va&(BY2PG-1);
+	va -= o;
+	size += o;
+	size = ROUND(size, BY2PG);
+	
+	if(size < 0 || va < VMAP || va+size > VMAP+VMAPSIZE)
+		panic("vunmap va=%#.8lux size=%#x pc=%#.8lux\n",
+			va, size, getcallerpc(&va));
 
-	return 1;
+	pdbunmap(MACHP(0)->pdb, va, size);
+	
+	/*
+	 * Flush mapping from all the tlbs and copied pdbs.
+	 * This can be (and is) slow, since it is called only rarely.
+	 */
+	for(i=0; i<conf.nproc; i++){
+		p = proctab(i);
+		if(p->state == Dead)
+			continue;
+		if(p != up)
+			p->newtlb = 1;
+	}
+	for(i=0; i<conf.nmach; i++){
+		nm = MACHP(i);
+		if(nm != m)
+			nm->flushmmu = 1;
+	}
+	flushmmu();
+	for(i=0; i<conf.nmach; i++){
+		nm = MACHP(i);
+		if(nm != m)
+			while((active.machs&(1<<nm->machno)) && nm->flushmmu)
+				;
+	}
 }
 
-ulong
-mmukmap(ulong pa, ulong va, int size)
+/*
+ * Add kernel mappings for pa -> va for a section of size bytes.
+ */
+int
+pdbmap(ulong *pdb, ulong pa, ulong va, int size)
 {
-	Mach *mach0;
-	ulong ova, pae, *table, pgsz, *pte, x;
-	int pse, sync;
+	int pse;
+	ulong pae, pgsz, *pte, *table;
+	ulong flag;
+	
+	flag = pa&0xFFF;
+	pa &= ~0xFFF;
 
-	mach0 = MACHP(0);
-	if((mach0->cpuiddx & 0x08) && (getcr4() & 0x10))
+	if((MACHP(0)->cpuiddx & 0x08) && (getcr4() & 0x10))
 		pse = 1;
 	else
 		pse = 0;
-	sync = 0;
-
-	pa = PPN(pa);
-	if(va == 0)
-		va = (ulong)KADDR(pa);
-	else
-		va = PPN(va);
-	ova = va;
 
 	pae = pa + size;
-	ilock(&mmukmaplock);
 	while(pa < pae){
-		table = &mach0->pdb[PDX(va)];
-		/*
-		 * Possibly already mapped.
-		 */
-		if(*table & PTEVALID){
-			if(*table & PTESIZE){
-				/*
-				 * Big page. Does it fit within?
-				 * If it does, adjust pgsz so the correct end can be
-				 * returned and get out.
-				 * If not, adjust pgsz up to the next 4MB boundary
-				 * and continue.
-				 */
-				x = PPN(*table);
-				if(x != pa)
-					panic("mmukmap1: pa %luX  entry %luX\n",
-						pa, *table);
-				x += 4*MB;
-				if(pae <= x){
-					pa = pae;
-					break;
-				}
-				pgsz = x - pa;
-				pa += pgsz;
-				va += pgsz;
-
-				continue;
-			}
-			else{
-				/*
-				 * Little page. Walk to the entry.
-				 * If the entry is valid, set pgsz and continue.
-				 * If not, make it so, set pgsz, sync and continue.
-				 */
-				pte = mmuwalk(mach0->pdb, va, 2, 0);
-				if(pte && *pte & PTEVALID){
-					x = PPN(*pte);
-					if(x != pa)
-						panic("mmukmap2: pa %luX entry %luX\n",
-							pa, *pte);
-					pgsz = BY2PG;
-					pa += pgsz;
-					va += pgsz;
-					sync++;
-
-					continue;
-				}
-			}
-		}
+		table = &pdb[PDX(va)];
+		if((*table&PTEVALID) && (*table&PTESIZE))
+			panic("vmap: va=%#.8lux pa=%#.8lux pde=%#.8lux",
+				va, pa, *table);
 
 		/*
-		 * Not mapped. Check if it can be mapped using a big page -
-		 * starts on a 4MB boundary, size >= 4MB and processor can do it.
-		 * If not a big page, walk the walk, talk the talk.
-		 * Sync is set.
-		 *
-		 * If we're creating a kernel mapping, we know that it will never
-		 * expire and thus we can set the PTEGLOBAL bit to make the entry
-	 	 * persist in the TLB across flushes.  If we do add support later for
-		 * unmapping kernel addresses, see devarch.c for instructions on
-		 * how to do a full TLB flush.
+		 * Check if it can be mapped using a 4MB page:
+		 * va, pa aligned and size >= 4MB and processor can do it.
 		 */
-		if(pse && (pa % (4*MB)) == 0 && (pae >= pa+4*MB)){
-			*table = pa|PTESIZE|PTEWRITE|PTEUNCACHED|PTEVALID;
-			if((va&KZERO) && m->havepge)
-				*table |= PTEGLOBAL;
+		if(pse && pa%(4*MB) == 0 && va%(4*MB) == 0 && (pae >= pa+4*MB)){
+			*table = pa|PTESIZE|flag|PTEVALID;
 			pgsz = 4*MB;
-		}
-		else{
-			pte = mmuwalk(mach0->pdb, va, 2, 1);
-			*pte = pa|PTEWRITE|PTEUNCACHED|PTEVALID;
-			if((va&KZERO) && m->havepge)
-				*pte |= PTEGLOBAL;
+		}else{
+			pte = mmuwalk(pdb, va, 2, 1);
+			if(*pte&PTEVALID)
+				panic("vmap: va=%#.8lux pa=%#.8lux pte=%#.8lux",
+					va, pa, *pte);
+			*pte = pa|flag|PTEVALID;
 			pgsz = BY2PG;
 		}
 		pa += pgsz;
 		va += pgsz;
-		sync++;
 	}
-	iunlock(&mmukmaplock);
+	return 0;
+}
+
+/*
+ * Remove mappings.  Must already exist, for sanity.
+ * Only used for kernel mappings, so okay to use KADDR.
+ */
+static void
+pdbunmap(ulong *pdb, ulong va, int size)
+{
+	ulong vae;
+	ulong *table;
+	
+	vae = va+size;
+	while(va < vae){
+		table = &pdb[PDX(va)];
+		if(!(*table & PTEVALID)){
+			panic("vunmap: not mapped");
+			/* 
+			va = (va+4*MB-1) & ~(4*MB-1);
+			continue;
+			*/
+		}
+		if(*table & PTESIZE){
+			*table = 0;
+			va = (va+4*MB-1) & ~(4*MB-1);
+			continue;
+		}
+		table = KADDR(PPN(*table));
+		if(!(table[PTX(va)] & PTEVALID))
+			panic("vunmap: not mapped");
+		table[PTX(va)] = 0;
+		va += BY2PG;
+	}
+}
+
+/*
+ * Handle a fault by bringing vmap up to date.
+ * Only copy pdb entries and they never go away,
+ * so no locking needed.
+ */
+int
+vmapsync(ulong va)
+{
+	ulong entry, *table;
+
+	if(va < VMAP || va >= VMAP+VMAPSIZE)
+		return 0;
+
+	entry = MACHP(0)->pdb[PDX(va)];
+	if(!(entry&PTEVALID))
+		return 0;
+	if(!(entry&PTESIZE)){
+		/* make sure entry will help the fault */
+		table = KADDR(PPN(entry));
+		if(!(table[PTX(va)]&PTEVALID))
+			return 0;
+	}
+	vpd[PDX(va)] = entry;
+	/*
+	 * TLB doesn't cache negative results, so no flush needed.
+	 */
+	return 1;
+}
+
+
+/*
+ * KMap is used to map individual pages into virtual memory.
+ * It is rare to have more than a few KMaps at a time (in the 
+ * absence of interrupts, only two at a time are ever used,
+ * but interrupts can stack).  The mappings are local to a process,
+ * so we can use the same range of virtual address space for
+ * all processes without any coordination.
+ */
+#define kpt (vpt+VPTX(KMAP))
+#define NKPT (KMAPSIZE/BY2PG)
+
+KMap*
+kmap(Page *page)
+{
+	int i, o, s;
+	Page *pdb;
+
+	if(up == nil)
+		panic("kmap: up=0 pc=%#.8lux", getcallerpc(&page));
+	if(up->mmupdb == nil)
+		upallocpdb();
+	if(!(vpd[PDX(KMAP)]&PTEVALID)){
+		/* allocate page directory */
+		if(KMAPSIZE > BY2XPG)
+			panic("bad kmapsize");
+		s = spllo();
+		pdb = newpage(0, 0, 0);
+		splx(s);
+		vpd[PDX(KMAP)] = pdb->pa|PTEWRITE|PTEVALID;
+		memset(kpt, 0, BY2PG);
+
+		/* might as well finish the job */
+		kpt[0] = page->pa|PTEWRITE|PTEVALID;
+		up->lastkmap = 0;
+		return (KMap*)KMAP;
+	}
+	o = up->lastkmap+1;
+	for(i=0; i<NKPT; i++){
+		if(kpt[(i+o)%NKPT] == 0){
+			o = (i+o)%NKPT;
+			kpt[o] = page->pa|PTEWRITE|PTEVALID;
+			up->lastkmap = o;
+			return (KMap*)(KMAP+o*BY2PG);
+		}
+	}
+	panic("out of kmap");
+	return nil;
+}
+
+void
+kunmap(KMap *k)
+{
+	ulong va;
+
+	va = (ulong)k;
+	if(up->mmupdb == nil || !(vpd[PDX(KMAP)]&PTEVALID))
+		panic("kunmap: no kmaps");
+	if(va < KMAP || va >= KMAP+KMAPSIZE)
+		panic("kunmap: bad address %#.8lux pc=%#.8lux", va, getcallerpc(&k));
+	if(!(vpt[VPTX(va)]&PTEVALID))
+		panic("kunmap: not mapped %#.8lux pc=%#.8lux", va, getcallerpc(&k));
+	vpt[VPTX(va)] = 0;
+	flushpg(va);
+}
+
+
+/*
+ * Temporary one-page mapping used to edit page directories.
+ *
+ * The fasttmp #define controls whether the code optimizes
+ * the case where the page is already mapped in the physical
+ * memory window.  
+ */
+#define fasttmp 1
+
+void*
+tmpmap(Page *p)
+{
+	ulong i;
+	ulong *entry;
+	
+	if(islo())
+		panic("tmpaddr: islo");
+
+	if(fasttmp && p->pa < -KZERO)
+		return KADDR(p->pa);
 
 	/*
-	 * If something was added
-	 * then need to sync up.
+	 * PDX(TMPADDR) == PDX(MACHADDR), so this
+	 * entry is private to the processor and shared 
+	 * between up->mmupdb (if any) and m->pdb.
 	 */
-	if(sync)
-		mmukmapsync(ova);
+	entry = &vpt[VPTX(TMPADDR)];
+	if(!(*entry&PTEVALID)){
+		for(i=KZERO; i<=CPU0MACH; i+=BY2PG)
+			print("%.8lux: *%.8lux=%.8lux (vpt=%.8lux index=%.8lux)\n", i, &vpt[VPTX(i)], vpt[VPTX(i)], vpt, VPTX(i));
+		panic("tmpmap: no entry");
+	}
+	if(PPN(*entry) != PPN(TMPADDR-KZERO))
+		panic("tmpmap: already mapped entry=%#.8lux", *entry);
+	*entry = p->pa|PTEWRITE|PTEVALID;
+	flushpg(TMPADDR);
+	return (void*)TMPADDR;
+}
 
-	return pa;
+void
+tmpunmap(void *v)
+{
+	ulong *entry;
+	
+	if(islo())
+		panic("tmpaddr: islo");
+	if(fasttmp && (ulong)v >= KZERO && v != (void*)TMPADDR)
+		return;
+	if(v != (void*)TMPADDR)
+		panic("tmpunmap: bad address");
+	entry = &vpt[VPTX(TMPADDR)];
+	if(!(*entry&PTEVALID) || PPN(*entry) == PPN(PADDR(TMPADDR)))
+		panic("tmpmap: not mapped entry=%#.8lux", *entry);
+	*entry = PPN(TMPADDR-KZERO)|PTEWRITE|PTEVALID;
+	flushpg(TMPADDR);
+}
+
+/*
+ * These could go back to being macros once the kernel is debugged,
+ * but the extra checking is nice to have.
+ */
+void*
+kaddr(ulong pa)
+{
+	if(pa > (ulong)-KZERO)
+		panic("kaddr: pa=%#.8lux", pa);
+	return (void*)(pa+KZERO);
+}
+
+ulong
+paddr(void *v)
+{
+	ulong va;
+	
+	va = (ulong)v;
+	if(va < KZERO)
+		panic("paddr: va=%#.8lux", va);
+	return va-KZERO;
 }

+ 10 - 5
sys/src/9/pc/mp.c

@@ -137,6 +137,7 @@ static Apic*
 mkioapic(PCMPioapic* p)
 {
 	Apic *apic;
+	void *va;
 
 	if(!(p->flags & PcmpEN) || p->apicno > MaxAPICNO)
 		return 0;
@@ -144,13 +145,13 @@ mkioapic(PCMPioapic* p)
 	/*
 	 * Map the I/O APIC.
 	 */
-	if(mmukmap(p->addr, 0, 1024) == 0)
+	if((va = vmap(p->addr, 1024)) == 0)
 		return 0;
 
 	apic = &mpapic[p->apicno];
 	apic->type = PcmpIOAPIC;
 	apic->apicno = p->apicno;
-	apic->addr = KADDR(p->addr);
+	apic->addr = va;
 	apic->flags = p->flags;
 
 	return apic;
@@ -440,6 +441,9 @@ mpstartap(Apic* apic)
 	*p++ = PADDR(APBOOTSTRAP);
 	*p++ = PADDR(APBOOTSTRAP)>>8;
 	i = (PADDR(APBOOTSTRAP) & ~0xFFFF)/16;
+	/* code assumes i==0 */
+	if(i != 0)
+		print("mp: bad APBOOTSTRAP\n");
 	*p++ = i;
 	*p = i>>8;
 
@@ -465,6 +469,7 @@ mpinit(void)
 	PCMP *pcmp;
 	uchar *e, *p;
 	Apic *apic, *bpapic;
+	void *va;
 
 	i8259init();
 	syncclock();
@@ -476,7 +481,7 @@ mpinit(void)
 	/*
 	 * Map the local APIC.
 	 */
-	if(mmukmap(pcmp->lapicbase, 0, 1024) == 0)
+	if((va = vmap(pcmp->lapicbase, 1024)) == nil)
 		return;
 
 	bpapic = nil;
@@ -508,7 +513,7 @@ mpinit(void)
 			 * guarantee that the bootstrap processor appears
 			 * first in the table before the others.
 			 */
-			apic->addr = KADDR(pcmp->lapicbase);
+			apic->addr = va;
 			if(apic->flags & PcmpBP)
 				bpapic = apic;
 		}
@@ -766,7 +771,7 @@ mpintrenable(Vctl* v)
 		if(vno != -1)
 			return vno;
 	}
-
+	print("mpintrenable: out of choices %d %d\n", mpeisabus, mpisabus);
 	return -1;
 }
 

+ 2 - 0
sys/src/9/pc/mp.h

@@ -217,6 +217,8 @@ extern void lapicspurious(Ureg*, void*);
 extern int lapicisr(int);
 extern int lapiceoi(int);
 extern void lapicicrw(int, int);
+extern void lapicintron(void);
+extern void lapicintroff(void);
 
 extern void mpinit(void);
 extern void mpshutdown(void);

+ 2 - 0
sys/src/9/pc/pc

@@ -38,6 +38,7 @@ dev
 link
 	devpccard
 	devi82365
+	realmode
 	ether2000	ether8390
 	ether2114x	pci
 	ether589	etherelnk3
@@ -93,6 +94,7 @@ misc
 	vgat2r4		+cur
 	vgatvp3020	=cur
 	vgatvp3026	=cur
+	vgavesa
 	vgavmware	+cur
 
 ip

+ 4 - 1
sys/src/9/pc/pcauth

@@ -37,13 +37,14 @@ link
 	loopbackmedium
 
 misc
+	realmode
 	sdata		pci sdscsi
 
 	uarti8250
 	uartpci
 
 	vgamach64xx	+cur
-	vgas3  +cur vgasavage
+	vgas3 		+cur vgasavage
 
 ip
 	il
@@ -65,4 +66,6 @@ bootdir
 	bootpcauth.out boot
 	/386/bin/ip/ipconfig
 	/386/bin/auth/factotum
+	/386/bin/fossil/fossil
+	/386/bin/venti/venti
 	/386/bin/disk/kfs

+ 1 - 0
sys/src/9/pc/pccd

@@ -61,6 +61,7 @@ link
 	usbuhci
 
 misc
+	realmode
 	archmp		mp apic
 
 	sdata		pci sdscsi

+ 2 - 0
sys/src/9/pc/pccpu

@@ -28,6 +28,7 @@ dev
 	usb
 
 link
+	realmode
 	ether2000	ether8390
 	ether2114x	pci
 	ether79c970	pci
@@ -53,6 +54,7 @@ misc
 
 	sdata		pci sdscsi
 	sd53c8xx	pci sdscsi
+	sdmv50xx	pci sdscsi
 
 
 ip

+ 2 - 0
sys/src/9/pc/pccpuf

@@ -58,6 +58,7 @@ link
 	usbuhci
 
 misc
+	realmode
 	archmp		mp apic
 
 	uarti8250
@@ -86,6 +87,7 @@ misc
 	vgat2r4		+cur
 	vgatvp3020	=cur
 	vgatvp3026	=cur
+	vgavesa
 	vgavmware	+cur
 
 

+ 2 - 0
sys/src/9/pc/pcdisk

@@ -60,6 +60,7 @@ link
 	usbuhci
 
 misc
+	realmode
 	archmp		mp apic
 
 	sdata		pci sdscsi
@@ -89,6 +90,7 @@ misc
 	vgat2r4		+cur
 	vgatvp3020	=cur
 	vgatvp3026	=cur
+	vgavesa
 	vgavmware	+cur
 
 ip

+ 2 - 0
sys/src/9/pc/pcf

@@ -62,6 +62,7 @@ link
 	usbuhci
 
 misc
+	realmode
 	archmp		mp apic
 
 	sdata		pci sdscsi
@@ -91,6 +92,7 @@ misc
 	vgat2r4		+cur
 	vgatvp3020	=cur
 	vgatvp3026	=cur
+	vgavesa
 	vgavmware	+cur
 
 ip

+ 2 - 0
sys/src/9/pc/pcflop

@@ -62,6 +62,7 @@ link
 #	usbuhci
 
 misc
+	realmode
 #	archmp		mp apic
 
 	sdata		pci sdscsi
@@ -91,6 +92,7 @@ misc
 	vgat2r4		+cur
 	vgatvp3020	=cur
 	vgatvp3026	=cur
+	vgavesa
 	vgavmware	+cur
 
 ip

+ 19 - 0
sys/src/9/pc/pci.c

@@ -759,6 +759,8 @@ pcirouting(void)
 	}
 }
 
+static void pcireservemem(void);
+
 static void
 pcicfginit(void)
 {
@@ -898,12 +900,29 @@ pcicfginit(void)
 		pcirouting();
 
 out:
+	pcireservemem();
 	unlock(&pcicfginitlock);
 
 	if(getconf("*pcihinv"))
 		pcihinv(nil);
 }
 
+static void
+pcireservemem(void)
+{
+	int i;
+	Pcidev *p;
+	
+	/*
+	 * mark all the physical address space claimed by pci devices
+	 * as in use, so that upaalloc doesn't give it out.
+	 */
+	for(p=pciroot; p; p=p->list)
+		for(i=0; i<nelem(p->mem); i++)
+			if(p->mem[i].bar && (p->mem[i].bar&1) == 0)
+				upareserve(p->mem[i].bar&~0x0F, p->mem[i].size);
+}
+
 static int
 pcicfgrw8(int tbdf, int rno, int data, int read)
 {

+ 132 - 0
sys/src/9/pc/realmode.c

@@ -0,0 +1,132 @@
+#include	"u.h"
+#include	"tos.h"
+#include	"../port/lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"io.h"
+#include	"ureg.h"
+#include	"../port/error.h"
+
+/*
+ * Back the processor into real mode to run a BIOS call,
+ * then return.  This must be used carefully, since it 
+ * completely disables hardware interrupts (e.g., the i8259)
+ * while running.  It is *not* using VM86 mode. 
+ * Maybe that's really the right answer, but real mode
+ * is fine for now.  We don't expect to use this very much --
+ * just for VGA and APM.
+ */
+#define realmoderegs (*(Ureg*)RMUADDR)
+
+#define LORMBUF (RMBUF-KZERO)
+
+static Ureg rmu;
+static Lock rmlock;
+
+void
+realmode(Ureg *ureg)
+{
+	int s;
+	extern void realmode0(void);	/* in l.s */
+	extern void i8259off(void), i8259on(void);
+
+	if(getconf("*norealmode"))
+		return;
+
+	lock(&rmlock);
+	realmoderegs = *ureg;
+
+	/* copy l.s so that it can be run from 16-bit mode */
+	memmove((void*)RMCODE, (void*)KTZERO, 0x1000);
+
+	s = splhi();
+	m->pdb[PDX(0)] = m->pdb[PDX(KZERO)];	/* identity map low */
+	putcr3(PADDR(m->pdb));
+	i8259off();
+	realmode0();
+	if(m->tss){
+		/*
+		 * Called from memory.c before initialization of mmu.
+		 * Don't turn interrupts on before the kernel is ready!
+		 */
+		i8259on();
+		putcr3(m->tss->cr3);
+	}
+	m->pdb[PDX(0)] = 0;	/* remove low mapping */
+	splx(s);
+	*ureg = realmoderegs;
+	unlock(&rmlock);
+}
+
+static long
+rtrapread(Chan*, void *a, long n, vlong off)
+{
+	if(off < 0)
+		error("badarg");
+	if(n+off > sizeof rmu)
+		n = sizeof rmu - off;
+	if(n <= 0)
+		return 0;
+	memmove(a, (char*)&rmu+off, n);
+	return n;
+}
+
+static long
+rtrapwrite(Chan*, void *a, long n, vlong off)
+{
+	if(off || n != sizeof rmu)
+		error("write a Ureg");
+	memmove(&rmu, a, sizeof rmu);
+	/*
+	 * Sanity check
+	 */
+	if(rmu.trap == 0x10){	/* VBE */
+		rmu.es = (LORMBUF>>4)&0xF000;
+		rmu.di = LORMBUF&0xFFFF;
+	}else
+		error("invalid trap arguments");
+	realmode(&rmu);
+	return n;
+}
+
+static long
+rmemrw(int isr, void *a, long n, vlong off)
+{
+	if(off >= 1024*1024 || off+n >= 1024*1024)
+		return 0;
+	if(off < 0 || n < 0)
+		error("bad offset/count");
+	if(isr)
+		memmove(a, KADDR((ulong)off), n);
+	else{
+		/* writes are more restricted */
+		if(LORMBUF <= off && off < LORMBUF+BY2PG
+		&& off+n <= LORMBUF+BY2PG)
+			{}
+		else
+			error("bad offset/count in write");
+		memmove(KADDR((ulong)off), a, n);
+	}
+	return n;
+}
+
+static long
+rmemread(Chan*, void *a, long n, vlong off)
+{
+	return rmemrw(1, a, n, off);
+}
+
+static long
+rmemwrite(Chan*, void *a, long n, vlong off)
+{
+	return rmemrw(0, a, n, off);
+}
+
+void
+realmodelink(void)
+{
+	addarchfile("realmode", 0660, rtrapread, rtrapwrite);
+	addarchfile("realmodemem", 0660, rmemread, rmemwrite);
+}
+

+ 0 - 7
sys/src/9/pc/reboot.h

@@ -1,7 +0,0 @@
-uchar rebootcode[]={
-0x8b,0x7c,0x24,0x04,0x89,0xf8,0x8b,0x74,0x24,0x08,0x8b,0x4c,0x24,0x0c,0x0f,0x20,
-0xc2,0x81,0xe2,0xff,0xff,0xff,0x7f,0x0f,0x22,0xc2,0x31,0xd2,0x0f,0x22,0xda,0x39,
-0xfe,0x7f,0x08,0x89,0xf2,0x01,0xca,0x39,0xfa,0x7f,0x07,0xfc,0xf3,0xa4,0x09,0xc0,
-0xff,0xe0,0x01,0xcf,0x01,0xce,0x4f,0x4e,0xfd,0xf3,0xa4,0xeb,0xf1,
-
-};

+ 339 - 28
sys/src/9/pc/screen.c

@@ -38,11 +38,14 @@ Cursor	arrow = {
 	},
 };
 
+int didswcursorinit;
+
 int
 screensize(int x, int y, int z, ulong chan)
 {
 	VGAscr *scr;
 
+	lock(&vgascreenlock);
 	memimageinit();
 	scr = &vgascreen[0];
 
@@ -50,7 +53,7 @@ screensize(int x, int y, int z, ulong chan)
 	 * BUG: need to check if any xalloc'ed memory needs to
 	 * be given back if aperture is set.
 	 */
-	if(scr->aperture == 0){
+	if(scr->paddr == 0){
 		int width = (x*z)/BI2WD;
 
 		gscreendata.bdata = xalloc(width*BY2WD*y);
@@ -58,19 +61,23 @@ screensize(int x, int y, int z, ulong chan)
 			error("screensize: vga soft memory");
 /*		memset(gscreendata.bdata, 0x72, width*BY2WD*y);	/* not really black */
 		scr->useflush = 1;
-		scr->aperture = VGAMEM();
+		scr->paddr = VGAMEM();
+		scr->vaddr = KADDR(scr->paddr);
 		scr->apsize = 1<<16;
 	}
 	else
-		gscreendata.bdata = KADDR(scr->aperture);
+		gscreendata.bdata = scr->vaddr;
 
 	if(gscreen)
 		freememimage(gscreen);
+	scr->gscreen = nil;
 
 	gscreen = allocmemimaged(Rect(0,0,x,y), chan, &gscreendata);
 	vgaimageinit(chan);
-	if(gscreen == nil)
+	if(gscreen == nil){
+		unlock(&vgascreenlock);
 		return -1;
+	}
 
 	if(scr->dev && scr->dev->flush)
 		scr->useflush = 1;
@@ -81,7 +88,10 @@ screensize(int x, int y, int z, ulong chan)
 	scr->gscreen = gscreen;
 
 	physgscreenr = gscreen->r;
+	unlock(&vgascreenlock);
 
+	if(didswcursorinit)
+		swcursorinit();
 	drawcmap();
 	return 0;
 }
@@ -90,32 +100,31 @@ int
 screenaperture(int size, int align)
 {
 	VGAscr *scr;
-	ulong aperture;
 
 	scr = &vgascreen[0];
 
-	if(size == 0){
-		if(scr->aperture && scr->isupamem)
-			upafree(scr->aperture, scr->apsize);
-		scr->aperture = 0;
-		scr->isupamem = 0;
+	if(scr->paddr)	/* set up during enable */
 		return 0;
-	}
+
+	if(size == 0)
+		return 0;
+
 	if(scr->dev && scr->dev->linear){
-		aperture = scr->dev->linear(scr, &size, &align);
-		if(aperture == 0)
-			return 1;
-	}else{
-		aperture = upamalloc(0, size, align);
-		if(aperture == 0)
-			return 1;
-
-		if(scr->aperture && scr->isupamem)
-			upafree(scr->aperture, scr->apsize);
-		scr->isupamem = 1;
+		scr->dev->linear(scr, size, align);
+		return 0;
 	}
 
-	scr->aperture = aperture;
+	/*
+	 * Need to allocate some physical address space.
+	 * The driver will tell the card to use it.
+	 */
+	size = PGROUND(size);
+	scr->paddr = upaalloc(size, align);
+	if(scr->paddr == 0)
+		return -1;
+	scr->vaddr = vmap(scr->paddr, size);
+	if(scr->vaddr == nil)
+		return -1;
 	scr->apsize = size;
 
 	return 0;
@@ -179,7 +188,7 @@ flushmemscreen(Rectangle r)
 	off = r.min.y*scr->gscreen->width*BY2WD+(r.min.x*scr->gscreen->depth)/8;
 	page = off/scr->apsize;
 	off %= scr->apsize;
-	disp = KADDR(scr->aperture);
+	disp = scr->vaddr;
 	sdisp = disp+off;
 	edisp = disp+scr->apsize;
 
@@ -339,17 +348,29 @@ int
 hwdraw(Memdrawparam *par)
 {
 	VGAscr *scr;
-	Memimage *dst, *src;
+	Memimage *dst, *src, *mask;
 	int m;
 
 	if(hwaccel == 0)
 		return 0;
 
-	dst = par->dst;
 	scr = &vgascreen[0];
-	if(dst == nil || dst->data == nil)
+	if((dst=par->dst) == nil || dst->data == nil)
+		return 0;
+	if((src=par->src) == nil || src->data == nil)
+		return 0;
+	if((mask=par->mask) == nil || mask->data == nil)
 		return 0;
 
+	if(scr->cur == &swcursor){
+		if(dst->data->bdata == gscreendata.bdata)
+			swcursoravoid(par->r);
+		if(src->data->bdata == gscreendata.bdata)
+			swcursoravoid(par->sr);
+		if(mask->data->bdata == gscreendata.bdata)
+			swcursoravoid(par->mr);
+	}
+	
 	if(dst->data->bdata != gscreendata.bdata)
 		return 0;
 
@@ -374,7 +395,6 @@ hwdraw(Memdrawparam *par)
 	 * the source is not replicated, memmove suffices.
 	 */
 	m = Simplemask|Fullmask;
-	src = par->src;
 	if(scr->scroll
 	&& src->data->bdata==dst->data->bdata
 	&& !(src->flags&Falpha)
@@ -398,3 +418,294 @@ blankscreen(int blank)
 			vgablank(scr, blank);
 	}
 }
+
+void
+vgalinearpciid(VGAscr *scr, int vid, int did)
+{
+	Pcidev *p;
+
+	p = nil;
+	while((p = pcimatch(p, vid, 0)) != nil){
+		if(p->ccrb != 3)	/* video card */
+			continue;
+		if(did != 0 && p->did != did)
+			continue;
+		break;
+	}
+	if(p == nil)
+		error("pci video card not found");
+
+	scr->pci = p;
+	vgalinearpci(scr);
+}
+
+void
+vgalinearpci(VGAscr *scr)
+{
+	ulong paddr;
+	int i, size, best;
+	Pcidev *p;
+	
+	p = scr->pci;
+	if(p == nil)
+		return;
+
+	/*
+	 * Scan for largest memory region on card.
+	 * Some S3 cards (e.g. Savage) have enormous
+	 * mmio regions (but even larger frame buffers).
+	 */
+	best = -1;
+	for(i=0; i<nelem(p->mem); i++){
+		if(p->mem[i].bar&1)	/* not memory */
+			continue;
+		if(p->mem[i].size < 640*480)	/* not big enough */
+			continue;
+		if(best==-1 || p->mem[i].size > p->mem[best].size)
+			best = i;
+	}
+	if(best >= 0){
+		paddr = p->mem[best].bar & ~0x0F;
+		size = p->mem[best].size;
+		vgalinearaddr(scr, paddr, size);
+		return;
+	}
+	error("no video memory found on pci card");
+}
+
+void
+vgalinearaddr(VGAscr *scr, ulong paddr, int size)
+{
+	int x, nsize;
+	ulong npaddr;
+
+	/*
+	 * new approach.  instead of trying to resize this
+	 * later, let's assume that we can just allocate the
+	 * entire window to start with.
+	 */
+
+	if(scr->paddr == paddr && size <= scr->apsize)
+		return;
+
+	if(scr->paddr){
+		/*
+		 * could call vunmap and vmap,
+		 * but worried about dangling pointers in devdraw
+		 */
+		error("cannot grow vga frame buffer");
+	}
+	
+	/* round to page boundary, just in case */
+	x = paddr&(BY2PG-1);
+	npaddr = paddr-x;
+	nsize = PGROUND(size+x);
+
+	scr->vaddr = vmap(npaddr, nsize);
+	if(scr->vaddr == 0)
+		error("cannot allocate vga frame buffer");
+	scr->vaddr = (char*)scr->vaddr+x;
+	scr->paddr = paddr;
+	scr->apsize = nsize;
+}
+
+
+/*
+ * Software cursor. 
+ */
+int	swvisible;	/* is the cursor visible? */
+int	swenabled;	/* is the cursor supposed to be on the screen? */
+Memimage*	swback;	/* screen under cursor */
+Memimage*	swimg;	/* cursor image */
+Memimage*	swmask;	/* cursor mask */
+Memimage*	swimg1;
+Memimage*	swmask1;
+
+Point	swoffset;
+Rectangle	swrect;	/* screen rectangle in swback */
+Point	swpt;	/* desired cursor location */
+Point	swvispt;	/* actual cursor location */
+int	swvers;	/* incremented each time cursor image changes */
+int	swvisvers;	/* the version on the screen */
+
+/*
+ * called with drawlock locked for us, most of the time.
+ * kernel prints at inopportune times might mean we don't
+ * hold the lock, but memimagedraw is now reentrant so
+ * that should be okay: worst case we get cursor droppings.
+ */
+void
+swcursorhide(void)
+{
+	if(swvisible == 0)
+		return;
+	if(swback == nil)
+		return;
+	swvisible = 0;
+	memimagedraw(gscreen, swrect, swback, ZP, memopaque, ZP, S);
+}
+
+void
+swcursoravoid(Rectangle r)
+{
+	if(swvisible && rectXrect(r, swrect))
+		swcursorhide();
+}
+
+void
+swcursordraw(void)
+{
+	if(swvisible)
+		return;
+	if(swenabled == 0)
+		return;
+	if(swback == nil || swimg1 == nil || swmask1 == nil)
+		return;
+	assert(!canqlock(&drawlock));
+	swvispt = swpt;
+	swvisvers = swvers;
+	swrect = rectaddpt(Rect(0,0,16,16), swvispt);
+	memimagedraw(swback, swback->r, gscreen, swpt, memopaque, ZP, S);
+	memimagedraw(gscreen, swrect, swimg1, ZP, swmask1, ZP, SoverD);
+	swvisible = 1;
+}
+
+/*
+ * Need to lock drawlock for ourselves.
+ */
+void
+swenable(VGAscr*)
+{
+	swenabled = 1;
+	if(canqlock(&drawlock)){
+		swcursordraw();
+		qunlock(&drawlock);
+	}
+}
+
+void
+swdisable(VGAscr*)
+{
+	swenabled = 0;
+	if(canqlock(&drawlock)){
+		swcursorhide();
+		qunlock(&drawlock);
+	}
+}
+
+void
+swload(VGAscr*, Cursor *curs)
+{
+	uchar *ip, *mp;
+	int i, j, set, clr;
+
+	if(!swimg || !swmask || !swimg1 || !swmask1)
+		return;
+	/*
+	 * Build cursor image and mask.
+	 * Image is just the usual cursor image
+	 * but mask is a transparent alpha mask.
+	 * 
+	 * The 16x16x8 memimages do not have
+	 * padding at the end of their scan lines.
+	 */
+	ip = byteaddr(swimg, ZP);
+	mp = byteaddr(swmask, ZP);
+	for(i=0; i<32; i++){
+		set = curs->set[i];
+		clr = curs->clr[i];
+		for(j=0x80; j; j>>=1){
+			*ip++ = set&j ? 0x00 : 0xFF;
+			*mp++ = (clr|set)&j ? 0xFF : 0x00;
+		}
+	}
+	swoffset = curs->offset;
+	swvers++;
+	memimagedraw(swimg1, swimg1->r, swimg, ZP, memopaque, ZP, S);
+	memimagedraw(swmask1, swmask1->r, swmask, ZP, memopaque, ZP, S);
+}
+
+int
+swmove(VGAscr*, Point p)
+{
+	swpt = addpt(p, swoffset);
+	return 0;
+}
+
+void
+swcursorclock(void)
+{
+	int x;
+
+	if(!swenabled)
+		return;
+	if(swvisible && eqpt(swpt, swvispt) && swvers==swvisvers)
+		return;
+
+	x = splhi();
+	if(swenabled)
+	if(!swvisible || !eqpt(swpt, swvispt) || swvers!=swvisvers)
+	if(canqlock(&drawlock)){
+		swcursorhide();
+		swcursordraw();
+		qunlock(&drawlock);
+	}
+	splx(x);
+}
+
+void
+swcursorinit(void)
+{
+	static int init, warned;
+	VGAscr *scr;
+
+	didswcursorinit = 1;
+	if(!init){
+		init = 1;
+		addclock0link(swcursorclock, 50);
+	}
+	scr = &vgascreen[0];
+	if(scr==nil || scr->gscreen==nil)
+		return;
+
+	if(scr->dev == nil || scr->dev->linear == nil){
+		if(!warned){
+			print("cannot use software cursor on non-linear vga screen\n");
+			warned = 1;
+		}
+		return;
+	}
+
+	if(swback){
+		freememimage(swback);
+		freememimage(swmask);
+		freememimage(swmask1);
+		freememimage(swimg);
+		freememimage(swimg1);
+	}
+
+	swback = allocmemimage(Rect(0,0,32,32), gscreen->chan);
+	swmask = allocmemimage(Rect(0,0,16,16), GREY8);
+	swmask1 = allocmemimage(Rect(0,0,16,16), GREY1);
+	swimg = allocmemimage(Rect(0,0,16,16), GREY8);
+	swimg1 = allocmemimage(Rect(0,0,16,16), GREY1);
+	if(swback==nil || swmask==nil || swmask1==nil || swimg==nil || swimg1 == nil){
+		print("software cursor: allocmemimage: %r");
+		return;
+	}
+
+	memfillcolor(swmask, DOpaque);
+	memfillcolor(swmask1, DOpaque);
+	memfillcolor(swimg, DBlack);
+	memfillcolor(swimg1, DBlack);
+}
+
+VGAcur swcursor =
+{
+	"soft",
+	swenable,
+	swdisable,
+	swload,
+	swmove,
+};
+

+ 25 - 7
sys/src/9/pc/screen.h

@@ -67,7 +67,7 @@ struct VGAdev {
 	void	(*enable)(VGAscr*);
 	void	(*disable)(VGAscr*);
 	void	(*page)(VGAscr*, int);
-	ulong	(*linear)(VGAscr*, int*, int*);
+	void	(*linear)(VGAscr*, int, int);
 	void	(*drawinit)(VGAscr*);
 	int	(*fill)(VGAscr*, Rectangle, ulong);
 	void	(*ovlctl)(VGAscr*, Chan*, void*, int);
@@ -91,6 +91,7 @@ struct VGAcur {
 struct VGAscr {
 	Lock	devlock;
 	VGAdev*	dev;
+	Pcidev*	pci;
 
 	VGAcur*	cur;
 	ulong	storage;
@@ -98,16 +99,16 @@ struct VGAscr {
 
 	int	useflush;
 
-	ulong	aperture;			/* physical address */
-	int	isupamem;
-	int	apsize;
+	ulong	paddr;		/* frame buffer */
+	void*	vaddr;
+	int		apsize;
 
 	ulong	io;				/* device specific registers */
-
+	ulong	*mmio;
+	
 	ulong	colormap[Pcolours][3];
 	int	palettedepth;
 
-	ulong	*mmio;
 	Memimage* gscreen;
 	Memdata* gscreendata;
 	Memsubfont* memdefont;
@@ -128,6 +129,7 @@ enum {
 
 /* mouse.c */
 extern void mousectl(Cmdbuf*);
+extern void mouseresize(void);
 
 /* screen.c */
 extern int		hwaccel;	/* use hw acceleration; default on */
@@ -144,18 +146,34 @@ extern int	screenaperture(int, int);
 extern Rectangle physgscreenr;	/* actual monitor size */
 extern void	blankscreen(int);
 
+extern VGAcur swcursor;
+extern void swcursorinit(void);
+extern void swcursorhide(void);
+extern void swcursoravoid(Rectangle);
+extern void swcursorunhide(void);
+
 /* devdraw.c */
 extern void	deletescreenimage(void);
+extern void	resetscreenimage(void);
 extern int		drawhasclients(void);
 extern ulong	blanktime;
 extern void	setscreenimageclipr(Rectangle);
 extern void	drawflush(void);
 extern int drawidletime(void);
+extern QLock	drawlock;
 
 /* vga.c */
 extern void	vgascreenwin(VGAscr*);
 extern void	vgaimageinit(ulong);
-extern ulong	vgapcilinear(VGAscr*, int*, int*, int, int);
+extern void	vgalinearpciid(VGAscr*, int, int);
+extern void	vgalinearpci(VGAscr*);
+extern void	vgalinearaddr(VGAscr*, ulong, int);
 
 extern void	drawblankscreen(int);
 extern void	vgablank(VGAscr*, int);
+
+extern Lock	vgascreenlock;
+
+
+
+

+ 190 - 68
sys/src/9/pc/sd53c8xx.c

@@ -52,8 +52,9 @@ extern SDifc sd53c8xxifc;
 
 #else
 
-#define KPRINT	if(0) print
-#define IPRINT	if(0) print
+static int idebug = 1;
+#define KPRINT	if(0) iprint
+#define IPRINT	if(idebug) iprint
 #define DEBUG(n)	(0)
 #define IFLUSH()
 
@@ -304,7 +305,6 @@ typedef struct Controller {
 	struct {
 		Lock;
 		uchar head[4];		/* head of free list (NCR byte order) */
-		Dsa	*tail;
 		Dsa	*freechain;
 	} dsalist;
 
@@ -383,32 +383,51 @@ oprint(char *format, ...)
 
 #include "sd53c8xx.i"
 
+/*
+ * We used to use a linked list of Dsas with nil as the terminator,
+ * but occasionally the 896 card seems not to notice that the 0
+ * is really a 0, and then it tries to reference the Dsa at address 0.
+ * To address this, we use a sentinel dsa that links back to itself
+ * and has state A_STATE_END.  If the card takes an iteration or
+ * two to notice that the state says A_STATE_END, that's no big 
+ * deal.  Clearly this isn't the right approach, but I'm just
+ * stumped.  Even with this, we occasionally get prints about
+ * "WSR set", usually with about the same frequency that the
+ * card used to walk past 0. 
+ */
+static Dsa *dsaend;
+
+static Dsa*
+dsaallocnew(Controller *c)
+{
+	Dsa *d;
+	
+	/* c->dsalist must be ilocked */
+	d = xalloc(sizeof *d);
+	lesetl(d->next, legetl(c->dsalist.head));
+	lesetl(&d->stateb, A_STATE_FREE);
+	coherence();
+	lesetl(c->dsalist.head, DMASEG(d));
+	coherence();
+	return d;
+}
+
 static Dsa *
 dsaalloc(Controller *c, int target, int lun)
 {
 	Dsa *d;
 
 	ilock(&c->dsalist);
-	if ((d = c->dsalist.freechain) == 0) {
-		d = xalloc(sizeof(*d));
-		if (DEBUG(1)) {
-			KPRINT(PRINTPREFIX "%d/%d: allocated new dsa %lux\n", target, lun, (ulong)d);
-		}
-		lesetl(d->next, 0);
-		lesetl(&d->stateb, A_STATE_ALLOCATED);
-		if (legetl(c->dsalist.head) == 0)
-			lesetl(c->dsalist.head, DMASEG(d));	/* ATOMIC?!? */
-		else
-			lesetl(c->dsalist.tail->next, DMASEG(d));	/* ATOMIC?!? */
-		c->dsalist.tail = d;
-	}
-	else {
-		if (DEBUG(1)) {
-			KPRINT(PRINTPREFIX "%d/%d: reused dsa %lux\n", target, lun, (ulong)d);
-		}
-		c->dsalist.freechain = d->freechain;
-		lesetl(&d->stateb, A_STATE_ALLOCATED);
+	if ((d = c->dsalist.freechain) != 0) {
+		if (DEBUG(1))
+			IPRINT(PRINTPREFIX "%d/%d: reused dsa %lux\n", target, lun, (ulong)d);
+	} else {	
+		d = dsaallocnew(c);
+		if (DEBUG(1))
+			IPRINT(PRINTPREFIX "%d/%d: allocated dsa %lux\n", target, lun, (ulong)d);
 	}
+	c->dsalist.freechain = d->freechain;
+	lesetl(&d->stateb, A_STATE_ALLOCATED);
 	iunlock(&c->dsalist);
 	d->target = target;
 	d->lun = lun;
@@ -425,11 +444,50 @@ dsafree(Controller *c, Dsa *d)
 	iunlock(&c->dsalist);
 }
 
+static void
+dsadump(Controller *c)
+{
+	Dsa *d;
+	u32int *a;
+	
+	iprint("dsa controller list: c=%p head=%.8lux\n", c, legetl(c->dsalist.head));
+	for(d=KPTR(legetl(c->dsalist.head)); d != dsaend; d=KPTR(legetl(d->next))){
+		if(d == (void*)-1){
+			iprint("\t dsa %p\n", d);
+			break;
+		}
+		a = (u32int*)d;
+		iprint("\tdsa %p %.8ux %.8ux %.8ux %.8ux %.8ux %.8ux\n", a, a[0], a[1], a[2], a[3], a[4], a[5]);
+	}
+
+/*
+	a = KPTR(c->scriptpa+E_dsa_addr);
+	iprint("dsa_addr: %.8ux %.8ux %.8ux %.8ux %.8ux\n",
+		a[0], a[1], a[2], a[3], a[4]);
+	a = KPTR(c->scriptpa+E_issue_addr);
+	iprint("issue_addr: %.8ux %.8ux %.8ux %.8ux %.8ux\n",
+		a[0], a[1], a[2], a[3], a[4]);
+
+	a = KPTR(c->scriptpa+E_issue_test_begin);
+	e = KPTR(c->scriptpa+E_issue_test_end);
+	iprint("issue_test code (at offset %.8ux):\n", E_issue_test_begin);
+	
+	i = 0;
+	for(; a<e; a++){
+		iprint(" %.8ux", *a);
+		if(++i%8 == 0)
+			iprint("\n");
+	}
+	if(i%8)
+		iprint("\n");
+*/
+}
+
 static Dsa *
 dsafind(Controller *c, uchar target, uchar lun, uchar state)
 {
 	Dsa *d;
-	for (d = KPTR(legetl(c->dsalist.head)); d; d = KPTR(legetl(d->next))) {
+	for (d = KPTR(legetl(c->dsalist.head)); d != dsaend; d = KPTR(legetl(d->next))) {
 		if (d->target != 0xff && d->target != target)
 			continue;
 		if (lun != 0xff && d->lun != lun)
@@ -764,6 +822,7 @@ start(Controller *c, long entry)
 	c->running = 1;
 	p = c->scriptpa + entry;
 	lesetl(c->n->dsp, p);
+	coherence();
 	if (c->ssm)
 		c->n->dcntl |= 0x4;		/* start DMA in SSI mode */
 }
@@ -775,6 +834,7 @@ ncrcontinue(Controller *c)
 		panic(PRINTPREFIX "ncrcontinue called while running");
 	/* set the start DMA bit to continue execution */
 	c->running = 1;
+	coherence();
 	c->n->dcntl |= 0x4;
 }
 
@@ -1126,6 +1186,7 @@ sd53c8xxinterrupt(Ureg *ur, void *a)
 	int wakeme = 0;
 	int cont = -1;
 	Dsa *dsa;
+	ulong dsapa;
 	Controller *c = a;
 	Ncr *n = c->n;
 
@@ -1143,7 +1204,7 @@ sd53c8xxinterrupt(Ureg *ur, void *a)
 		}
 		n->istat = Intf;
 		/* search for structures in A_STATE_DONE */
-		for (d = KPTR(legetl(c->dsalist.head)); d; d = KPTR(legetl(d->next))) {
+		for (d = KPTR(legetl(c->dsalist.head)); d != dsaend; d = KPTR(legetl(d->next))) {
 			if (d->stateb == A_STATE_DONE) {
 				d->p9status = d->status;
 				if (DEBUG(1)) {
@@ -1168,7 +1229,25 @@ sd53c8xxinterrupt(Ureg *ur, void *a)
 
 	sist = (n->sist1<<8)|n->sist0;	/* BUG? can two-byte read be inconsistent? */
 	dstat = n->dstat;
-	dsa = (Dsa *)DMASEG_TO_KADDR(legetl(n->dsa));
+	dsapa = legetl(n->dsa);
+
+	/*
+	 * Can't compute dsa until we know that dsapa is valid.
+	 */
+	if(dsapa < -KZERO)
+		dsa = (Dsa*)DMASEG_TO_KADDR(dsapa);
+	else{
+		dsa = nil;
+		/*
+		 * happens at startup on some cards but we 
+		 * don't actually deref dsa because none of the
+		 * flags we are about are set.
+		 * still, print in case that changes and we're
+		 * about to dereference nil.
+		 */
+		iprint("sd53c8xxinterrupt: dsa=%.8lux istat=%ux sist=%ux dstat=%ux\n", dsapa, istat, sist, dstat);
+	}
+
 	c->running = 0;
 	if (istat & Sip) {
 		if (DEBUG(1)) {
@@ -1315,6 +1394,7 @@ sd53c8xxinterrupt(Ureg *ur, void *a)
 			}
 			dsa->p9status = SDtimeout;
 			dsa->stateb = A_STATE_DONE;
+			coherence();
 			softreset(c);
 			cont = E_issue_check;
 			wakeme = 1;
@@ -1336,8 +1416,7 @@ sd53c8xxinterrupt(Ureg *ur, void *a)
 			IPRINT("dstat = %.2x\n", dstat);
 		}
 		/*else*/ if (dstat & Ssi) {
-			ulong *p = DMASEG_TO_KADDR(legetl(n->dsp));
-			ulong w = (uchar *)p - (uchar *)c->script;
+			ulong w = legetl(n->dsp) - c->scriptpa;
 			IPRINT("[%lux]", w);
 			USED(w);
 			cont = -2;	/* restart */
@@ -1375,6 +1454,15 @@ sd53c8xxinterrupt(Ureg *ur, void *a)
 				dumpncrregs(c, 1);
 				wakeme = 1;
 				break;
+			case A_SIR_NOTIFY_LOAD_STATE:
+				IPRINT(PRINTPREFIX ": load_state dsa=%p\n", dsa);
+				if (dsa == (void*)KZERO || dsa == (void*)-1) {
+					dsadump(c);
+					dumpncrregs(c, 1);
+					panic("bad dsa in load_state");
+				}
+				cont = -2;
+				break;
 			case A_SIR_NOTIFY_MSG_IN:
 				IPRINT(PRINTPREFIX "%d/%d: msg_in %d\n",
 				    dsa->target, dsa->lun, n->sfbr);
@@ -1431,7 +1519,7 @@ sd53c8xxinterrupt(Ureg *ur, void *a)
 				cont = -2;
 				break;
 			case A_SIR_NOTIFY_ISSUE:
-				IPRINT(PRINTPREFIX "%d/%d: issue:", dsa->target, dsa->lun);
+				IPRINT(PRINTPREFIX "%d/%d: issue dsa=%p end=%p:", dsa->target, dsa->lun, dsa, dsaend);
 			dsadump:
 				IPRINT(" tgt=%d", dsa->target);
 				IPRINT(" time=%ld", TK2MS(m->ticks));
@@ -1447,7 +1535,7 @@ sd53c8xxinterrupt(Ureg *ur, void *a)
 				cont = -2;
 				break;
 			case A_SIR_NOTIFY_DUMP_NEXT_CODE: {
-				ulong *dsp = DMASEG_TO_KADDR(legetl(n->dsp));
+				ulong *dsp = c->script + (legetl(n->dsp)-c->scriptpa)/4;
 				int x;
 				IPRINT(PRINTPREFIX "code at %lux", dsp - c->script);
 				for (x = 0; x < 6; x++) {
@@ -1475,9 +1563,9 @@ sd53c8xxinterrupt(Ureg *ur, void *a)
 				cont = -2;
 				break;
 			case A_error_reselected:		/* dsa isn't valid here */
-				print(PRINTPREFIX "reselection error\n");
+				iprint(PRINTPREFIX "reselection error\n");
 				dumpncrregs(c, 1);
-				for (dsa = KPTR(legetl(c->dsalist.head)); dsa; dsa = KPTR(legetl(dsa->next))) {
+				for (dsa = KPTR(legetl(c->dsalist.head)); dsa != dsaend; dsa = KPTR(legetl(dsa->next))) {
 					IPRINT(PRINTPREFIX "dsa target %d lun %d state %d\n", dsa->target, dsa->lun, dsa->stateb);
 				}
 				break;
@@ -1489,15 +1577,40 @@ sd53c8xxinterrupt(Ureg *ur, void *a)
 			}
 		}
 		/*else*/ if (dstat & Iid) {
-			ulong addr = legetl(n->dsp);
-			ulong dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];
+			int i, target, lun;
+			ulong addr, dbc, *v;
+			
+			addr = legetl(n->dsp);
+			if(dsa){
+				target = dsa->target;
+				lun = dsa->lun;
+			}else{
+				target = -1;
+				lun = -1;
+			}
+			dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];
+
+		//	if(dsa == nil)
+				idebug++;
 			IPRINT(PRINTPREFIX "%d/%d: Iid pa=%.8lux sa=%.8lux dbc=%lux\n",
-			    dsa->target, dsa->lun,
+			    target, lun,
 			    addr, addr - c->scriptpa, dbc);
-			addr = (ulong)DMASEG_TO_KADDR(addr);
-			IPRINT("%.8lux %.8lux %.8lux\n",
-			    *(ulong *)(addr - 12), *(ulong *)(addr - 8), *(ulong *)(addr - 4));
+			addr = (ulong)c->script + addr - c->scriptpa;
+			addr -= 64;
+			addr &= ~63;
+			v = (ulong*)addr;
+			for(i=0; i<8; i++){
+				IPRINT("%.8lux: %.8lux %.8lux %.8lux %.8lux\n", 
+					addr, v[0], v[1], v[2], v[3]);
+				addr += 4*4;
+				v += 4;
+			}
 			USED(addr, dbc);
+			if(dsa == nil){
+				dsadump(c);
+				dumpncrregs(c, 1);
+				panic("bad dsa");
+			}
 			dsa->p9status = SDeio;
 			wakeme = 1;
 		}
@@ -1634,6 +1747,7 @@ sd53c8xxrio(SDreq* r)
 
 	if((target = r->unit->subno) == 0x07)
 		return r->status = SDtimeout;	/* assign */
+
 	c = r->unit->dev->ctlr;
 
 	check = 0;
@@ -1702,7 +1816,7 @@ docheck:
 
 	setmovedata(&d->msg_out_buf, DMASEG(d->msg_out), bc);
 	setmovedata(&d->cmd_buf, DMASEG(r->cmd), r->clen);
-	calcblockdma(d, DMASEG(r->data), r->dlen);
+	calcblockdma(d, r->data ? DMASEG(r->data) : 0, r->dlen);
 
 	if (DEBUG(0)) {
 		KPRINT(PRINTPREFIX "%d/%d: exec: ", target, r->lun);
@@ -1722,14 +1836,15 @@ docheck:
 
 	d->p9status = SDnostatus;
 	d->parityerror = 0;
-
+	coherence();
 	d->stateb = A_STATE_ISSUE;		/* start operation */
+	coherence();
 
 	ilock(c);
 	if (c->ssm)
-		c->n->dcntl |= 0x10;		/* SSI */
+		c->n->dcntl |= 0x10;		/* single step */
 	if (c->running) {
-		c->n->istat |= Sigp;
+		c->n->istat = Sigp;
 	}
 	else {
 		start(c, E_issue_check);
@@ -1802,6 +1917,7 @@ docheck:
 		 * so the Dsa can be re-used.
 		 */
 		lesetl(&d->stateb, A_STATE_ALLOCATED);
+		coherence();
 		goto docheck;
 	}
 	qunlock(&c->q[target]);
@@ -1825,12 +1941,14 @@ docheck:
 	return r->status = status;
 }
 
+#define	vpt ((ulong*)VPT)
+#define	VPTX(va)		(((ulong)(va))>>12)
 static void
 cribbios(Controller *c)
 {
 	c->bios.scntl3 = c->n->scntl3;
 	c->bios.stest2 = c->n->stest2;
-	KPRINT(PRINTPREFIX "bios scntl3(%.2x) stest2(%.2x)\n", c->bios.scntl3, c->bios.stest2);
+	print(PRINTPREFIX "bios scntl3(%.2x) stest2(%.2x)\n", c->bios.scntl3, c->bios.stest2);
 }
 
 static int
@@ -1879,8 +1997,6 @@ static Variant variant[] = {
 { SYM_1011_DID,   0xff, "SYM53C1010",	Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
 };
 
-#define offsetof(s, t) ((ulong)&((s *)0)->t)
-
 static int
 xfunc(Controller *c, enum na_external x, unsigned long *v)
 {
@@ -1968,6 +2084,7 @@ sd53c8xxpnp(void)
 	Controller *ctlr;
 	SDev *sdev, *head, *tail;
 	ulong regpa, *script, scriptpa;
+	void *regva, *scriptva;
 
 	if(cp = getconf("*maxsd53c8xx"))
 		nctlr = strtoul(cp, 0, 0);
@@ -1995,23 +2112,27 @@ sd53c8xxpnp(void)
 				continue;
 			ba++;
 		}
-		regpa = upamalloc(regpa & ~0x0F, p->mem[1].size, 0);
 		if(regpa == 0)
+			print("regpa 0\n");
+		regpa &= ~0xF;
+		regva = vmap(regpa, p->mem[1].size);
+		if(regva == 0)
 			continue;
 
 		script = nil;
 		scriptpa = 0;
+		scriptva = nil;
 		scriptma = nil;
 		if((v->feature & LocalRAM) && sizeof(na_script) <= 4096){
 			scriptpa = p->mem[ba].bar;
 			if((scriptpa & 0x04) && p->mem[ba+1].bar){
-				upafree(regpa, p->mem[1].size);
+				vunmap(regva, p->mem[1].size);
 				continue;
 			}
-			scriptpa = upamalloc(scriptpa & ~0x0F,
-					p->mem[ba].size, 0);
-			if(scriptpa)
-				script = KADDR(scriptpa);
+			scriptpa &= ~0x0F;
+			scriptva = vmap(scriptpa, p->mem[ba].size);
+			if(scriptva)
+				script = scriptva;
 		}
 		if(scriptpa == 0){
 			/*
@@ -2020,7 +2141,7 @@ sd53c8xxpnp(void)
 			 */
 			scriptma = malloc(sizeof(na_script));
 			if(scriptma == nil){
-				upafree(regpa, p->mem[1].size);
+				vunmap(regva, p->mem[1].size);
 				continue;
 			}
 			scriptpa = DMASEG(scriptma);
@@ -2037,13 +2158,23 @@ buggery:
 				free(sdev);
 			if(scriptma)
 				free(scriptma);
-			else
-				upafree(scriptpa, p->mem[ba].size);
-			upafree(regpa, p->mem[1].size);
+			else if(scriptva)
+				vunmap(scriptva, p->mem[ba].size);
+			if(regva)
+				vunmap(regva, p->mem[1].size);
 			continue;
 		}
 
-		ctlr->n = KADDR(regpa);
+		if(dsaend == nil)
+			dsaend = xalloc(sizeof *dsaend);
+		lesetl(&dsaend->stateb, A_STATE_END);
+	//	lesetl(dsaend->next, DMASEG(dsaend));
+		coherence();
+		lesetl(ctlr->dsalist.head, DMASEG(dsaend));
+		coherence();
+		ctlr->dsalist.freechain = 0;
+
+		ctlr->n = regva;
 		ctlr->v = v;
 		ctlr->script = script;
 		memmove(ctlr->script, na_script, sizeof(na_script));
@@ -2062,19 +2193,17 @@ buggery:
 		}
 		swabl(ctlr->script, ctlr->script, sizeof(na_script));
 
-		ctlr->dsalist.freechain = 0;
-		lesetl(ctlr->dsalist.head, 0);
-
 		ctlr->pcidev = p;
 
 		sdev->ifc = &sd53c8xxifc;
 		sdev->ctlr = ctlr;
+		sdev->idno = '0';
 		if(!(v->feature & Wide))
 			sdev->nunit = 8;
 		else
 			sdev->nunit = MAXTARGET;
 		ctlr->sdev = sdev;
-
+		
 		if(head != nil)
 			tail->next = sdev;
 		else
@@ -2087,12 +2216,6 @@ buggery:
 	return head;
 }
 
-static SDev*
-sd53c8xxid(SDev* sdev)
-{
-	return scsiid(sdev, &sd53c8xxifc);
-}
-
 static int
 sd53c8xxenable(SDev* sdev)
 {
@@ -2104,13 +2227,13 @@ sd53c8xxenable(SDev* sdev)
 	pcidev = ctlr->pcidev;
 
 	pcisetbme(pcidev);
-	snprint(name, sizeof(name), "%s (%s)", sdev->name, sdev->ifc->name);
-	intrenable(pcidev->intl, sd53c8xxinterrupt, ctlr, pcidev->tbdf, name);
 
 	ilock(ctlr);
 	synctabinit(ctlr);
 	cribbios(ctlr);
 	reset(ctlr);
+	snprint(name, sizeof(name), "%s (%s)", sdev->name, sdev->ifc->name);
+	intrenable(pcidev->intl, sd53c8xxinterrupt, ctlr, pcidev->tbdf, name);
 	iunlock(ctlr);
 
 	return 1;
@@ -2121,7 +2244,6 @@ SDifc sd53c8xxifc = {
 
 	sd53c8xxpnp,			/* pnp */
 	nil,				/* legacy */
-	sd53c8xxid,			/* id */
 	sd53c8xxenable,			/* enable */
 	nil,				/* disable */
 

+ 0 - 773
sys/src/9/pc/sd53c8xx.i

@@ -1,773 +0,0 @@
-unsigned long na_script[] = {
-			/*	extern	scsi_id_buf */
-			/*	extern	msg_out_buf */
-			/*	extern	cmd_buf */
-			/*	extern	data_buf */
-			/*	extern	status_buf */
-			/*	extern	msgin_buf */
-			/*	extern	dsa_0 */
-			/*	extern  dsa_1 */
-			/*	extern	dsa_head */
-			/*	extern	ssid_mask */
-			/*	SIR_MSG_IO_COMPLETE = 0 */
-			/*	error_not_cmd_complete = 1 */
-			/*	error_disconnected = 2 */
-			/*	error_reselected = 3 */
-			/*	error_unexpected_phase = 4 */
-			/*	error_weird_message = 5 */
-			/*	SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT = 6 */
-			/*	error_not_identify_after_reselect = 7 */
-			/*	error_too_much_data = 8 */
-			/*	error_too_little_data = 9 */
-			/*	SIR_MSG_REJECT = 10 */
-			/*	SIR_MSG_SDTR = 11 */
-			/*	SIR_EV_RESPONSE_OK = 12 */
-			/*	error_sigp_set = 13 */
-			/*	SIR_EV_PHASE_SWITCH_AFTER_ID = 14 */
-			/*	SIR_MSG_WDTR = 15 */
-			/*	SIR_MSG_IGNORE_WIDE_RESIDUE = 16 */
-			/*	SIR_NOTIFY_DISC = 100 */
-			/*	SIR_NOTIFY_RESELECT = 101 */
-			/*	SIR_NOTIFY_MSG_IN = 102 */
-			/*	SIR_NOTIFY_STATUS = 103 */
-			/*	SIR_NOTIFY_DUMP = 104 */
-			/*	SIR_NOTIFY_DUMP2 = 105 */
-			/*	SIR_NOTIFY_SIGP = 106 */
-			/*	SIR_NOTIFY_ISSUE = 107 */
-			/*	SIR_NOTIFY_WAIT_RESELECT = 108 */
-			/*	SIR_NOTIFY_ISSUE_CHECK = 109 */
-			/*	SIR_NOTIFY_DUMP_NEXT_CODE = 110 */
-			/*	SIR_NOTIFY_COMMAND = 111 */
-			/*	SIR_NOTIFY_DATA_IN = 112 */
-			/*	SIR_NOTIFY_DATA_OUT = 113 */
-			/*	SIR_NOTIFY_BLOCK_DATA_IN = 114 */
-			/*	SIR_NOTIFY_WSR = 115 */
-			/*	SIR_NOTIFY_LOAD_SYNC = 116 */
-			/*	SIR_NOTIFY_RESELECTED_ON_SELECT = 117 */
-			/*	STATE_FREE = 0 */
-			/*	STATE_ALLOCATED = 1 */
-			/*	STATE_ISSUE = 2 */
-			/*	STATE_DISCONNECTED = 3 */
-			/*	STATE_DONE = 4 */
-			/*	RESULT_OK = 0 */
-			/*	MSG_IDENTIFY = 0x80 */
-			/*	MSG_DISCONNECT = 0x04 */
-			/*	MSG_SAVE_DATA_POINTER = 0x02 */
-			/*	MSG_RESTORE_POINTERS = 0x03 */
-			/*	MSG_IGNORE_WIDE_RESIDUE = 0x23 */
-			/*	X_MSG = 0x01 */
-			/*	X_MSG_SDTR = 0x01 */
-			/*	X_MSG_WDTR = 0x03 */
-			/*	MSG_REJECT = 0x07 */
-			/*	BSIZE = 512 */
-/* 0000 */ 0x80880000L, /*		jump	wait_for_reselection */
-/* 0004 */ 0x00000514L,
-/* 0008 */ 0x88880000L, /*		call	load_sync */
-/* 000c */ 0x0000074cL,
-/* 0010 */ 0x60000200L, /*		clear	target */
-/* 0014 */ 0x00000000L,
-/* 0018 */ 0x47000000L, /*		select	atn from scsi_id_buf, reselected_on_select */
-/* 001c */ 0x000004ecL,
-/* 0020 */ 0x878b0000L, /*		jump	start1, when msg_in */
-/* 0024 */ 0x00000000L,
-/* 0028 */ 0x1e000000L, /*		move	from msg_out_buf, when msg_out */
-/* 002c */ 0x00000001L,
-/* 0030 */ 0x868b0000L, /*		jump	start1, when msg_out */
-/* 0034 */ 0x00fffff0L,
-/* 0038 */ 0x82830000L, /*		jump	to_decisions, when not cmd */
-/* 003c */ 0x000005f0L,
-/* 0040 */ 0x60000008L, /*		clear	atn */
-/* 0044 */ 0x00000000L,
-/* 0048 */ 0x1a000000L, /*		move	from cmd_buf, when cmd */
-/* 004c */ 0x00000002L,
-/* 0050 */ 0x81830000L, /*		jump	to_decisions, when not data_in */
-/* 0054 */ 0x000005d8L,
-/* 0058 */ 0xc0000004L, /*		move	memory 4, state, scratcha */
-/* 005c */ 0x00000678L,
-/* 0060 */ 0x00000034L,
-/* 0064 */ 0xc0000004L, /*		move	memory 4, dmaaddr, scratchb */
-/* 0068 */ 0x0000067cL,
-/* 006c */ 0x0000005cL,
-/* 0070 */ 0x72360000L, /*		move	scratcha2 to sfbr */
-/* 0074 */ 0x00000000L,
-/* 0078 */ 0x808c0000L, /*		jump	data_in_normal, if 0 */
-/* 007c */ 0x00000078L,
-/* 0080 */ 0x29000200L, /*		move	BSIZE, ptr dmaaddr, when data_in */
-/* 0084 */ 0x0000067cL,
-/* 0088 */ 0x7e5d0200L, /*		move	scratchb1 + BSIZE / 256 to scratchb1 */
-/* 008c */ 0x00000000L,
-/* 0090 */ 0x7f5e0000L, /*		move	scratchb2 + 0 to scratchb2 with carry */
-/* 0094 */ 0x00000000L,
-/* 0098 */ 0x7f5f0000L, /*		move	scratchb3 + 0 to scratchb3 with carry */
-/* 009c */ 0x00000000L,
-/* 00a0 */ 0x7e36ff00L, /*		move	scratcha2 + 255 to scratcha2 */
-/* 00a4 */ 0x00000000L,
-/* 00a8 */ 0xc0000004L, /*		move	memory 4, scratchb, dmaaddr */
-/* 00ac */ 0x0000005cL,
-/* 00b0 */ 0x0000067cL,
-/* 00b4 */ 0x818b0000L, /*		jump	data_in_block_loop, when data_in */
-/* 00b8 */ 0x00ffffb4L,
-/* 00bc */ 0xc0000004L, /*		move	memory 4, scratcha, state */
-/* 00c0 */ 0x00000034L,
-/* 00c4 */ 0x00000678L,
-/* 00c8 */ 0x88880000L, /*		call	save_state */
-/* 00cc */ 0x000005e0L,
-/* 00d0 */ 0x80880000L, /*		jump	to_decisions */
-/* 00d4 */ 0x00000558L,
-/* 00d8 */ 0xc0000004L, /*		move	memory 4, scratchb, dmaaddr */
-/* 00dc */ 0x0000005cL,
-/* 00e0 */ 0x0000067cL,
-/* 00e4 */ 0xc0000004L, /*		move	memory 4, scratcha, state */
-/* 00e8 */ 0x00000034L,
-/* 00ec */ 0x00000678L,
-/* 00f0 */ 0x80880000L, /*		jump	to_decisions */
-/* 00f4 */ 0x00000538L,
-/* 00f8 */ 0x72370000L, /*		move	scratcha3 to sfbr */
-/* 00fc */ 0x00000000L,
-/* 0100 */ 0x98040000L, /*		int	error_too_much_data, if not 0 */
-/* 0104 */ 0x00000008L,
-/* 0108 */ 0x19000000L, /*		move	from data_buf, when data_in */
-/* 010c */ 0x00000003L,
-/* 0110 */ 0x78370200L, /*		move	2 to scratcha3 */
-/* 0114 */ 0x00000000L,
-/* 0118 */ 0xc0000004L, /*		move	memory 4, scratcha, state */
-/* 011c */ 0x00000034L,
-/* 0120 */ 0x00000678L,
-/* 0124 */ 0x88880000L, /*		call	save_state */
-/* 0128 */ 0x00000584L,
-/* 012c */ 0x80880000L, /*		jump	post_data_to_decisions */
-/* 0130 */ 0x0000052cL,
-/* 0134 */ 0xc0000004L, /*		move	memory 4, state, scratcha */
-/* 0138 */ 0x00000678L,
-/* 013c */ 0x00000034L,
-/* 0140 */ 0xc0000004L, /*		move	memory 4, dmaaddr, scratchb */
-/* 0144 */ 0x0000067cL,
-/* 0148 */ 0x0000005cL,
-/* 014c */ 0x72360000L, /*		move	scratcha2 to sfbr */
-/* 0150 */ 0x00000000L,
-/* 0154 */ 0x808c0000L, /*		jump	data_out_normal, if 0 */
-/* 0158 */ 0x0000005cL,
-/* 015c */ 0xc0000004L, /*		move	memory 4, dmaaddr, scratchb */
-/* 0160 */ 0x0000067cL,
-/* 0164 */ 0x0000005cL,
-/* 0168 */ 0x28000200L, /*		move	BSIZE, ptr dmaaddr, when data_out */
-/* 016c */ 0x0000067cL,
-/* 0170 */ 0x7e5d0200L, /*		move	scratchb1 + BSIZE / 256 to scratchb1 */
-/* 0174 */ 0x00000000L,
-/* 0178 */ 0x7f5e0000L, /*		move	scratchb2 + 0 to scratchb2 with carry */
-/* 017c */ 0x00000000L,
-/* 0180 */ 0x7f5f0000L, /*		move	scratchb3 + 0 to scratchb3 with carry */
-/* 0184 */ 0x00000000L,
-/* 0188 */ 0x7e36ff00L, /*		move	scratcha2 + 255 to scratcha2 */
-/* 018c */ 0x00000000L,
-/* 0190 */ 0xc0000004L, /*		move	memory 4, scratchb, dmaaddr */
-/* 0194 */ 0x0000005cL,
-/* 0198 */ 0x0000067cL,
-/* 019c */ 0x808b0000L, /*		jump	data_out_block_loop, when data_out */
-/* 01a0 */ 0x00ffffa8L,
-/* 01a4 */ 0xc0000004L, /*		move	memory 4, scratcha, state */
-/* 01a8 */ 0x00000034L,
-/* 01ac */ 0x00000678L,
-/* 01b0 */ 0x80880000L, /*		jump	to_decisions */
-/* 01b4 */ 0x00000478L,
-/* 01b8 */ 0x72370000L, /*		move	scratcha3 to sfbr */
-/* 01bc */ 0x00000000L,
-/* 01c0 */ 0x98040000L, /*		int	error_too_little_data, if not 0 */
-/* 01c4 */ 0x00000009L,
-/* 01c8 */ 0x18000000L, /*		move	from data_buf, when data_out */
-/* 01cc */ 0x00000003L,
-/* 01d0 */ 0x78370200L, /*		move	2 to scratcha3 */
-/* 01d4 */ 0x00000000L,
-/* 01d8 */ 0xc0000004L, /*		move	memory 4, scratcha, state */
-/* 01dc */ 0x00000034L,
-/* 01e0 */ 0x00000678L,
-/* 01e4 */ 0x88880000L, /*		call	save_state */
-/* 01e8 */ 0x000004c4L,
-/* 01ec */ 0x80880000L, /*		jump	post_data_to_decisions */
-/* 01f0 */ 0x0000046cL,
-/* 01f4 */ 0x1b000000L, /*		move	from status_buf, when status */
-/* 01f8 */ 0x00000004L,
-/* 01fc */ 0x9f030000L, /*		int	error_unexpected_phase, when not msg_in */
-/* 0200 */ 0x00000004L,
-/* 0204 */ 0x0f000001L, /*		move	1, scratcha, when msg_in */
-/* 0208 */ 0x00000034L,
-/* 020c */ 0x808c0007L, /*		jump	rejected, if MSG_REJECT */
-/* 0210 */ 0x00000088L,
-/* 0214 */ 0x808c0004L, /*		jump	disconnected, if MSG_DISCONNECT */
-/* 0218 */ 0x00000298L,
-/* 021c */ 0x808c0002L, /*		jump	msg_in_skip, if MSG_SAVE_DATA_POINTER */
-/* 0220 */ 0x00000090L,
-/* 0224 */ 0x808c0003L, /*		jump	msg_in_skip, if MSG_RESTORE_POINTERS */
-/* 0228 */ 0x00000088L,
-/* 022c */ 0x808c0023L, /*		jump	ignore_wide, if MSG_IGNORE_WIDE_RESIDUE */
-/* 0230 */ 0x000001f0L,
-/* 0234 */ 0x808c0001L, /*		jump	extended, if X_MSG */
-/* 0238 */ 0x00000088L,
-/* 023c */ 0x98040000L, /*		int	error_not_cmd_complete, if not 0 */
-/* 0240 */ 0x00000001L,
-/* 0244 */ 0x7c027e00L, /*		move	scntl2&0x7e to scntl2 */
-/* 0248 */ 0x00000000L,
-/* 024c */ 0x60000040L, /*		clear	ack */
-/* 0250 */ 0x00000000L,
-/* 0254 */ 0x48000000L, /*		wait	disconnect */
-/* 0258 */ 0x00000000L,
-/* 025c */ 0xc0000004L, /*		move	memory 4, state, scratcha */
-/* 0260 */ 0x00000678L,
-/* 0264 */ 0x00000034L,
-/* 0268 */ 0x78340400L, /*		move	STATE_DONE to scratcha0 */
-/* 026c */ 0x00000000L,
-/* 0270 */ 0x78350000L, /*		move	RESULT_OK to scratcha1 */
-/* 0274 */ 0x00000000L,
-/* 0278 */ 0xc0000004L, /*		move	memory 4, scratcha, state */
-/* 027c */ 0x00000034L,
-/* 0280 */ 0x00000678L,
-/* 0284 */ 0x88880000L, /*		call	save_state */
-/* 0288 */ 0x00000424L,
-/* 028c */ 0x98180000L, /*		intfly	0 */
-/* 0290 */ 0x00000000L,
-/* 0294 */ 0x80880000L, /*		jump	issue_check */
-/* 0298 */ 0x0000043cL,
-/* 029c */ 0x98080000L, /*		int	SIR_MSG_REJECT */
-/* 02a0 */ 0x0000000aL,
-/* 02a4 */ 0x60000040L, /*		clear	ack */
-/* 02a8 */ 0x00000000L,
-/* 02ac */ 0x80880000L, /*		jump	to_decisions */
-/* 02b0 */ 0x0000037cL,
-/* 02b4 */ 0x60000040L, /*		clear	ack */
-/* 02b8 */ 0x00000000L,
-/* 02bc */ 0x80880000L, /*		jump	to_decisions */
-/* 02c0 */ 0x0000036cL,
-/* 02c4 */ 0x60000040L, /*		clear	ack */
-/* 02c8 */ 0x00000000L,
-/* 02cc */ 0x9f030000L, /*		int	error_unexpected_phase, when not msg_in */
-/* 02d0 */ 0x00000004L,
-/* 02d4 */ 0x0f000001L, /*		move	1, scratcha1, when msg_in */
-/* 02d8 */ 0x00000035L,
-/* 02dc */ 0x808c0003L, /*		jump	ext_3, if 3 */
-/* 02e0 */ 0x00000030L,
-/* 02e4 */ 0x808c0002L, /*		jump	ext_2, if 2 */
-/* 02e8 */ 0x00000098L,
-/* 02ec */ 0x98040001L, /*		int	error_weird_message, if not 1 */
-/* 02f0 */ 0x00000005L,
-/* 02f4 */ 0x60000040L, /*		clear	ack */
-/* 02f8 */ 0x00000000L,
-/* 02fc */ 0x9f030000L, /*		int	error_unexpected_phase, when not msg_in */
-/* 0300 */ 0x00000004L,
-/* 0304 */ 0x0f000001L, /*		move	1, scratcha1, when msg_in */
-/* 0308 */ 0x00000035L,
-/* 030c */ 0x80880000L, /*		jump	ext_done */
-/* 0310 */ 0x000000c8L,
-/* 0314 */ 0x60000040L, /*	ext_3:	clear	ack */
-/* 0318 */ 0x00000000L,
-/* 031c */ 0x9f030000L, /*		int	error_unexpected_phase, when not msg_in */
-/* 0320 */ 0x00000004L,
-/* 0324 */ 0x0f000001L, /*		move	1, scratcha1, when msg_in */
-/* 0328 */ 0x00000035L,
-/* 032c */ 0x60000040L, /*		clear	ack */
-/* 0330 */ 0x00000000L,
-/* 0334 */ 0x9f030000L, /*		int	error_unexpected_phase, when not msg_in */
-/* 0338 */ 0x00000004L,
-/* 033c */ 0x0f000001L, /*		move	1, scratcha2, when msg_in */
-/* 0340 */ 0x00000036L,
-/* 0344 */ 0x60000040L, /*		clear	ack */
-/* 0348 */ 0x00000000L,
-/* 034c */ 0x9f030000L, /*		int	error_unexpected_phase, when not msg_in */
-/* 0350 */ 0x00000004L,
-/* 0354 */ 0x0f000001L, /*		move	1, scratcha3, when msg_in */
-/* 0358 */ 0x00000037L,
-/* 035c */ 0x72350000L, /*		move	scratcha1 to sfbr */
-/* 0360 */ 0x00000000L,
-/* 0364 */ 0x80840001L, /*		jump	ext_done, if not X_MSG_SDTR */
-/* 0368 */ 0x00000070L,
-/* 036c */ 0x98080000L, /*	sdtr:	int	SIR_MSG_SDTR */
-/* 0370 */ 0x0000000bL,
-/* 0374 */ 0x60000040L, /*		clear	ack */
-/* 0378 */ 0x00000000L,
-/* 037c */ 0x80880000L, /*		jump	to_decisions */
-/* 0380 */ 0x000002acL,
-/* 0384 */ 0x60000040L, /*	ext_2:	clear	ack */
-/* 0388 */ 0x00000000L,
-/* 038c */ 0x9f030000L, /*		int	error_unexpected_phase, when not msg_in */
-/* 0390 */ 0x00000004L,
-/* 0394 */ 0x0f000001L, /*		move	1, scratcha1, when msg_in */
-/* 0398 */ 0x00000035L,
-/* 039c */ 0x60000040L, /*		clear	ack */
-/* 03a0 */ 0x00000000L,
-/* 03a4 */ 0x9f030000L, /*		int	error_unexpected_phase, when not msg_in */
-/* 03a8 */ 0x00000004L,
-/* 03ac */ 0x0f000001L, /*		move	1, scratcha2, when msg_in */
-/* 03b0 */ 0x00000036L,
-/* 03b4 */ 0x72350000L, /*		move	scratcha1 to sfbr */
-/* 03b8 */ 0x00000000L,
-/* 03bc */ 0x80840003L, /*		jump	ext_done, if not X_MSG_WDTR */
-/* 03c0 */ 0x00000018L,
-/* 03c4 */ 0x98080000L, /*	wdtr:	int	SIR_MSG_WDTR */
-/* 03c8 */ 0x0000000fL,
-/* 03cc */ 0x60000040L, /*		clear	ack */
-/* 03d0 */ 0x00000000L,
-/* 03d4 */ 0x80880000L, /*		jump	to_decisions */
-/* 03d8 */ 0x00000254L,
-/* 03dc */ 0x58000008L, /*		set	atn */
-/* 03e0 */ 0x00000000L,
-/* 03e4 */ 0x60000040L, /*		clear	ack */
-/* 03e8 */ 0x00000000L,
-/* 03ec */ 0x78340700L, /*		move	MSG_REJECT to scratcha */
-/* 03f0 */ 0x00000000L,
-/* 03f4 */ 0x9e030000L, /*		int	error_unexpected_phase, when not msg_out */
-/* 03f8 */ 0x00000004L,
-/* 03fc */ 0x60000008L, /*		clear	atn */
-/* 0400 */ 0x00000000L,
-/* 0404 */ 0x0e000001L, /*		move	1, scratcha, when msg_out */
-/* 0408 */ 0x00000034L,
-/* 040c */ 0x60000040L, /*		clear	ack */
-/* 0410 */ 0x00000000L,
-/* 0414 */ 0x868b0000L, /*		jump	reject, when msg_out */
-/* 0418 */ 0x00ffffc0L,
-/* 041c */ 0x80880000L, /*		jump	to_decisions */
-/* 0420 */ 0x0000020cL,
-/* 0424 */ 0x60000040L, /*		clear	ack */
-/* 0428 */ 0x00000000L,
-/* 042c */ 0x9f030000L, /*		int	error_unexpected_phase, when not msg_in */
-/* 0430 */ 0x00000004L,
-/* 0434 */ 0x0f000001L, /*		move	1, scratcha1, when msg_in */
-/* 0438 */ 0x00000035L,
-/* 043c */ 0x98080000L, /*		int	SIR_MSG_IGNORE_WIDE_RESIDUE */
-/* 0440 */ 0x00000010L,
-/* 0444 */ 0x60000040L, /*		clear	ack */
-/* 0448 */ 0x00000000L,
-/* 044c */ 0x80880000L, /*		jump	to_decisions */
-/* 0450 */ 0x000001dcL,
-/* 0454 */ 0x58000008L, /*		set	atn */
-/* 0458 */ 0x00000000L,
-/* 045c */ 0x60000040L, /*		clear	ack */
-/* 0460 */ 0x00000000L,
-/* 0464 */ 0x9e030000L, /*		int	error_unexpected_phase, when not msg_out */
-/* 0468 */ 0x00000004L,
-/* 046c */ 0x1e000000L, /*		move	from msg_out_buf, when msg_out */
-/* 0470 */ 0x00000001L,
-/* 0474 */ 0x868b0000L, /*		jump	response_repeat, when msg_out */
-/* 0478 */ 0x00fffff0L,
-/* 047c */ 0x878b0000L, /*		jump	response_msg_in, when msg_in */
-/* 0480 */ 0x00000010L,
-/* 0484 */ 0x98080000L, /*		int	SIR_EV_RESPONSE_OK */
-/* 0488 */ 0x0000000cL,
-/* 048c */ 0x80880000L, /*		jump	to_decisions */
-/* 0490 */ 0x0000019cL,
-/* 0494 */ 0x0f000001L, /*		move	1, scratcha, when msg_in */
-/* 0498 */ 0x00000034L,
-/* 049c */ 0x808c0007L, /*		jump	rejected, if MSG_REJECT */
-/* 04a0 */ 0x00fffdf8L,
-/* 04a4 */ 0x98080000L, /*		int	SIR_EV_RESPONSE_OK */
-/* 04a8 */ 0x0000000cL,
-/* 04ac */ 0x80880000L, /*		jump	msg_in_not_reject */
-/* 04b0 */ 0x00fffd60L,
-/* 04b4 */ 0x7c027e00L, /*		move	scntl2&0x7e to scntl2 */
-/* 04b8 */ 0x00000000L,
-/* 04bc */ 0x60000040L, /*		clear 	ack */
-/* 04c0 */ 0x00000000L,
-/* 04c4 */ 0x48000000L, /*		wait	disconnect */
-/* 04c8 */ 0x00000000L,
-/* 04cc */ 0xc0000004L, /*		move	memory 4, state, scratcha */
-/* 04d0 */ 0x00000678L,
-/* 04d4 */ 0x00000034L,
-/* 04d8 */ 0x78340300L, /*		move	STATE_DISCONNECTED to scratcha0 */
-/* 04dc */ 0x00000000L,
-/* 04e0 */ 0xc0000004L, /*		move	memory 4, scratcha, state */
-/* 04e4 */ 0x00000034L,
-/* 04e8 */ 0x00000678L,
-/* 04ec */ 0x88880000L, /*		call	save_state */
-/* 04f0 */ 0x000001bcL,
-/* 04f4 */ 0x74020100L, /*		move	scntl2&0x01 to sfbr */
-/* 04f8 */ 0x00000000L,
-/* 04fc */ 0x98040000L, /*		int	SIR_NOTIFY_WSR, if not 0 */
-/* 0500 */ 0x00000073L,
-/* 0504 */ 0x80880000L, /*		jump	issue_check */
-/* 0508 */ 0x000001ccL,
-/* 050c */ 0x98080000L, /*		int	SIR_NOTIFY_RESELECTED_ON_SELECT */
-/* 0510 */ 0x00000075L,
-/* 0514 */ 0x80880000L, /*		jump	reselected */
-/* 0518 */ 0x00000008L,
-/* 051c */ 0x54000000L, /*		wait reselect sigp_set */
-/* 0520 */ 0x000001acL,
-/* 0524 */ 0x60000200L, /*		clear	target */
-/* 0528 */ 0x00000000L,
-/* 052c */ 0x9f030000L, /*		int	SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT, when not msg_in */
-/* 0530 */ 0x00000006L,
-/* 0534 */ 0x0f000001L, /*		move	1, scratchb, when msg_in */
-/* 0538 */ 0x0000005cL,
-/* 053c */ 0x98041f80L, /*		int	error_not_identify_after_reselect, if not MSG_IDENTIFY and mask 0x1f */
-/* 0540 */ 0x00000007L,
-/* 0544 */ 0xc0000004L, /*	 	move	memory 4, dsa_head, dsa */
-/* 0548 */ 0x00000008L,
-/* 054c */ 0x00000010L,
-/* 0550 */ 0x72100000L, /*		move	dsa0 to sfbr */
-/* 0554 */ 0x00000000L,
-/* 0558 */ 0x80840000L, /*		jump	find_dsa_1, if not 0 */
-/* 055c */ 0x00000030L,
-/* 0560 */ 0x72110000L, /*		move	dsa1 to sfbr */
-/* 0564 */ 0x00000000L,
-/* 0568 */ 0x80840000L, /*		jump	find_dsa_1, if not 0 */
-/* 056c */ 0x00000020L,
-/* 0570 */ 0x72120000L, /*		move	dsa2 to sfbr */
-/* 0574 */ 0x00000000L,
-/* 0578 */ 0x80840000L, /*		jump	find_dsa_1, if not 0 */
-/* 057c */ 0x00000010L,
-/* 0580 */ 0x72130000L, /*		move	dsa3 to sfbr */
-/* 0584 */ 0x00000000L,
-/* 0588 */ 0x980c0000L, /*		int	error_reselected, if 0 */
-/* 058c */ 0x00000003L,
-/* 0590 */ 0x88880000L, /*		call	load_state */
-/* 0594 */ 0x000000f8L,
-/* 0598 */ 0xc0000004L, /*		move	memory 4, state, scratcha */
-/* 059c */ 0x00000678L,
-/* 05a0 */ 0x00000034L,
-/* 05a4 */ 0x72340000L, /*		move	scratcha0 to sfbr */
-/* 05a8 */ 0x00000000L,
-/* 05ac */ 0x80840003L, /*		jump	find_dsa_next, if not STATE_DISCONNECTED */
-/* 05b0 */ 0x00000038L,
-/* 05b4 */ 0x740a0900L, /*		move	ssid & ssid_mask to sfbr */
-/* 05b8 */ 0x00000000L,
-/* 05bc */ 0xc0000001L, /*		move	memory 1, targ, find_dsa_smc1 */
-/* 05c0 */ 0x00000680L,
-/* 05c4 */ 0x000005c8L,
-/* 05c8 */ 0x808400ffL, /*		jump	find_dsa_next, if not 255 */
-/* 05cc */ 0x0000001cL,
-/* 05d0 */ 0xc0000001L, /*		move	memory 1, lun, find_dsa_smc2 */
-/* 05d4 */ 0x00000684L,
-/* 05d8 */ 0x000005e4L,
-/* 05dc */ 0x725c0000L, /*		move	scratchb0 to sfbr */
-/* 05e0 */ 0x00000000L,
-/* 05e4 */ 0x808cf8ffL, /*		jump	reload_sync, if 255 and mask ~7 */
-/* 05e8 */ 0x00000034L,
-/* 05ec */ 0xc0000004L, /*		move	memory 4, next, dsa */
-/* 05f0 */ 0x0000068cL,
-/* 05f4 */ 0x00000010L,
-/* 05f8 */ 0x80880000L, /*		jump	find_dsa_loop */
-/* 05fc */ 0x00ffff50L,
-/* 0600 */ 0x60000008L, /*		clear	atn */
-/* 0604 */ 0x00000000L,
-/* 0608 */ 0x878b0000L, /*	        jump    msg_in_phase, when msg_in */
-/* 060c */ 0x00fffbf4L,
-/* 0610 */ 0x98080000L, /*	        int     SIR_MSG_REJECT */
-/* 0614 */ 0x0000000aL,
-/* 0618 */ 0x80880000L, /*	        jump    to_decisions */
-/* 061c */ 0x00000010L,
-/* 0620 */ 0x88880000L, /*		call	load_sync */
-/* 0624 */ 0x00000134L,
-/* 0628 */ 0x60000040L, /*		clear	ack */
-/* 062c */ 0x00000000L,
-/* 0630 */ 0x818b0000L, /*		jump	data_in_phase, when data_in */
-/* 0634 */ 0x00fffa20L,
-/* 0638 */ 0x828a0000L, /*		jump	cmd_phase, if cmd */
-/* 063c */ 0x00fffa00L,
-/* 0640 */ 0x808a0000L, /*		jump	data_out_phase, if data_out */
-/* 0644 */ 0x00fffaecL,
-/* 0648 */ 0x838a0000L, /*		jump	status_phase, if status */
-/* 064c */ 0x00fffba4L,
-/* 0650 */ 0x878a0000L, /*		jump	msg_in_phase, if msg_in */
-/* 0654 */ 0x00fffbacL,
-/* 0658 */ 0x98080000L, /*		int	error_unexpected_phase */
-/* 065c */ 0x00000004L,
-/* 0660 */ 0x838b0000L, /*		jump	status_phase, when status */
-/* 0664 */ 0x00fffb8cL,
-/* 0668 */ 0x878a0000L, /*		jump	msg_in_phase, if msg_in */
-/* 066c */ 0x00fffb94L,
-/* 0670 */ 0x98080000L, /*		int	error_unexpected_phase */
-/* 0674 */ 0x00000004L,
-/* 0678 */ 0x00000000L, /*	state:	defw	0 */
-/* 067c */ 0x00000000L, /*	dmaaddr: defw	0 */
-/* 0680 */ 0x00000000L, /*	targ:	defw	0 */
-/* 0684 */ 0x00000000L, /*	lun:	defw	0 */
-/* 0688 */ 0x00000000L, /*	sync:	defw	0 */
-/* 068c */ 0x00000000L, /*	next:	defw	0 */
-			/*	dsa_load_len = dsa_load_end - dsa_copy */
-			/*	dsa_save_len = dsa_save_end - dsa_copy */
-/* 0690 */ 0xc0000004L, /*		move	memory 4, dsa, load_state_smc0 + 4 */
-/* 0694 */ 0x00000010L,
-/* 0698 */ 0x000006a0L,
-/* 069c */ 0xc0000018L, /*		move	memory dsa_load_len, 0, dsa_copy */
-/* 06a0 */ 0x00000000L,
-/* 06a4 */ 0x00000678L,
-/* 06a8 */ 0x90080000L, /*		return */
-/* 06ac */ 0x00000000L,
-/* 06b0 */ 0xc0000004L, /*		move	memory 4, dsa, save_state_smc0 + 8 */
-/* 06b4 */ 0x00000010L,
-/* 06b8 */ 0x000006c4L,
-/* 06bc */ 0xc0000008L, /*		move	memory dsa_save_len, dsa_copy, 0 */
-/* 06c0 */ 0x00000678L,
-/* 06c4 */ 0x00000000L,
-/* 06c8 */ 0x90080000L, /*		return */
-/* 06cc */ 0x00000000L,
-/* 06d0 */ 0x721a0000L, /*		move	ctest2 to sfbr */
-/* 06d4 */ 0x00000000L,
-/* 06d8 */ 0xc0000004L, /*		move	memory 4, dsa_head, dsa */
-/* 06dc */ 0x00000008L,
-/* 06e0 */ 0x00000010L,
-/* 06e4 */ 0x72100000L, /*		move	dsa0 to sfbr */
-/* 06e8 */ 0x00000000L,
-/* 06ec */ 0x80840000L, /*		jump	issue_check_1, if not 0 */
-/* 06f0 */ 0x00000030L,
-/* 06f4 */ 0x72110000L, /*		move	dsa1 to sfbr */
-/* 06f8 */ 0x00000000L,
-/* 06fc */ 0x80840000L, /*		jump	issue_check_1, if not 0 */
-/* 0700 */ 0x00000020L,
-/* 0704 */ 0x72120000L, /*		move	dsa2 to sfbr */
-/* 0708 */ 0x00000000L,
-/* 070c */ 0x80840000L, /*		jump	issue_check_1, if not 0 */
-/* 0710 */ 0x00000010L,
-/* 0714 */ 0x72130000L, /*		move	dsa3 to sfbr */
-/* 0718 */ 0x00000000L,
-/* 071c */ 0x808c0000L, /*		jump	wait_for_reselection, if 0 */
-/* 0720 */ 0x00fffdf8L,
-/* 0724 */ 0x88880000L, /*	 	call	load_state */
-/* 0728 */ 0x00ffff64L,
-/* 072c */ 0xc0000004L, /*		move	memory 4, state, scratcha */
-/* 0730 */ 0x00000678L,
-/* 0734 */ 0x00000034L,
-/* 0738 */ 0x72340000L, /*		move	scratcha0 to sfbr */
-/* 073c */ 0x00000000L,
-/* 0740 */ 0x808c0002L, /*		jump	start, if STATE_ISSUE */
-/* 0744 */ 0x00fff8c0L,
-/* 0748 */ 0xc0000004L, /*		move	memory 4, next, dsa */
-/* 074c */ 0x0000068cL,
-/* 0750 */ 0x00000010L,
-/* 0754 */ 0x80880000L, /*		jump	issue_check_loop */
-/* 0758 */ 0x00ffff88L,
-/* 075c */ 0xc0000004L, /*		move	memory 4, sync, scratcha */
-/* 0760 */ 0x00000688L,
-/* 0764 */ 0x00000034L,
-/* 0768 */ 0x72340000L, /*		move	scratcha0 to sfbr */
-/* 076c */ 0x00000000L,
-/* 0770 */ 0x6a030000L, /*		move	sfbr to scntl3 */
-/* 0774 */ 0x00000000L,
-/* 0778 */ 0x72350000L, /*		move	scratcha1 to sfbr */
-/* 077c */ 0x00000000L,
-/* 0780 */ 0x6a050000L, /*		move	sfbr to sxfer */
-/* 0784 */ 0x00000000L,
-/* 0788 */ 0x90080000L, /*		return */
-/* 078c */ 0x00000000L,
-};
-
-#define NA_SCRIPT_SIZE 484
-
-struct na_patch na_patches[] = {
-	{ 0x0006, 5 }, /* 00000018 */
-	{ 0x000b, 4 }, /* 0000002c */
-	{ 0x0013, 4 }, /* 0000004c */
-	{ 0x0017, 1 }, /* 0000005c */
-	{ 0x0018, 2 }, /* 00000060 */
-	{ 0x001a, 1 }, /* 00000068 */
-	{ 0x001b, 2 }, /* 0000006c */
-	{ 0x0021, 1 }, /* 00000084 */
-	{ 0x002b, 2 }, /* 000000ac */
-	{ 0x002c, 1 }, /* 000000b0 */
-	{ 0x0030, 2 }, /* 000000c0 */
-	{ 0x0031, 1 }, /* 000000c4 */
-	{ 0x0037, 2 }, /* 000000dc */
-	{ 0x0038, 1 }, /* 000000e0 */
-	{ 0x003a, 2 }, /* 000000e8 */
-	{ 0x003b, 1 }, /* 000000ec */
-	{ 0x0043, 4 }, /* 0000010c */
-	{ 0x0047, 2 }, /* 0000011c */
-	{ 0x0048, 1 }, /* 00000120 */
-	{ 0x004e, 1 }, /* 00000138 */
-	{ 0x004f, 2 }, /* 0000013c */
-	{ 0x0051, 1 }, /* 00000144 */
-	{ 0x0052, 2 }, /* 00000148 */
-	{ 0x0058, 1 }, /* 00000160 */
-	{ 0x0059, 2 }, /* 00000164 */
-	{ 0x005b, 1 }, /* 0000016c */
-	{ 0x0065, 2 }, /* 00000194 */
-	{ 0x0066, 1 }, /* 00000198 */
-	{ 0x006a, 2 }, /* 000001a8 */
-	{ 0x006b, 1 }, /* 000001ac */
-	{ 0x0073, 4 }, /* 000001cc */
-	{ 0x0077, 2 }, /* 000001dc */
-	{ 0x0078, 1 }, /* 000001e0 */
-	{ 0x007e, 4 }, /* 000001f8 */
-	{ 0x0082, 2 }, /* 00000208 */
-	{ 0x0098, 1 }, /* 00000260 */
-	{ 0x0099, 2 }, /* 00000264 */
-	{ 0x009f, 2 }, /* 0000027c */
-	{ 0x00a0, 1 }, /* 00000280 */
-	{ 0x00b6, 2 }, /* 000002d8 */
-	{ 0x00c2, 2 }, /* 00000308 */
-	{ 0x00ca, 2 }, /* 00000328 */
-	{ 0x00d0, 2 }, /* 00000340 */
-	{ 0x00d6, 2 }, /* 00000358 */
-	{ 0x00e6, 2 }, /* 00000398 */
-	{ 0x00ec, 2 }, /* 000003b0 */
-	{ 0x0102, 2 }, /* 00000408 */
-	{ 0x010e, 2 }, /* 00000438 */
-	{ 0x011c, 4 }, /* 00000470 */
-	{ 0x0126, 2 }, /* 00000498 */
-	{ 0x0134, 1 }, /* 000004d0 */
-	{ 0x0135, 2 }, /* 000004d4 */
-	{ 0x0139, 2 }, /* 000004e4 */
-	{ 0x013a, 1 }, /* 000004e8 */
-	{ 0x014e, 2 }, /* 00000538 */
-	{ 0x0152, 4 }, /* 00000548 */
-	{ 0x0153, 2 }, /* 0000054c */
-	{ 0x0167, 1 }, /* 0000059c */
-	{ 0x0168, 2 }, /* 000005a0 */
-	{ 0x016d, 3 }, /* 000005b4 */
-	{ 0x0170, 1 }, /* 000005c0 */
-	{ 0x0171, 1 }, /* 000005c4 */
-	{ 0x0175, 1 }, /* 000005d4 */
-	{ 0x0176, 1 }, /* 000005d8 */
-	{ 0x017c, 1 }, /* 000005f0 */
-	{ 0x017d, 2 }, /* 000005f4 */
-	{ 0x01a5, 2 }, /* 00000694 */
-	{ 0x01a6, 1 }, /* 00000698 */
-	{ 0x01a9, 1 }, /* 000006a4 */
-	{ 0x01ad, 2 }, /* 000006b4 */
-	{ 0x01ae, 1 }, /* 000006b8 */
-	{ 0x01b0, 1 }, /* 000006c0 */
-	{ 0x01b7, 4 }, /* 000006dc */
-	{ 0x01b8, 2 }, /* 000006e0 */
-	{ 0x01cc, 1 }, /* 00000730 */
-	{ 0x01cd, 2 }, /* 00000734 */
-	{ 0x01d3, 1 }, /* 0000074c */
-	{ 0x01d4, 2 }, /* 00000750 */
-	{ 0x01d8, 1 }, /* 00000760 */
-	{ 0x01d9, 2 }, /* 00000764 */
-};
-#define NA_PATCHES 80
-
-enum na_external {
-	X_scsi_id_buf,
-	X_msg_out_buf,
-	X_cmd_buf,
-	X_data_buf,
-	X_status_buf,
-	X_msgin_buf,
-	X_dsa_0,
-	X_dsa_1,
-	X_dsa_head,
-	X_ssid_mask,
-};
-
-enum {
-	E_issue_check_next = 1864,
-	E_issue_check_1 = 1828,
-	E_issue_check_loop = 1764,
-	E_save_state_smc0 = 1724,
-	E_load_state_smc0 = 1692,
-	E_dsa_load_end = 1680,
-	E_sync = 1672,
-	E_dsa_save_end = 1664,
-	E_dsa_copy = 1656,
-	E_id_out_mismatch_recover = 1536,
-	E_next = 1676,
-	E_reload_sync = 1568,
-	E_find_dsa_smc2 = 1508,
-	E_lun = 1668,
-	E_find_dsa_smc1 = 1480,
-	E_targ = 1664,
-	E_find_dsa_next = 1516,
-	E_load_state = 1680,
-	E_find_dsa_1 = 1424,
-	E_find_dsa_loop = 1360,
-	E_find_dsa = 1348,
-	E_sigp_set = 1744,
-	E_reselected = 1316,
-	E_wsr_check = 1268,
-	E_response_msg_in = 1172,
-	E_response_repeat = 1132,
-	E_response = 1108,
-	E_reject = 988,
-	E_wdtr = 964,
-	E_sdtr = 876,
-	E_ext_done = 988,
-	E_ext_1 = 756,
-	E_ext_2 = 900,
-	E_ext_3 = 788,
-	E_issue_check = 1752,
-	E_extended = 708,
-	E_ignore_wide = 1060,
-	E_msg_in_skip = 692,
-	E_disconnected = 1204,
-	E_msg_in_not_reject = 532,
-	E_rejected = 668,
-	E_msg_in_phase = 516,
-	E_status_phase = 500,
-	E_data_out_mismatch = 464,
-	E_data_out_block_mismatch = 368,
-	E_data_out_normal = 440,
-	E_data_out_block_loop = 332,
-	E_data_out_phase = 308,
-	E_post_data_to_decisions = 1632,
-	E_data_in_mismatch = 272,
-	E_data_mismatch_recover = 228,
-	E_data_block_mismatch_recover = 216,
-	E_save_state = 1712,
-	E_data_in_block_mismatch = 136,
-	E_data_in_normal = 248,
-	E_data_in_block_loop = 112,
-	E_dmaaddr = 1660,
-	E_state = 1656,
-	E_data_in_phase = 88,
-	E_cmd_out_mismatch = 80,
-	E_cmd_phase = 64,
-	E_to_decisions = 1584,
-	E_id_out_mismatch = 48,
-	E_start1 = 40,
-	E_reselected_on_select = 1292,
-	E_load_sync = 1884,
-	E_start = 8,
-	E_wait_for_reselection = 1308,
-	E_idle = 0,
-};
-#define A_dsa_save_len 8
-#define A_dsa_load_len 24
-#define A_BSIZE 512
-#define A_MSG_REJECT 7
-#define A_X_MSG_WDTR 3
-#define A_X_MSG_SDTR 1
-#define A_X_MSG 1
-#define A_MSG_IGNORE_WIDE_RESIDUE 35
-#define A_MSG_RESTORE_POINTERS 3
-#define A_MSG_SAVE_DATA_POINTER 2
-#define A_MSG_DISCONNECT 4
-#define A_MSG_IDENTIFY 128
-#define A_RESULT_OK 0
-#define A_STATE_DONE 4
-#define A_STATE_DISCONNECTED 3
-#define A_STATE_ISSUE 2
-#define A_STATE_ALLOCATED 1
-#define A_STATE_FREE 0
-#define A_SIR_NOTIFY_RESELECTED_ON_SELECT 117
-#define A_SIR_NOTIFY_LOAD_SYNC 116
-#define A_SIR_NOTIFY_WSR 115
-#define A_SIR_NOTIFY_BLOCK_DATA_IN 114
-#define A_SIR_NOTIFY_DATA_OUT 113
-#define A_SIR_NOTIFY_DATA_IN 112
-#define A_SIR_NOTIFY_COMMAND 111
-#define A_SIR_NOTIFY_DUMP_NEXT_CODE 110
-#define A_SIR_NOTIFY_ISSUE_CHECK 109
-#define A_SIR_NOTIFY_WAIT_RESELECT 108
-#define A_SIR_NOTIFY_ISSUE 107
-#define A_SIR_NOTIFY_SIGP 106
-#define A_SIR_NOTIFY_DUMP2 105
-#define A_SIR_NOTIFY_DUMP 104
-#define A_SIR_NOTIFY_STATUS 103
-#define A_SIR_NOTIFY_MSG_IN 102
-#define A_SIR_NOTIFY_RESELECT 101
-#define A_SIR_NOTIFY_DISC 100
-#define A_SIR_MSG_IGNORE_WIDE_RESIDUE 16
-#define A_SIR_MSG_WDTR 15
-#define A_SIR_EV_PHASE_SWITCH_AFTER_ID 14
-#define A_error_sigp_set 13
-#define A_SIR_EV_RESPONSE_OK 12
-#define A_SIR_MSG_SDTR 11
-#define A_SIR_MSG_REJECT 10
-#define A_error_too_little_data 9
-#define A_error_too_much_data 8
-#define A_error_not_identify_after_reselect 7
-#define A_SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT 6
-#define A_error_weird_message 5
-#define A_error_unexpected_phase 4
-#define A_error_reselected 3
-#define A_error_disconnected 2
-#define A_error_not_cmd_complete 1
-#define A_SIR_MSG_IO_COMPLETE 0

+ 36 - 25
sys/src/9/pc/sd53c8xx.n

@@ -54,12 +54,14 @@ SIR_NOTIFY_BLOCK_DATA_IN = 114
 SIR_NOTIFY_WSR = 115
 SIR_NOTIFY_LOAD_SYNC = 116
 SIR_NOTIFY_RESELECTED_ON_SELECT = 117
+SIR_NOTIFY_LOAD_STATE = 118
 
 STATE_FREE = 0
 STATE_ALLOCATED = 1
 STATE_ISSUE = 2
 STATE_DISCONNECTED = 3
 STATE_DONE = 4
+STATE_END = 5
 
 RESULT_OK = 0
 	
@@ -76,7 +78,7 @@ MSG_REJECT = 0x07
 BSIZE = 512
 //BSIZE=4096
 
-idle:
+ // idle:
 	jump	wait_for_reselection	
 start:
 	call	load_sync
@@ -84,7 +86,7 @@ start:
 //	int	SIR_NOTIFY_ISSUE
 	clear	target
 	select	atn from scsi_id_buf, reselected_on_select // do I need to clear ATN here?
-	jump	start1, when msg_in
+	jump	start1, when msg_in	// why is this here?
 start1:
 //	move	14 to ctest0
 	move	from msg_out_buf, when msg_out
@@ -320,21 +322,13 @@ find_dsa:
  	move	memory 4, dsa_head, dsa
 find_dsa_loop:
 //	move	7 to ctest0
-	move	dsa0 to sfbr
-	jump	find_dsa_1, if not 0
-	move	dsa1 to sfbr
-	jump	find_dsa_1, if not 0
-	move	dsa2 to sfbr
-	jump	find_dsa_1, if not 0
-	move	dsa3 to sfbr
-	int	error_reselected, if 0			// couldn't match dsa (panic)
-find_dsa_1:
 //	move	8 to ctest0
 	// load state from DSA into dsa_copy
 	call	load_state
 	move	memory 4, state, scratcha		// get dsastate in scratcha
 	move	scratcha0 to sfbr			// and state variable in sfbr
 	jump	find_dsa_next, if not STATE_DISCONNECTED // wrong state
+	int	error_reselected, if STATE_END
 	move	ssid & ssid_mask to sfbr			// get target ID
 	move	memory 1, targ, find_dsa_smc1		// forge target comparison instruction
 find_dsa_smc1:
@@ -350,6 +344,7 @@ find_dsa_next:
 // id_out terminated early
 // most likely the message wasn't recognised
 // clear ATN and accept the message in
+// called from sd53c8xx.c directly
 id_out_mismatch_recover:
 	clear	atn
         jump    msg_in_phase, when msg_in
@@ -374,6 +369,7 @@ to_decisions:
 	jump	status_phase, if status
 	jump	msg_in_phase, if msg_in
 	int	error_unexpected_phase
+
 post_data_to_decisions:
 	jump	status_phase, when status
 	jump	msg_in_phase, if msg_in
@@ -398,6 +394,30 @@ dsa_load_len = dsa_load_end - dsa_copy
 dsa_save_len = dsa_save_end - dsa_copy
 
 load_state:
+//	int	SIR_NOTIFY_LOAD_STATE
+	jump load_state_okay
+
+	move	dsa0 to sfbr
+	jump load_state_okay, if not 0
+	move	dsa1 to sfbr
+	jump load_state_okay, if not 0
+	move	dsa2 to sfbr
+	jump load_state_okay, if not 0
+	move	dsa3 to sfbr
+	jump load_state_okay, if not 0
+	// dsa is 0
+	move	memory 4, dsa, dmaaddr
+	move	memory 4, dsa, targ
+	move	memory 4, dsa, lun
+	move	memory 4, dsa, sync
+	move	memory 4, dsa, next
+	move	memory 4, dsa, scratcha
+	move	STATE_END to sfbr
+	move	sfbr to scratcha0
+	move	memory 4, scratcha, state
+	return
+
+load_state_okay:
 	// load state from DSA into dsa_copy
 //	move	9 to ctest0
 	move	memory 4, dsa, load_state_smc0 + 4
@@ -419,30 +439,21 @@ issue_check:
 //	move	1 to ctest0
 	move	memory 4, dsa_head, dsa
 issue_check_loop:
-//	move	2 to ctest0
-	move	dsa0 to sfbr
-	jump	issue_check_1, if not 0
-	move	dsa1 to sfbr
-	jump	issue_check_1, if not 0
-	move	dsa2 to sfbr
-	jump	issue_check_1, if not 0
-	move	dsa3 to sfbr
-	jump	wait_for_reselection, if 0		// nothing to do
-issue_check_1:
-//	move	3 to ctest0
  	call	load_state
 	move	memory 4, state, scratcha		// get dsastate in scratcha
 	move	scratcha0 to sfbr			// and state variable in sfbr
 	jump	start, if STATE_ISSUE			// right state
-issue_check_next:
-//	move	4 to ctest0
+	jump	wait_for_reselection, if STATE_END
+ //	move	4 to ctest0
 	move	memory 4, next, dsa			// find next
 	jump	issue_check_loop
+
+
 load_sync:
 	move	memory 4, sync, scratcha		// load the sync stuff
 	move	scratcha0 to sfbr			// assuming load_state has been called
 	move	sfbr to scntl3
 	move	scratcha1 to sfbr
 	move	sfbr to sxfer
-//	int	SIR_NOTIFY_LOAD_SYNC
+ //	int	SIR_NOTIFY_LOAD_SYNC
 	return

+ 103 - 91
sys/src/9/pc/sdata.c

@@ -9,6 +9,9 @@
 
 #include "../port/sd.h"
 
+#define	HOWMANY(x, y)	(((x)+((y)-1))/(y))
+#define ROUNDUP(x, y)	(HOWMANY((x), (y))*(y))
+
 extern SDifc sdataifc;
 
 enum {
@@ -254,14 +257,15 @@ enum {					/* bit masks for supported/enabled features */
 typedef struct Ctlr Ctlr;
 typedef struct Drive Drive;
 
-typedef struct Prd {
+typedef struct Prd {			/* Physical Region Descriptor */
 	ulong	pa;			/* Physical Base Address */
 	int	count;
 } Prd;
 
 enum {
-	PRDmaxio	= 32*1024,	/* must be power of 2 <= 64*1024 */
-	Nprd		= SDmaxio/PRDmaxio+2,
+	BMspan		= 64*1024,	/* must be power of 2 <= 64*1024 */
+
+	Nprd		= SDmaxio/BMspan+2,
 };
 
 typedef struct Ctlr {
@@ -270,6 +274,8 @@ typedef struct Ctlr {
 	int	irq;
 	int	tbdf;
 	int	bmiba;			/* bus master interface base address */
+	int	maxio;			/* sector count transfer maximum */
+	int	span;			/* don't span this boundary with dma */
 
 	Pcidev*	pcidev;
 	void	(*ienable)(Ctlr*);
@@ -734,7 +740,8 @@ ataprobe(int cmdport, int ctlport, int irq)
 	SDev *sdev;
 	Drive *drive;
 	int dev, error, rhi, rlo;
-
+	static int nonlegacy = 'C';
+	
 	if(ioalloc(cmdport, 8, 0, "atacmd") < 0) {
 		print("ataprobe: Cannot allocate %X\n", cmdport);
 		return nil;
@@ -877,7 +884,20 @@ tryedd1:
 	ctlr->irq = irq;
 	ctlr->tbdf = BUSUNKNOWN;
 	ctlr->command = Cedd;		/* debugging */
-
+	
+	switch(cmdport){
+	default:
+		sdev->idno = nonlegacy;
+		break;
+	case 0x1F0:
+		sdev->idno = 'C';
+		nonlegacy = 'E';
+		break;
+	case 0x170:
+		sdev->idno = 'D';
+		nonlegacy = 'E';
+		break;
+	}
 	sdev->ifc = &sdataifc;
 	sdev->ctlr = ctlr;
 	sdev->nunit = 2;
@@ -921,12 +941,26 @@ atastat(SDev *sdev, char *p, char *e)
 static SDev*
 ataprobew(DevConf *cf)
 {
+	char *p;
+	ISAConf isa;
+	
 	if (cf->nports != 2)
 		error(Ebadarg);
 
+	memset(&isa, 0, sizeof isa);
+	isa.port = cf->ports[0].port;
+	isa.irq = cf->intnum;
+	if((p=strchr(cf->type, '/')) == nil || pcmspecial(p+1, &isa) < 0)
+		error("cannot find controller");
+
 	return ataprobe(cf->ports[0].port, cf->ports[1].port, cf->intnum);
 }
 
+/*
+ * These are duplicated with sdsetsense, etc., in devsd.c, but
+ * those assume that the disk is not SCSI while in fact here
+ * ata drives are not SCSI but ATAPI ones kind of are.
+ */
 static int
 atasetsense(Drive* drive, int status, int key, int asc, int ascq)
 {
@@ -937,6 +971,33 @@ atasetsense(Drive* drive, int status, int key, int asc, int ascq)
 	return status;
 }
 
+static int
+atamodesense(Drive* drive, uchar* cmd)
+{
+	int len;
+
+	/*
+	 * Fake a vendor-specific request with page code 0,
+	 * return the drive info.
+	 */
+	if((cmd[2] & 0x3F) != 0 && (cmd[2] & 0x3F) != 0x3F)
+		return atasetsense(drive, SDcheck, 0x05, 0x24, 0);
+	len = (cmd[7]<<8)|cmd[8];
+	if(len == 0)
+		return SDok;
+	if(len < 8+sizeof(drive->info))
+		return atasetsense(drive, SDcheck, 0x05, 0x1A, 0);
+	if(drive->data == nil || drive->dlen < len)
+		return atasetsense(drive, SDcheck, 0x05, 0x20, 1);
+	memset(drive->data, 0, 8);
+	drive->data[0] = sizeof(drive->info)>>8;
+	drive->data[1] = sizeof(drive->info);
+	memmove(drive->data+8, drive->info, sizeof(drive->info));
+	drive->data += 8+sizeof(drive->info);
+
+	return SDok;
+}
+
 static int
 atastandby(Drive* drive, int period)
 {
@@ -959,7 +1020,7 @@ atastandby(Drive* drive, int period)
 
 	while(waserror())
 		;
-	tsleep(ctlr, atadone, ctlr, 30*1000);
+	tsleep(ctlr, atadone, ctlr, 60*1000);
 	poperror();
 
 	done = ctlr->done;
@@ -970,33 +1031,6 @@ atastandby(Drive* drive, int period)
 	return SDok;
 }
 
-static int
-atamodesense(Drive* drive, uchar* cmd)
-{
-	int len;
-
-	/*
-	 * Fake a vendor-specific request with page code 0,
-	 * return the drive info.
-	 */
-	if((cmd[2] & 0x3F) != 0 && (cmd[2] & 0x3F) != 0x3F)
-		return atasetsense(drive, SDcheck, 0x05, 0x24, 0);
-	len = (cmd[7]<<8)|cmd[8];
-	if(len == 0)
-		return SDok;
-	if(len < 8+sizeof(drive->info))
-		return atasetsense(drive, SDcheck, 0x05, 0x1A, 0);
-	if(drive->data == nil || drive->dlen < len)
-		return atasetsense(drive, SDcheck, 0x05, 0x20, 1);
-	memset(drive->data, 0, 8);
-	drive->data[0] = sizeof(drive->info)>>8;
-	drive->data[1] = sizeof(drive->info);
-	memmove(drive->data+8, drive->info, sizeof(drive->info));
-	drive->data += 8+sizeof(drive->info);
-
-	return SDok;
-}
-
 static void
 atanop(Drive* drive, int subcommand)
 {
@@ -1055,29 +1089,32 @@ atadmasetup(Drive* drive, int len)
 	Prd *prd;
 	ulong pa;
 	Ctlr *ctlr;
-	int bmiba, bmisx, count;
+	int bmiba, bmisx, count, i, span;
 
+	ctlr = drive->ctlr;
 	pa = PCIWADDR(drive->data);
 	if(pa & 0x03)
 		return -1;
-	ctlr = drive->ctlr;
-	prd = ctlr->prdt;
 
 	/*
 	 * Sometimes drives identify themselves as being DMA capable
 	 * although they are not on a busmastering controller.
 	 */
+	prd = ctlr->prdt;
 	if(prd == nil){
 		drive->dmactl = 0;
 		print("disabling dma: not on a busmastering controller\n");
 		return -1;
 	}
 
-	for(;;){
+	for(i = 0; len && i < Nprd; i++){
 		prd->pa = pa;
-		count = PRDmaxio - (pa & (PRDmaxio-1));
+		span = ROUNDUP(pa, ctlr->span);
+		if(span == pa)
+			span += ctlr->span;
+		count = span - pa;
 		if(count >= len){
-			prd->count = PrdEOT|(len & (PRDmaxio-1));
+			prd->count = PrdEOT|len;
 			break;
 		}
 		prd->count = count;
@@ -1085,6 +1122,8 @@ atadmasetup(Drive* drive, int len)
 		pa += count;
 		prd++;
 	}
+	if(i == Nprd)
+		(prd-1)->count |= PrdEOT;
 
 	bmiba = ctlr->bmiba;
 	outl(bmiba+Bmidtpx, PCIWADDR(ctlr->prdt));
@@ -1271,7 +1310,7 @@ atapktio(Drive* drive, uchar* cmd, int clen)
 			break;
 		ilock(ctlr);
 		atadmainterrupt(drive, 0);
-		if(!drive->error && timeo > 10){
+		if(!drive->error && timeo > 20){
 			ataabort(drive, 0);
 			atadmastop(ctlr);
 			drive->dmactl = 0;
@@ -1389,7 +1428,8 @@ atageniostart(Drive* drive, vlong lba)
 	case Cws:
 	case Cwsm:
 		microdelay(1);
-		as = ataready(cmdport, ctlport, 0, Bsy, Drq|Err, 1000);
+		/* 10*1000 for flash ide drives - maybe detect them? */
+		as = ataready(cmdport, ctlport, 0, Bsy, Drq|Err, 10*1000);
 		if(as < 0 || (as & Err)){
 			iunlock(ctlr);
 			return -1;
@@ -1430,8 +1470,8 @@ atagenio(Drive* drive, uchar* cmd, int)
 {
 	uchar *p;
 	Ctlr *ctlr;
-	int count, max;
 	vlong lba, len;
+	int count, maxio;
 
 	/*
 	 * Map SCSI commands into ATA commands for discs.
@@ -1522,7 +1562,7 @@ atagenio(Drive* drive, uchar* cmd, int)
 		*p++ = len>>16;
 		*p++ = len>>8;
 		*p = len;
-		drive->data += 8;
+		drive->data += 12;
 		return SDok;
 
 	case 0x28:			/* read */
@@ -1541,10 +1581,15 @@ atagenio(Drive* drive, uchar* cmd, int)
 	if(drive->dlen < count*drive->secsize)
 		count = drive->dlen/drive->secsize;
 	qlock(ctlr);
+	if(ctlr->maxio)
+		maxio = ctlr->maxio;
+	else if(drive->flags & Lba48)
+		maxio = 65536;
+	else
+		maxio = 256;
 	while(count){
-		max = (drive->flags&Lba48) ? 65536 : 256;
-		if(count > max)
-			drive->count = max;
+		if(count > maxio)
+			drive->count = maxio;
 		else
 			drive->count = count;
 		if(atageniostart(drive, lba)){
@@ -1557,7 +1602,7 @@ atagenio(Drive* drive, uchar* cmd, int)
 
 		while(waserror())
 			;
-		tsleep(ctlr, atadone, ctlr, 30*1000);
+		tsleep(ctlr, atadone, ctlr, 60*1000);
 		poperror();
 		if(!ctlr->done){
 			/*
@@ -1797,8 +1842,8 @@ atapnp(void)
 {
 	Ctlr *ctlr;
 	Pcidev *p;
-	int channel, ispc87415, pi, r;
 	SDev *legacy[2], *sdev, *head, *tail;
+	int channel, ispc87415, maxio, pi, r, span;
 
 	legacy[0] = legacy[1] = head = tail = nil;
 	if(sdev = ataprobe(0x1F0, 0x3F4, IrqATA0)){
@@ -1839,6 +1884,8 @@ atapnp(void)
 			continue;
 		pi = p->ccrp;
 		ispc87415 = 0;
+		maxio = 0;
+		span = BMspan;
 
 		switch((p->did<<16)|p->vid){
 		default:
@@ -1868,8 +1915,11 @@ atapnp(void)
 		case (0x4D69<<16)|0x105A:	/* Promise Ultra/133 TX2 */
 		case (0x3373<<16)|0x105A:	/* Promise 20378 RAID */
 		case (0x3149<<16)|0x1106:	/* VIA VT8237 SATA/RAID */
-		case (0x3112<<16)|0x1095:   	/* SiL 3112 SATA (DMA busted?) */
-		case (0x3114<<16)|0x1095:	/* SiL 3114 SATA/RAID */
+		case (0x3112<<16)|0x1095:   	/* SiI 3112 SATA/RAID */
+			maxio = 15;
+			span = 8*1024;
+			/*FALLTHROUGH*/
+		case (0x3114<<16)|0x1095:	/* SiI 3114 SATA/RAID */
 			pi = 0x85;
 			break;
 		case (0x0004<<16)|0x1103:	/* HighPoint HPT366 */
@@ -1932,6 +1982,7 @@ atapnp(void)
 				r &= ~0x2000;
 				pcicfgw32(sb, 0x64, r);
 			}
+			span = 32*1024;
 			break;
 		case (0x5513<<16)|0x1039:	/* SiS 962 */
 		case (0x0646<<16)|0x1095:	/* CMD 646 */
@@ -1979,6 +2030,8 @@ atapnp(void)
 				ctlr = sdev->ctlr;
 
 			ctlr->pcidev = p;
+			ctlr->maxio = maxio;
+			ctlr->span = span;
 			if(!(pi & 0x80))
 				continue;
 			ctlr->bmiba = (p->mem[4].bar & ~0x01) + channel*8;
@@ -2030,46 +2083,6 @@ atalegacy(int port, int irq)
 	return ataprobe(port, port+0x204, irq);
 }
 
-static SDev*
-ataid(SDev* sdev)
-{
-	int i;
-	Ctlr *ctlr;
-	char name[32];
-
-	/*
-	 * Legacy controllers are always 'C' and 'D' and if
-	 * they exist and have drives will be first in the list.
-	 * If there are no active legacy controllers, native
-	 * controllers start at 'C'.
-	 */
-	if(sdev == nil)
-		return nil;
-	ctlr = sdev->ctlr;
-	if(ctlr->cmdport == 0x1F0 || ctlr->cmdport == 0x170)
-		i = 2;
-	else
-		i = 0;
-	while(sdev){
-		if(sdev->ifc == &sdataifc){
-			ctlr = sdev->ctlr;
-			if(ctlr->cmdport == 0x1F0)
-				sdev->idno = 'C';
-			else if(ctlr->cmdport == 0x170)
-				sdev->idno = 'D';
-			else{
-				sdev->idno = 'C'+i;
-				i++;
-			}
-			snprint(name, sizeof(name), "sd%c", sdev->idno);
-			kstrdup(&sdev->name, name);
-		}
-		sdev = sdev->next;
-	}
-
-	return nil;
-}
-
 static int
 ataenable(SDev* sdev)
 {
@@ -2230,7 +2243,6 @@ SDifc sdataifc = {
 
 	atapnp,				/* pnp */
 	atalegacy,			/* legacy */
-	ataid,				/* id */
 	ataenable,			/* enable */
 	atadisable,			/* disable */
 

+ 1346 - 0
sys/src/9/pc/sdmv50xx.c

@@ -0,0 +1,1346 @@
+/*
+ * Marvell 88SX5040, 5041, 5080, 5081 driver
+ * This is a heavily-modified version of a driver written by Coraid, Inc.
+ * The original copyright notice appears at the end of this file.
+ */
+ 
+#include	"u.h"
+#include	"../port/lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include 	"io.h"
+#include	"../port/error.h"
+
+#include	"../port/sd.h"
+
+#define DPRINT	if(0)iprint
+
+enum {
+	SrbRing = 32,
+	
+	/* Addresses of ATA register */
+	ARcmd		= 027,
+	ARdev		= 026,
+	ARerr		= 021,
+	ARfea		= 021,
+	ARlba2		= 025,
+	ARlba1		= 024,
+	ARlba0		= 023,
+	ARseccnt		= 022,
+	ARstat		= 027,
+	
+	ATAerr	= (1<<0),
+	ATAdrq	= (1<<3),
+	ATAdf 	= (1<<5),
+	ATAdrdy 	= (1<<6),
+	ATAbusy 	= (1<<7),
+	ATAabort	= (1<<2),
+	ATAeIEN	= (1<<1),
+	ATAsrst	= (1<<2),
+	ATAhob	= (1<<7),
+
+	SFdone = (1<<0),
+	SFerror = (1<<1),
+
+	SRBident = 0,
+	SRBread,
+	SRBwrite,
+	SRBsmart,
+
+	SRBnodata = 0,
+	SRBdatain,
+	SRBdataout,
+	
+	RQread	= 1,			/* data coming IN from device */
+	
+	PRDeot	= (1<<15),
+	
+	/* EDMA interrupt error cause register */
+
+	ePrtDataErr	= (1<<0),
+	ePrtPRDErr	= (1<<1),
+	eDevErr		= (1<<2),
+	eDevDis		= (1<<3),
+	eDevCon		= (1<<4),
+	eOverrun		= (1<<5),
+	eUnderrun	= (1<<6),
+	eSelfDis		= (1<<8),
+	ePrtCRQBErr	= (1<<9),
+	ePrtCRPBErr	= (1<<10),
+	ePrtIntErr		= (1<<11),
+	eIORdyErr		= (1<<12),
+
+	/* EDMA Command Register */
+
+	eEnEDMA		= (1<<0),
+	eDsEDMA 	= (1<<1),
+	eAtaRst 		= (1<<2),
+
+	/* Interrupt mask for errors we care about */
+	IEM			= (eDevDis | eDevCon | eSelfDis),
+	
+	Dnull = 0,
+	Dnew,
+	Dident,
+	Dready,
+	Derror,
+	Dmissing,
+	Dunconfig,
+
+	Dext	 	= (1<<0),		/* use ext commands */
+	Dpio		= (1<<1),		/* doing pio */
+	Dwanted	= (1<<2),		/* someone wants an srb entry */
+	Dedma	= (1<<3),		/* device in edma mode */
+	Dpiowant	= (1<<4),		/* some wants to use the pio mode */
+};
+
+static char* diskstates[] =
+{
+	"null",
+	"new",
+	"ident",
+	"ready",
+	"error",
+	"missing",
+	"unconfigured",
+};
+
+extern SDifc sdmv50xxifc;
+
+typedef struct Arb Arb;
+typedef struct Bridge Bridge;
+typedef struct Chip Chip;
+typedef struct Ctlr Ctlr;
+typedef struct Drive Drive;
+typedef struct Edma Edma;
+typedef struct Prd Prd;
+typedef struct Rx Rx;
+typedef struct Srb Srb;
+typedef struct Tx Tx;
+
+struct Chip	/* pointers to per-Chip mmio */
+{
+	Arb		*arb;
+	Edma	*edma;	/* array of 4 */
+};
+
+struct Drive	/* a single disk */
+{
+	Lock;
+
+	Ctlr		*ctlr;
+	SDunit	*unit;
+	int		subno;
+	char		name[10];
+
+	Bridge	*bridge;
+	Edma	*edma;
+	Chip		*chip;
+	int		chipx;
+	
+	int		state;
+	int		flag;
+	uvlong	sectors;
+
+	char		serial[20+1];
+	char		firmware[8+1];
+	char		model[40+1];
+
+	ushort	info[256];
+	
+	Srb		*srb[SrbRing-1];
+	int		nsrb;
+	Prd		*prd;
+	Tx		*tx;
+	Rx		*rx;
+	
+	Srb		*srbhead;
+	Srb		*srbtail;
+};
+
+struct Ctlr		/* a single PCI card */
+{
+	Lock;
+
+	int		irq;
+	int		tbdf;
+	SDev		*sdev;
+	Pcidev	*pcidev;
+
+	uchar	*mmio;
+	Chip		chip[2];
+	int		nchip;
+	Drive	drive[8];
+	int		ndrive;
+};
+
+struct Srb		/* request buffer */
+{
+	Lock;
+	Rendez;
+	Srb		*next;
+
+	Drive	*drive;
+	uvlong	blockno;
+	int		count;
+	int		req;
+	int		flag;
+	uchar	*data;
+	
+	uchar	cmd;
+	uchar	lba[6];
+	uchar	sectors;
+	int		sta;
+	int		err;
+};
+
+/*
+ * Memory-mapped I/O registers in many forms.
+ */
+struct Bridge	/* memory-mapped per-Drive registers */
+{
+	ulong	status;
+	ulong	serror;
+	ulong	sctrl;
+	ulong	phyctrl;
+	char		fill1[0x2c];
+	ulong	ctrl;
+	char		fill2[0x34];
+	ulong	phymode;
+	char		fill3[0x88];	/* pad to 0x100 in length */
+};
+
+struct Arb		/* memory-mapped per-Chip registers */
+{
+	ulong	fill0;
+	ulong	rqop;	/* request queue out-pointer */
+	ulong	rqip;		/* response queue in pointer */
+	ulong	ict;		/* inerrupt caolescing threshold */
+	ulong	itt;		/* interrupt timer threshold */
+	ulong	ic;		/* interrupt cause */
+	ulong	btc;		/* bridges test control */
+	ulong	bts;		/* bridges test status */
+	ulong	bpc;		/* bridges pin configuration */
+	char		fill1[0xdc];
+	Bridge	bridge[4];
+};
+
+struct Edma	/* memory-mapped per-Drive DMA-related registers */
+{
+	ulong		config;		/* configuration register */
+	ulong		timer;
+	ulong		iec;			/* interrupt error cause */
+	ulong		iem;			/* interrupt error mask */
+
+	ulong		txbasehi;		/* request queue base address high */
+	ulong		txi;			/* request queue in pointer */
+	ulong		txo;			/* request queue out pointer */
+
+	ulong		rxbasehi;		/* response queue base address high */
+	ulong		rxi;			/* response queue in pointer */
+	ulong		rxo;			/* response queue out pointer */
+	
+	ulong		ctl;			/* command register */
+	ulong		testctl;		/* test control */
+	ulong		status;
+	ulong		iordyto;		/* IORDY timeout */
+	char			fill[0xc8];
+	ushort		pio;			/* data register */
+	char			pad0[2];
+	uchar		err;			/* features and error */
+	char			pad1[3];
+	uchar		seccnt;		/* sector count */
+	char			pad2[3];
+	uchar		lba0;
+	char			pad3[3];
+	uchar		lba1;
+	char			pad4[3];
+	uchar		lba2;
+	char			pad5[3];
+	uchar		lba3;
+	char			pad6[3];
+	uchar		cmdstat;		/* cmd/status */
+	char			pad7[3];
+	uchar		altstat;		/* alternate status */
+	char			fill2[0x1edc];	/* pad to 0x2000 bytes */
+};
+
+/*
+ * Memory structures shared with card.
+ */
+struct Prd		/* physical region descriptor */
+{
+	ulong	pa;		/* byte address of physical memory */
+	ushort	count;		/* byte count (bit0 must be 0) */
+	ushort	flag;
+	ulong	zero;			/* high long of 64 bit address */
+	ulong	reserved;
+};
+
+struct Tx		/* command request block */
+{
+	ulong	prdpa;		/* physical region descriptor table structures */
+	ulong	zero;			/* must be zero (high long of prd address) */
+	ushort	flag;			/* control flags */
+	ushort	regs[11];
+};
+
+struct Rx		/* command response block */
+{
+	ushort	cid;			/* cID of response */
+	uchar	cEdmaSts;		/* EDMA status */
+	uchar	cDevSts;		/* status from disk */
+	ulong	ts;			/* time stamp */
+};
+
+/*
+ * Little-endian parsing for drive data.
+ */
+static ushort
+lhgets(void *p)
+{
+	uchar *a = p;
+	return ((ushort) a[1] << 8) | a[0];
+}
+
+static ulong
+lhgetl(void *p)
+{
+	uchar *a = p;
+	return ((ulong) lhgets(a+2) << 16) | lhgets(a);
+}
+
+static uvlong
+lhgetv(void *p)
+{
+	uchar *a = p;
+	return ((uvlong) lhgetl(a+4) << 32) | lhgetl(a);
+}
+
+static void
+idmove(char *p, ushort *a, int n)
+{
+	char *op;
+	int i;
+	
+	op = p;
+	for(i=0; i<n/2; i++){
+		*p++ = a[i]>>8;
+		*p++ = a[i];
+	}
+	while(p>op && *--p == ' ')
+		*p = 0;
+}
+
+/*
+ * Request buffers.
+ */
+struct 
+{
+	Lock;
+	Srb *freechain;
+	int nalloc;
+} srblist;
+
+static Srb*
+allocsrb(void)
+{
+	Srb *p;
+	
+	ilock(&srblist);
+	if((p = srblist.freechain) == nil){
+		srblist.nalloc++;
+		iunlock(&srblist);
+		p = smalloc(sizeof *p);
+	}else{
+		srblist.freechain = p->next;
+		iunlock(&srblist);
+	}
+	return p;
+}
+
+static void
+freesrb(Srb *p)
+{
+	ilock(&srblist);
+	p->next = srblist.freechain;
+	srblist.freechain = p;
+	iunlock(&srblist);
+}
+
+/*
+ * Wait for a byte to be a particular value.
+ */
+static int
+satawait(uchar *p, uchar mask, uchar v, int ms)
+{
+	int i;
+
+//	DPRINT("satawait %p %#x %#x %d...", p, mask, v, ms);
+//	DPRINT("!%#x...", *p);
+	for(i=0; i<ms && (*p & mask) != v; i++){
+		if(i%1000 == 0)
+			DPRINT("!%#x", *p);
+		microdelay(1000);
+	}
+	return (*p & mask) == v;
+}
+
+/*
+ * Drive initialization
+ */
+static int
+configdrive(Ctlr *ctlr, Drive *d, SDunit *unit)
+{
+	int i;
+	ulong *r;
+	
+	DPRINT("%s: configdrive\n", unit->name);
+	d->unit = unit;
+	d->ctlr = ctlr;
+	d->chipx = unit->subno%4;
+	d->chip = &ctlr->chip[unit->subno/4];
+	d->bridge = &d->chip->arb->bridge[d->chipx];
+	d->edma = &d->chip->edma[d->chipx];
+
+	if(d->tx == nil){
+		d->tx = mallocalign(32*sizeof(Tx), 1024, 0, 0);
+		d->rx = mallocalign(32*sizeof(Rx), 256, 0, 0);
+		d->prd = mallocalign(32*sizeof(Prd), 32, 0, 0);
+		if(d->tx == nil || d->rx == nil || d->prd == nil){
+			iprint("%s: out of memory allocating ring buffers\n",
+				unit->name);
+			free(d->tx);
+			d->tx = nil;
+			free(d->rx);
+			d->rx = nil;
+			free(d->prd);
+			d->prd = nil;
+			d->state = Dunconfig;
+			return 0;
+		}
+		for(i=0; i<32; i++)
+			d->tx[i].prdpa = PADDR(&d->prd[i]);
+		coherence();
+	}
+	
+	/* leave disk interrupts turned off until we use it ... */
+	d->edma->iem = 0;
+	
+	/* ... but enable them on the controller */
+	r = (ulong*)(d->ctlr->mmio + 0x1D64);
+	if(d->unit->subno < 4)
+		*r |= 3 << (d->chipx*2);
+	else
+		*r |= 3 << (d->chipx*2+9);
+
+	return 1;
+}
+
+static int
+enabledrive(Drive *d)
+{
+	Edma *edma;
+	
+	DPRINT("%s: enabledrive\n", d->unit->name);
+
+	if((d->bridge->status & 0xF) != 0x3){	/* Det */
+		DPRINT("%s: not present\n", d->unit->name);
+		d->state = Dmissing;
+		return 0;
+	}
+	edma = d->edma;
+	if(satawait(&edma->cmdstat, ATAbusy, 0, 10*1000) == 0){
+		print("%s: busy timeout\n", d->unit->name);
+		d->state = Dmissing;
+		return 0;
+	}
+
+	edma->iec = 0;
+	d->chip->arb->ic &= ~(0x101 << d->chipx);
+	edma->config = 0x11F;
+	edma->txi = PADDR(d->tx);
+	edma->txo = (ulong)d->tx & 0x3E0;
+	edma->rxi = (ulong)d->rx & 0xF8;
+	edma->rxo = PADDR(d->rx);
+	edma->ctl |= 1;		/* enable dma */
+
+	DPRINT("%s: enable interrupts\n", d->unit->name);
+	if(d->bridge->status = 0x113)
+		d->state = Dnew;
+	d->edma->iem = IEM;
+	return 1;
+}
+
+static void
+disabledrive(Drive *d)
+{
+	int i;
+	ulong *r;
+
+	DPRINT("%s: disabledrive\n", d->unit->name);
+
+	if(d->tx == nil)	/* never enabled */
+		return;
+
+	d->edma->ctl = 0;
+	d->edma->iem = 0;
+
+	r = (ulong*)(d->ctlr->mmio + 0x1D64);
+	i = d->chipx;
+	if(d->chipx < 4)
+		*r &= ~(3 << (i*2));
+	else
+		*r |= ~(3 << (i*2+9));
+}
+
+static int
+setudmamode(Drive *d, uchar mode)
+{
+	Edma *edma;
+	
+	DPRINT("%s: setudmamode %d\n", d->unit->name, mode);
+
+	edma = d->edma;
+	if(satawait(&edma->cmdstat, ATAerr|ATAdrq|ATAdf|ATAdrdy|ATAbusy, ATAdrdy, 15*1000) == 0){
+		iprint("%s: cmdstat 0x%.2ux ready timeout\n",
+			d->unit->name, edma->cmdstat);
+		return 0;
+	}
+	edma->altstat = ATAeIEN;
+	edma->err = 3;
+	edma->seccnt = 0x40 | mode;
+	edma->cmdstat = 0xEF;
+	microdelay(1);
+	if(satawait(&edma->cmdstat, ATAbusy, 0, 15*1000) == 0){
+		iprint("%s: cmdstat 0x%.2ux busy timeout\n", 
+			d->unit->name, edma->cmdstat);
+		return 0;
+	}
+	return 1;
+}
+
+static void
+identifydrive(Drive *d)
+{
+	int i;
+	ushort *id;
+	Edma *edma;
+	SDunit *unit;
+	
+	DPRINT("%s: identifydrive\n", d->unit->name);
+
+	if(setudmamode(d, 5) == 0)	/* do all SATA support 5? */
+		goto Error;
+
+	id = d->info;
+	memset(d->info, 0, sizeof d->info);
+	edma = d->edma;
+	if(satawait(&edma->cmdstat, 0xE9, 0x40, 15*1000) == 0)
+		goto Error;
+
+	edma->altstat = ATAeIEN;	/* no interrupts */
+	edma->cmdstat = 0xEC;
+	microdelay(1);
+	if(satawait(&edma->cmdstat, ATAbusy, 0, 15*1000) == 0)
+		goto Error;
+	for(i=0; i<256; i++)
+		id[i] = edma->pio;
+	if(edma->cmdstat & (ATAerr|ATAdf))
+		goto Error;
+	i = lhgets(id+83) | lhgets(id+86);
+	if(i & (1<<10)){
+		d->flag |= Dext;
+		d->sectors = lhgetv(id+100);
+	}else{
+		d->flag &= ~Dext;
+		d->sectors = lhgetl(id+60);
+	}
+	idmove(d->serial, id+10, 20);
+	idmove(d->firmware, id+23, 8);
+	idmove(d->model, id+27, 40);
+	
+	unit = d->unit;
+	memset(unit->inquiry, 0, sizeof unit->inquiry);
+	unit->inquiry[2] = 2;
+	unit->inquiry[3] = 2;
+	unit->inquiry[4] = sizeof(unit->inquiry)-4;
+	idmove((char*)unit->inquiry+8, id+27, 40);
+
+	if(enabledrive(d))
+		d->state = Dready;
+	else
+		d->state = Derror;
+	return;
+
+Error:
+	DPRINT("error...");
+	d->state = Derror;
+}
+
+static void abortallsrb(Drive*);
+
+static void
+updatedrive(Drive *d, ulong cause)
+{
+	int x;
+	Edma *edma;
+	
+	if(cause == 0)
+		return;
+
+	DPRINT("%s: updatedrive %#lux\n", d->unit->name, cause);
+
+	edma = d->edma;
+	if(cause & eDevDis){
+		d->state = Dmissing;
+		edma->ctl |= eAtaRst;
+		microdelay(25);
+		edma->ctl &= ~eAtaRst;
+		microdelay(25);
+	}
+	if(cause & eDevCon){
+		d->bridge->sctrl = (d->bridge->sctrl & ~0xF) | 1;
+		d->state = Dnew;
+	}
+	if(cause & eSelfDis)
+		d->state = Derror;
+	edma->iec = 0;
+	d->sectors = 0;
+	d->unit->sectors = 0;
+	abortallsrb(d);
+	x = edma->cmdstat;
+	USED(x);
+}
+
+/*
+ * Requests
+ */
+static Srb*
+srbrw(int req, Drive *d, uchar *data, uint sectors, uvlong lba)
+{
+	int i;
+	Srb *srb;
+	static uchar cmd[2][2] = { 0xC8, 0x25, 0xCA, 0x35 };
+
+	switch(req){
+	case SRBread:
+	case SRBwrite:
+		break;
+	default:
+		return nil;
+	}
+	
+	srb = allocsrb();
+	srb->req = req;
+	srb->drive = d;
+	srb->blockno = lba;
+	srb->sectors = sectors;
+	srb->count = sectors*512;
+	srb->flag = 0;
+	srb->data = data;
+
+	for(i=0; i<6; i++)
+		srb->lba[i] = lba >> (8*i);
+	srb->cmd = cmd[srb->req!=SRBread][(d->flag&Dext)!=0];
+	return srb;
+}
+
+static uintptr
+advance(uintptr pa, int shift)
+{
+	int n, mask;
+	
+	mask = 0x1F<<shift;
+	n = (pa & mask) + (1<<shift);
+	return (pa & ~mask) | (n & mask);
+}
+
+#define CMD(r, v) (((r)<<8) | ((v)&0xFF))
+static void
+atarequest(ushort *cmd, Srb *srb, int ext)
+{
+	*cmd++ = CMD(ARseccnt, 0);
+	*cmd++ = CMD(ARseccnt, srb->sectors);
+	*cmd++ = CMD(ARfea, 0);
+	if(ext){
+		*cmd++ = CMD(ARlba0, srb->lba[3]);
+		*cmd++ = CMD(ARlba0, srb->lba[0]);
+		*cmd++ = CMD(ARlba1, srb->lba[4]);
+		*cmd++ = CMD(ARlba1, srb->lba[1]);
+		*cmd++ = CMD(ARlba2, srb->lba[5]);
+		*cmd++ = CMD(ARlba2, srb->lba[2]);
+		*cmd++ = CMD(ARdev, 0xE0);
+	}else{
+		*cmd++ = CMD(ARlba0, srb->lba[0]);
+		*cmd++ = CMD(ARlba1, srb->lba[1]);
+		*cmd++ = CMD(ARlba2, srb->lba[2]);
+		*cmd++ = CMD(ARdev, srb->lba[3] | 0xE0);
+	}
+	*cmd++ = CMD(ARcmd, srb->cmd) | (1<<15);
+	USED(cmd);
+}
+
+static void
+startsrb(Drive *d, Srb *srb)
+{
+	int i;
+	Edma *edma;
+	Prd *prd;
+	Tx *tx;
+	
+	if(d->nsrb >= nelem(d->srb)){
+		srb->next = nil;
+		if(d->srbhead)
+			d->srbtail->next = srb;
+		else
+			d->srbhead = srb;
+		d->srbtail = srb;
+		return;
+	}
+	
+	d->nsrb++;
+	for(i=0; i<nelem(d->srb); i++)
+		if(d->srb[i] == nil)
+			break;
+	if(i == nelem(d->srb))
+		panic("sdmv50xx: no free srbs");
+	d->srb[i] = srb;
+	edma = d->edma;
+	tx = (Tx*)KADDR(edma->txi);
+	tx->flag = (i<<1) | (srb->req == SRBread);
+	prd = KADDR(tx->prdpa);
+	prd->pa = PADDR(srb->data);
+	prd->count = srb->count;
+	prd->flag = PRDeot;
+	atarequest(tx->regs, srb, d->flag&Dext);
+	coherence();
+	edma->txi = advance(edma->txi, 5);
+}
+
+static void
+completesrb(Drive *d)
+{
+	Edma *edma;
+	Rx *rx;
+	Srb *srb;
+	
+	edma = d->edma;
+	if((edma->ctl & eEnEDMA) == 0)
+		return;
+	
+	while((edma->rxo & (0x1F<<3)) != (edma->rxi & (0x1F<<3))){
+		rx = (Rx*)KADDR(edma->rxo);
+		if(srb = d->srb[rx->cid]){
+			d->srb[rx->cid] = nil;
+			d->nsrb--;
+			if(rx->cDevSts & (ATAerr|ATAdf))
+				srb->flag |= SFerror;
+			srb->flag |= SFdone;
+			srb->sta = rx->cDevSts;
+			wakeup(srb);
+		}else
+			iprint("srb missing\n");
+		edma->rxo = advance(edma->rxo, 3);
+		if(srb = d->srbhead){
+			d->srbhead = srb->next;
+			startsrb(d, srb);
+		}
+	}
+}
+			
+static void
+abortallsrb(Drive *d)
+{
+	int i;
+	Srb *srb;
+
+	for(i=0; i<nelem(d->srb); i++){
+		if(srb = d->srb[i]){
+			d->srb[i] = nil;
+			d->nsrb--;
+			srb->flag |= SFerror|SFdone;
+			wakeup(srb);
+		}
+	}
+	while(srb = d->srbhead){
+		d->srbhead = srb->next;
+		srb->flag |= SFerror|SFdone;
+		wakeup(srb);
+	}	
+}
+
+static int
+srbdone(void *v)
+{
+	Srb *srb;
+	
+	srb = v;
+	return srb->flag & SFdone;
+}
+
+/*
+ * Interrupts
+ */
+static void
+mv50interrupt(Ureg*, void *a)
+{
+	int i;
+	ulong cause;
+	Ctlr *ctlr;
+	Drive *drive;
+	
+	ctlr = a;
+	ilock(ctlr);
+	cause = *(ulong*)(ctlr->mmio + 0x1D60);
+	DPRINT("sd%c: mv50interrupt: 0x%lux\n", ctlr->sdev->idno, cause);
+	for(i=0; i<ctlr->ndrive; i++){
+		if(cause & (3<<(i*2+i/4))){
+			drive = &ctlr->drive[i];
+			ilock(drive);
+			updatedrive(drive, drive->edma->iec);
+			while(ctlr->chip[i/4].arb->ic & (0x0101 << (i%4))){
+				ctlr->chip[i/4].arb->ic = ~(0x101 << (i%4));
+				completesrb(drive);
+			}
+			iunlock(drive);
+		}
+	}
+	iunlock(ctlr);
+}
+
+/*
+ * Device discovery
+ */
+static SDev*
+mv50pnp(void)
+{
+	int i, nunit;
+	uchar *base;
+	ulong io;
+	void *mem;
+	Ctlr *ctlr;
+	Pcidev *p;
+	SDev *head, *tail, *sdev;
+
+	DPRINT("mv50pnp\n");
+
+	p = nil;
+	head = nil;
+	tail = nil;
+	while((p = pcimatch(p, 0x11AB, 0)) != nil){
+		switch(p->did){
+		case 0x5041:
+			nunit = 4;
+			break;
+		case 0x5081:
+			nunit = 8;
+			break;
+		default:
+			continue;
+		}
+		if((sdev = malloc(sizeof(SDev))) == nil)
+			continue;
+		if((ctlr = malloc(sizeof(Ctlr))) == nil){
+			free(sdev);
+			continue;
+		}
+		io = p->mem[0].bar & ~0x0F;
+		mem = vmap(io, p->mem[0].size);
+		if(mem == 0){
+			print("sdmv50xx: address 0x%luX in use\n", io);
+			free(sdev);
+			free(ctlr);
+			continue;
+		}
+		sdev->ifc = &sdmv50xxifc;
+		sdev->ctlr = ctlr;
+		sdev->nunit = nunit;
+		sdev->idno = 'E';
+		ctlr->sdev = sdev;
+		ctlr->irq = p->intl;
+		ctlr->tbdf = p->tbdf;
+		ctlr->pcidev = p;
+		ctlr->mmio = mem;
+		ctlr->nchip = (nunit+3)/4;
+		ctlr->ndrive = nunit;
+		for(i=0; i<ctlr->nchip; i++){
+			base = ctlr->mmio+0x20000+0x10000*i;
+			ctlr->chip[i].arb = (Arb*)base;
+			ctlr->chip[i].edma = (Edma*)(base + 0x2000);
+		}
+		if(head)
+			tail->next = sdev;
+		else
+			head = sdev;
+		tail = sdev;
+	}
+	return head;
+}
+
+/*
+ * Enable the controller.  Each disk has its own interrupt mask,
+ * and those get enabled as the disks are brought online.
+ */
+static int
+mv50enable(SDev *sdev)
+{
+	char name[32];
+	Ctlr *ctlr;
+
+	DPRINT("sd%c: enable\n", sdev->idno);
+
+	ctlr = sdev->ctlr;
+	snprint(name, sizeof name, "%s (%s)", sdev->name, sdev->ifc->name);
+	intrenable(ctlr->irq, mv50interrupt, ctlr, ctlr->tbdf, name);
+	return 1;
+}
+
+/*
+ * Disable the controller.
+ */
+static int
+mv50disable(SDev *sdev)
+{
+	char name[32];
+	int i;
+	Ctlr *ctlr;
+	Drive *drive;
+	
+	DPRINT("sd%c: disable\n", sdev->idno);
+
+	ctlr = sdev->ctlr;
+	ilock(ctlr);
+	for(i=0; i<ctlr->sdev->nunit; i++){
+		drive = &ctlr->drive[i];
+		ilock(drive);
+		disabledrive(drive);
+		iunlock(drive);
+	}
+	iunlock(ctlr);
+	snprint(name, sizeof name, "%s (%s)", sdev->name, sdev->ifc->name);
+	intrdisable(ctlr->irq, mv50interrupt, ctlr, ctlr->tbdf, name);
+	return 0;
+}
+
+/*
+ * Clean up all disk structures.  Already disabled.
+ * Could keep count of number of allocated controllers
+ * and free the srblist when it drops to zero.
+ */
+static void
+mv50clear(SDev *sdev)
+{
+	int i;
+	Ctlr *ctlr;
+	Drive *d;
+
+	DPRINT("sd%c: clear\n", sdev->idno);
+
+	ctlr = sdev->ctlr;
+	for(i=0; i<ctlr->ndrive; i++){
+		d = &ctlr->drive[i];
+		free(d->tx);
+		free(d->rx);
+		free(d->prd);
+	}
+	free(ctlr);
+}
+
+/*
+ * Check that there is a disk or at least a hot swap bay in the drive.
+ */
+static int
+mv50verify(SDunit *unit)
+{
+	Ctlr *ctlr;
+	Drive *drive;
+
+	DPRINT("%s: verify\n", unit->name);
+
+	/*
+	 * First access of unit.
+	 */
+
+	ctlr = unit->dev->ctlr;
+	drive = &ctlr->drive[unit->subno];
+	ilock(ctlr);
+	ilock(drive);
+
+	if(!configdrive(ctlr, drive, unit) || !enabledrive(drive)){
+		iunlock(drive);
+		iunlock(ctlr);
+		return 0;
+	}
+	/*
+	 * Need to reset the drive before the first call to 
+	 * identifydrive, or else the satawait in setudma will 
+	 * freeze the machine when accessing edma->cmdstat.
+	 * I do not understand this.		-rsc
+	 */
+	updatedrive(drive, eDevDis);
+
+	iunlock(drive);
+	iunlock(ctlr);
+
+	return 1;
+}
+
+/*
+ * Check whether the disk is online.
+ */
+static int
+mv50online(SDunit *unit)
+{
+	Ctlr *ctlr;
+	Drive *drive;
+
+	ctlr = unit->dev->ctlr;
+	drive = &ctlr->drive[unit->subno];
+	ilock(drive);
+	if(drive->state == Dready){
+		unit->sectors = drive->sectors;
+		unit->secsize = 512;
+		iunlock(drive);
+		return 1;
+	}
+
+	DPRINT("%s: online %s\n", unit->name, diskstates[drive->state]);
+
+	if(drive->state == Dnew){
+		identifydrive(drive);
+		if(drive->state == Dready){
+			unit->sectors = drive->sectors;
+			unit->secsize = 512;
+			iunlock(drive);
+			return 2;	/* media changed */
+		}
+	}
+	iunlock(drive);
+	return 0;
+}
+
+/*
+ * Register dumps
+ */
+typedef struct Regs Regs;
+struct Regs
+{
+	ulong offset;
+	char *name;
+};
+
+static Regs regsctlr[] =
+{
+	0x0C28, "pci serr# mask",
+	0x1D40, "pci err addr low",
+	0x1D44, "pci err addr hi",
+	0x1D48, "pci err attr",
+	0x1D50, "pci err cmd",
+	0x1D58, "pci intr cause",
+	0x1D5C, "pci mask cause",
+	0x1D60, "device micr",
+	0x1D64, "device mimr",
+};
+
+static Regs regsarb[] =
+{
+	0x0004,	"arb rqop",
+	0x0008,	"arb rqip",
+	0x000C,	"arb ict",
+	0x0010,	"arb itt",
+	0x0014,	"arb ic",
+	0x0018,	"arb btc",
+	0x001C,	"arb bts",
+	0x0020,	"arb bpc",
+};
+
+static Regs regsbridge[] =
+{
+	0x0000,	"bridge status",
+	0x0004,	"bridge serror",
+	0x0008,	"bridge sctrl",
+	0x000C,	"bridge phyctrl",
+	0x003C,	"bridge ctrl",
+	0x0074,	"bridge phymode",
+};
+
+static Regs regsedma[] =
+{
+	0x0000,	"edma config",
+	0x0004,	"edma timer",
+	0x0008,	"edma iec",
+	0x000C,	"edma iem",
+	0x0010,	"edma txbasehi",
+	0x0014,	"edma txi",
+	0x0018,	"edma txo",
+	0x001C,	"edma rxbasehi",
+	0x0020,	"edma rxi",
+	0x0024,	"edma rxo",
+	0x0028,	"edma c",
+	0x002C,	"edma tc",
+	0x0030,	"edma status",
+	0x0034,	"edma iordyto",
+/*	0x0100,	"edma pio",
+	0x0104,	"edma err",
+	0x0108,	"edma sectors",
+	0x010C,	"edma lba0",
+	0x0110,	"edma lba1",
+	0x0114,	"edma lba2",
+	0x0118,	"edma lba3",
+	0x011C,	"edma cmdstat",
+	0x0120,	"edma altstat",
+*/
+};
+
+static char*
+rdregs(char *p, char *e, void *base, Regs *r, int n, char *prefix)
+{
+	int i;
+	
+	for(i=0; i<n; i++)
+		p = seprint(p, e, "%s%s%-19s %.8ux\n", 
+			prefix ? prefix : "", prefix ? ": " : "",
+			r[i].name, *(u32int*)((uchar*)base+r[i].offset));
+	return p;
+}
+
+static char*
+rdinfo(char *p, char *e, ushort *info)
+{
+	int i;
+	
+	p = seprint(p, e, "info");
+	for(i=0; i<256; i++){
+		p = seprint(p, e, "%s%.4ux%s", 
+			i%8==0 ? "\t" : "",
+			info[i], 
+			i%8==7 ? "\n" : "");
+	}
+	return p;
+}
+
+static int
+mv50rctl(SDunit *unit, char *p, int l)
+{
+	char *e, *op;
+	Ctlr *ctlr;
+	Drive *drive;
+	
+	if((ctlr = unit->dev->ctlr) == nil)
+		return 0;
+	drive = &ctlr->drive[unit->subno];
+	
+	e = p+l;
+	op = p;
+	if(drive->state == Dready){
+		p = seprint(p, e, "model    %s\n", drive->model);
+		p = seprint(p, e, "serial   %s\n", drive->serial);
+		p = seprint(p, e, "firmware %s\n", drive->firmware);
+	}else
+		p = seprint(p, e, "no disk present\n");
+	p = seprint(p, e, "geometry %llud 512\n", drive->sectors);
+	p = rdinfo(p, e, drive->info);
+	
+	p = rdregs(p, e, drive->chip->arb, regsarb, nelem(regsarb), nil);
+	p = rdregs(p, e, drive->bridge, regsbridge, nelem(regsbridge), nil);
+	p = rdregs(p, e, drive->edma, regsedma, nelem(regsedma), nil);
+
+	return p-op;
+}
+
+static int
+mv50wctl(SDunit *unit, Cmdbuf *cb)
+{
+	Ctlr *ctlr;
+	Drive *drive;
+	
+	USED(unit);
+	if(strcmp(cb->f[0], "reset") == 0){
+		ctlr = unit->dev->ctlr;
+		drive = &ctlr->drive[unit->subno];
+		ilock(drive);
+		updatedrive(drive, eDevDis);
+		iunlock(drive);
+		return 0;
+	}
+	cmderror(cb, Ebadctl);
+	return -1;
+}
+
+static char*
+mv50rtopctl(SDev *sdev, char *p, char *e)
+{
+	char name[10];
+	Ctlr *ctlr;
+	
+	ctlr = sdev->ctlr;
+	if(ctlr == nil)
+		return p;
+
+	snprint(name, sizeof name, "sd%c", sdev->idno);
+	p = rdregs(p, e, ctlr->mmio, regsctlr, nelem(regsctlr), name);
+	/* info for first disk */
+	p = rdregs(p, e, ctlr->chip[0].arb, regsarb, nelem(regsarb), name);
+	p = rdregs(p, e, &ctlr->chip[0].arb->bridge[0], regsbridge, nelem(regsbridge), name);
+	p = rdregs(p, e, &ctlr->chip[0].edma[0], regsedma, nelem(regsedma), name);
+	
+	return p;
+}
+
+static int
+mv50rio(SDreq *r)
+{
+	int count, max, n, status;
+	uchar *cmd, *data;
+	uvlong lba;
+	Ctlr *ctlr;
+	Drive *drive;
+	SDunit *unit;
+	Srb *srb;
+	
+	unit = r->unit;
+	ctlr = unit->dev->ctlr;
+	drive = &ctlr->drive[unit->subno];
+	cmd = r->cmd;
+	
+	if((status = sdfakescsi(r, drive->info, sizeof drive->info)) != SDnostatus){
+		/* XXX check for SDcheck here */
+		r->status = status;
+		return status;
+	}
+
+	switch(cmd[0]){
+	case 0x28:	/* read */
+	case 0x2A:	/* write */
+		break;
+	default:
+		print("sdmv50xx: bad cmd 0x%.2ux\n", cmd[0]);
+		r->status = SDcheck;
+		return SDcheck;
+	}
+	
+	lba = (cmd[2]<<24)|(cmd[3]<<16)|(cmd[4]<<8)|cmd[5];
+	count = (cmd[7]<<8)|cmd[8];
+	if(r->data == nil)
+		return SDok;
+	if(r->dlen < count*unit->secsize)
+		count = r->dlen/unit->secsize;
+	
+	/* 
+	 * Could arrange here to have an Srb always outstanding:
+	 *
+	 *	lsrb = nil;
+	 *	while(count > 0 || lsrb != nil){
+	 *		srb = nil;
+	 *		if(count > 0){
+	 *			srb = issue next srb;
+	 *		}
+	 *		if(lsrb){
+	 *			sleep on lsrb and handle it
+	 *		}
+	 *	}
+	 *
+	 * On the disks I tried, this didn't help.  If anything,
+	 * it's a little slower.		-rsc
+	 */
+	data = r->data;
+	while(count > 0){
+		/*
+		 * Max is 128 sectors (64kB) because prd->count is 16 bits.
+		 */
+		max = 128;
+		n = count;
+		if(n > max)
+			n = max;
+		srb = srbrw(cmd[0]==0x28 ? SRBread : SRBwrite, drive, data, n, lba);
+		ilock(drive);
+		startsrb(drive, srb);
+		iunlock(drive);
+
+		/*
+		 * Cannot let user interrupt the DMA.
+		 */
+		while(waserror())
+			;
+		tsleep(srb, srbdone, srb, 60*1000);
+		poperror();
+		
+		if(!(srb->flag & SFdone)){
+			ilock(drive);
+			if(!(srb->flag & SFdone)){
+				/*
+				 * DMA didn't finish but we have to let go of
+				 * the data buffer.  Reset the drive to (try to) keep it
+				 * from using the buffer after we're gone.
+				 */
+				iprint("%s: i/o timeout\n", unit->name);
+				updatedrive(drive, eDevDis);
+				enabledrive(drive);
+				freesrb(srb);
+				iunlock(drive);
+				error("i/o timeout");
+			}
+			iunlock(drive);
+		}
+
+		if(srb->flag & SFerror){
+			freesrb(srb);
+			error("i/o error");
+		}
+		freesrb(srb);
+		count -= n;
+		lba += n;
+		data += n*unit->secsize;
+	}
+	r->rlen = data - (uchar*)r->data;
+	return SDok;	
+}
+
+SDifc sdmv50xxifc = {
+	"mv50xx",				/* name */
+
+	mv50pnp,			/* pnp */
+	nil,				/* legacy */
+	mv50enable,		/* enable */
+	mv50disable,		/* disable */
+
+	mv50verify,			/* verify */
+	mv50online,			/* online */
+	mv50rio,				/* rio */
+	mv50rctl,			/* rctl */
+	mv50wctl,			/* wctl */
+
+	scsibio,			/* bio */
+	nil,			/* probe */
+	mv50clear,			/* clear */
+	mv50rtopctl,			/* rtopctl */
+};
+
+/*
+ * The original driver on which this one is based came with the 
+ * following notice:
+ *
+ * Copyright 2005
+ * Coraid, Inc.
+ *
+ * This software is provided `as-is,' without any express or implied
+ * warranty.  In no event will the author be held liable for any damages
+ * arising from the use of this software.
+ * 
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ * 
+ * 1.  The origin of this software must not be misrepresented; you must
+ * not claim that you wrote the original software.  If you use this
+ * software in a product, an acknowledgment in the product documentation
+ * would be appreciated but is not required.
+ * 
+ * 2.  Altered source versions must be plainly marked as such, and must
+ * not be misrepresented as being the original software.
+ * 
+ * 3.  This notice may not be removed or altered from any source
+ * distribution.
+ */

+ 1 - 7
sys/src/9/pc/sdmylex.c

@@ -1012,6 +1012,7 @@ buggery:
 		goto buggery;
 	sdev->ifc = &sdmylexifc;
 	sdev->ctlr = ctlr;
+	sdev->idno = '0';
 	ctlr->sdev = sdev;
 	if(!ctlr->wide)
 		sdev->nunit = 8;
@@ -1089,12 +1090,6 @@ mylexpnp(void)
 	return head;
 }
 
-static SDev*
-mylexid(SDev* sdev)
-{
-	return scsiid(sdev, &sdmylexifc);
-}
-
 static int
 mylex24enable(Ctlr* ctlr)
 {
@@ -1232,7 +1227,6 @@ SDifc sdmylexifc = {
 
 	mylexpnp,			/* pnp */
 	nil,				/* legacy */
-	mylexid,			/* id */
 	mylexenable,			/* enable */
 	nil,				/* disable */
 

+ 0 - 20
sys/src/9/pc/sdscsi.c

@@ -372,23 +372,3 @@ again:
 	return rlen;
 }
 
-SDev*
-scsiid(SDev* sdev, SDifc* ifc)
-{
-	char name[32];
-	static char idno[16] = "0123456789abcdef";
-	static char *p = idno;
-
-	while(sdev){
-		if(sdev->ifc == ifc){
-			sdev->idno = *p++;
-			snprint(name, sizeof(name), "sd%c", sdev->idno);
-			kstrdup(&sdev->name, name);
-			if(p >= &idno[sizeof(idno)])
-				break;
-		}
-		sdev = sdev->next;
-	}
-
-	return nil;
-}

+ 39 - 10
sys/src/9/pc/trap.c

@@ -9,6 +9,8 @@
 #include	"../port/error.h"
 #include	<trace.h>
 
+static int trapinited;
+
 void	noted(Ureg*, ulong);
 
 static void debugbpt(Ureg*, void*);
@@ -175,8 +177,13 @@ nmienable(void)
 	outb(0x61, x);
 }
 
+/*
+ * Minimal trap setup.  Just enough so that we can panic
+ * on traps (bugs) during kernel initialization.  
+ * Called very early - malloc is not yet available.
+ */
 void
-trapinit(void)
+trapinit0(void)
 {
 	int d1, v;
 	ulong vaddr;
@@ -204,7 +211,11 @@ trapinit(void)
 		idt[v].d1 = d1;
 		vaddr += 6;
 	}
+}
 
+void
+trapinit(void)
+{
 	/*
 	 * Special traps.
 	 * Syscall() is called directly without going through trap().
@@ -216,6 +227,7 @@ trapinit(void)
 	nmienable();
 
 	addarchfile("irqalloc", 0444, irqallocread, nil);
+	trapinited = 1;
 }
 
 static char* excname[32] = {
@@ -306,6 +318,13 @@ trap(Ureg* ureg)
 	Vctl *ctl, *v;
 	Mach *mach;
 
+	if(!trapinited){
+		/* fault386 can give a better error message */
+		if(ureg->trap == VectorPF)
+			fault386(ureg, nil);
+		panic("trap %lud: not ready", ureg->trap);
+	}
+
 	m->perf.intrts = perfticks();
 	user = (ureg->cs & 0xFFFF) == UESEL;
 	if(user){
@@ -507,7 +526,7 @@ _dumpstack(Ureg *ureg)
 	iprint("dumpstack\n");
 
 	x = 0;
-	x += print("ktrace /kernel/path %.8lux %.8lux\n", ureg->pc, ureg->sp);
+	x += print("ktrace /kernel/path %.8lux %.8lux <<EOF\n", ureg->pc, ureg->sp);
 	i = 0;
 	if(up
 	&& (ulong)&l >= (ulong)up->kstack
@@ -522,7 +541,7 @@ _dumpstack(Ureg *ureg)
 
 	for(l=(ulong)&l; l<estack; l+=4){
 		v = *(ulong*)l;
-		if((KTZERO < v && v < (ulong)&etext) || estack-l<256){
+		if((KTZERO < v && v < (ulong)&etext) || estack-l<32){
 			/*
 			 * we could Pick off general CALL (((uchar*)v)[-5] == 0xE8)
 			 * and CALL indirect through AX (((uchar*)v)[-2] == 0xFF && ((uchar*)v)[-2] == 0xD0),
@@ -538,6 +557,7 @@ _dumpstack(Ureg *ureg)
 	}
 	if(i)
 		print("\n");
+	print("EOF\n");
 }
 
 void
@@ -571,8 +591,6 @@ unexpected(Ureg* ureg, void*)
 	print("unexpected trap %lud; ignoring\n", ureg->trap);
 }
 
-extern void checkpages(void);
-
 static void
 fault386(Ureg* ureg, void*)
 {
@@ -581,12 +599,20 @@ fault386(Ureg* ureg, void*)
 	char buf[ERRMAX];
 
 	addr = getcr2();
-	user = (ureg->cs & 0xFFFF) == UESEL;
-	if(!user && mmukmapsync(addr))
-		return;
 	read = !(ureg->ecode & 2);
+
+	user = (ureg->cs & 0xFFFF) == UESEL;
+	if(!user){
+		if(vmapsync(addr))
+			return;
+		if(addr >= USTKTOP)
+			panic("kernel fault: bad address pc=0x%.8lux addr=0x%.8lux", ureg->pc, addr);
+		if(up == nil)
+			panic("kernel fault: no user process pc=0x%.8lux addr=0x%.8lux", ureg->pc, addr);
+	}
 	if(up == nil)
-		panic("fault but up is zero; pc 0x%8.8lux addr 0x%8.8lux\n", ureg->pc, addr);
+		panic("user fault: up=0 pc=0x%.8lux addr=0x%.8lux", ureg->pc, addr);
+
 	insyscall = up->insyscall;
 	up->insyscall = 1;
 	n = fault(addr, read);
@@ -597,7 +623,7 @@ fault386(Ureg* ureg, void*)
 		}
 		checkpages();
 		sprint(buf, "sys: trap: fault %s addr=0x%lux",
-			read? "read" : "write", addr);
+			read ? "read" : "write", addr);
 		postnote(up, 1, buf, NDebug);
 	}
 	up->insyscall = insyscall;
@@ -888,6 +914,9 @@ execregs(ulong entry, ulong ssize, ulong nargs)
 	ulong *sp;
 	Ureg *ureg;
 
+	up->fpstate = FPinit;
+	fpoff();
+
 	sp = (ulong*)(USTKTOP - ssize);
 	*--sp = nargs;
 

+ 12 - 3
sys/src/9/pc/vga.c

@@ -3,6 +3,7 @@
 #include "mem.h"
 #include "dat.h"
 #include "fns.h"
+#include "io.h"
 #include "../port/error.h"
 
 #define	Image	IMAGE
@@ -18,7 +19,7 @@ static Point curpos;
 static Rectangle window;
 static int *xp;
 static int xbuf[256];
-static Lock vgascreenlock;
+Lock vgascreenlock;
 int drawdebug;
 
 void
@@ -136,7 +137,7 @@ vgascreenputc(VGAscr* scr, char* buf, Rectangle *flushr)
 static void
 vgascreenputs(char* s, int n)
 {
-	int i;
+	int i, gotdraw;
 	Rune r;
 	char buf[4];
 	VGAscr *scr;
@@ -155,6 +156,12 @@ vgascreenputs(char* s, int n)
 	else
 		lock(&vgascreenlock);
 
+	/*
+	 * Be nice to hold this, but not going to deadlock
+	 * waiting for it.  Just try and see.
+	 */
+	gotdraw = canqlock(&drawlock);
+
 	flushr = Rect(10000, 10000, -10000, -10000);
 
 	while(n > 0){
@@ -172,6 +179,8 @@ vgascreenputs(char* s, int n)
 	}
 	flushmemscreen(flushr);
 
+	if(gotdraw)
+		qunlock(&drawlock);
 	unlock(&vgascreenlock);
 }
 
@@ -241,7 +250,7 @@ cornerstring(char *s)
 	Point p;
 
 	scr = &vgascreen[0];
-	if(scr->aperture == 0 || screenputs != vgascreenputs)
+	if(scr->vaddr == nil || screenputs != vgascreenputs)
 		return;
 	p = memsubfontwidth(scr->memdefont, s);
 	w = p.x;

+ 23 - 80
sys/src/9/pc/vga3dfx.c

@@ -28,66 +28,13 @@ enum {
 	hwCur		= 0x5C,
 };
 
-static ulong
-tdfxlinear(VGAscr* scr, int* size, int* align)
-{
-	Pcidev *p;
-	int oapsize, wasupamem;
-	ulong aperture, oaperture;
-
-	oaperture = scr->aperture;
-	oapsize = scr->apsize;
-	wasupamem = scr->isupamem;
-
-	aperture = 0;
-	if(p = pcimatch(nil, 0x121A, 0)){
-		switch(p->did){
-		case 0x0003:		/* Banshee */
-		case 0x0005:		/* Avenger (a.k.a. Voodoo3) */
-		case 0x0009:		/* Voodoo5 */
-			aperture = p->mem[1].bar & ~0x0F;
-			*size = p->mem[1].size;
-			break;
-		default:
-			break;
-		}
-	}
-
-	if(wasupamem){
-		if(oaperture == aperture)
-			return oaperture;
-		upafree(oaperture, oapsize);
-	}
-	scr->isupamem = 0;
-
-	aperture = upamalloc(aperture, *size, *align);
-	if(aperture == 0){
-		if(wasupamem && upamalloc(oaperture, oapsize, 0)){
-			aperture = oaperture;
-			scr->isupamem = 1;
-		}
-		else
-			scr->isupamem = 0;
-	}
-	else
-		scr->isupamem = 1;
-
-	return aperture;
-}
-
 static void
 tdfxenable(VGAscr* scr)
 {
 	Pcidev *p;
-	ulong aperture;
-	int align, i, *mmio, size;
+	int i, *mmio;
 
-	/*
-	 * Only once, can't be disabled for now.
-	 * scr->io holds the physical address of
-	 * the MMIO registers.
-	 */
-	if(scr->io)
+	if(scr->mmio)
 		return;
 	if(p = pcimatch(nil, 0x121A, 0)){
 		switch(p->did){
@@ -100,20 +47,16 @@ tdfxenable(VGAscr* scr)
 	}
 	else
 		return;
-	scr->io = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
-	if(scr->io == 0)
+	
+	scr->mmio = vmap(p->mem[0].bar&~0x0F, p->mem[0].size);
+	if(scr->mmio == nil)
 		return;
-
-	addvgaseg("3dfxmmio", (ulong)scr->io, p->mem[0].size);
-
-	size = p->mem[1].size;
-	align = 0;
-	aperture = tdfxlinear(scr, &size, &align);
-	if(aperture){
-		scr->aperture = aperture;
-		scr->apsize = size;
-		addvgaseg("3dfxscreen", aperture, size);
-	}
+	scr->pci = p;
+	
+	addvgaseg("3dfxmmio", p->mem[0].bar&~0x0F, p->mem[0].size);
+	vgalinearpci(scr);
+	if(scr->apsize)
+		addvgaseg("3dfxscreen", scr->paddr, scr->apsize);
 
 	/*
 	 * Find a place for the cursor data in display memory.
@@ -123,7 +66,7 @@ tdfxenable(VGAscr* scr)
 	 * 8 of them.
 	 * Use the last 1KB of the framebuffer.
 	 */
-	mmio = KADDR(scr->io + dramInit0);
+	mmio = (void*)((uchar*)scr->mmio+dramInit0);
 	if(*(mmio+1) & 0x40000000)
 		i = 16*1024*1024;
 	else{
@@ -144,9 +87,9 @@ tdfxcurdisable(VGAscr* scr)
 {
 	Cursor3dfx *cursor3dfx;
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
-	cursor3dfx = KADDR(scr->io+hwCur);
+	cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
 	cursor3dfx->vidProcCfg &= ~0x08000000;
 }
 
@@ -157,9 +100,9 @@ tdfxcurload(VGAscr* scr, Cursor* curs)
 	uchar *p;
 	Cursor3dfx *cursor3dfx;
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
-	cursor3dfx = KADDR(scr->io+hwCur);
+	cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
 
 	/*
 	 * Disable the cursor then load the new image in
@@ -177,7 +120,7 @@ tdfxcurload(VGAscr* scr, Cursor* curs)
 	 * transparent.
 	 */
 	cursor3dfx->vidProcCfg &= ~0x08000000;
-	p = KADDR(scr->aperture + scr->storage);
+	p = (uchar*)scr->vaddr + scr->storage;
 	for(y = 0; y < 16; y++){
 		*p++ = curs->clr[2*y]|curs->set[2*y];
 		*p++ = curs->clr[2*y+1]|curs->set[2*y+1];
@@ -201,9 +144,9 @@ tdfxcurmove(VGAscr* scr, Point p)
 {
 	Cursor3dfx *cursor3dfx;
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return 1;
-	cursor3dfx = KADDR(scr->io+hwCur);
+	cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
 
 	cursor3dfx->hwCurLoc = ((p.y+scr->offset.y)<<16)|(p.x+scr->offset.x);
 
@@ -216,9 +159,9 @@ tdfxcurenable(VGAscr* scr)
 	Cursor3dfx *cursor3dfx;
 
 	tdfxenable(scr);
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
-	cursor3dfx = KADDR(scr->io+hwCur);
+	cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
 
 	/*
 	 * Cursor colours.
@@ -230,7 +173,7 @@ tdfxcurenable(VGAscr* scr)
 	 * Initialise the 64x64 cursor to be transparent (X11 mode).
 	 */
 	cursor3dfx->hwCurPatAddr = scr->storage;
-	memset(KADDR(scr->aperture + scr->storage), 0, 64*16);
+	memset((uchar*)scr->vaddr + scr->storage, 0, 64*16);
 
 	/*
 	 * Load, locate and enable the 64x64 cursor in X11 mode.
@@ -246,7 +189,7 @@ VGAdev vga3dfxdev = {
 	tdfxenable,
 	nil,
 	nil,
-	tdfxlinear,
+	nil,
 };
 
 VGAcur vga3dfxcur = {

+ 2 - 1
sys/src/9/pc/vgaark2000pv.c

@@ -3,6 +3,7 @@
 #include "mem.h"
 #include "dat.h"
 #include "fns.h"
+#include "io.h"
 #include "../port/error.h"
 
 #define	Image	IMAGE
@@ -90,7 +91,7 @@ ark2000pvload(VGAscr* scr, Cursor* curs)
 	 */
 	seq10 = vgaxi(Seqx, 0x10);
 	opage = 0;
-	p = KADDR(scr->aperture);
+	p = scr->vaddr;
 	if(!(seq10 & 0x10)){
 		lock(&scr->devlock);
 		opage = ark2000pvpageset(scr, scr->storage>>16);

+ 1 - 0
sys/src/9/pc/vgabt485.c

@@ -3,6 +3,7 @@
 #include "mem.h"
 #include "dat.h"
 #include "fns.h"
+#include "io.h"
 #include "../port/error.h"
 
 #define	Image	IMAGE

+ 4 - 30
sys/src/9/pc/vgaclgd542x.c

@@ -41,36 +41,10 @@ clgd542xpage(VGAscr* scr, int page)
 	unlock(&scr->devlock);
 }
 
-static ulong
-clgd542xlinear(VGAscr* scr, int* size, int* align)
+static void
+clgd542xlinear(VGAscr* scr, int, int)
 {
-	ulong aperture, oaperture;
-	int oapsize, wasupamem;
-	Pcidev *p;
-
-	oaperture = scr->aperture;
-	oapsize = scr->apsize;
-	wasupamem = scr->isupamem;
-	if(wasupamem)
-		upafree(oaperture, oapsize);
-	scr->isupamem = 0;
-
-	if(p = pcimatch(nil, 0x1013, 0)){
-		aperture = p->mem[0].bar & ~0x0F;
-		*size = p->mem[0].size;
-	}
-	else
-		aperture = 0;
-
-	aperture = upamalloc(aperture, *size, *align);
-	if(aperture == 0){
-		if(wasupamem && upamalloc(oaperture, oapsize, 0))
-			scr->isupamem = 1;
-	}
-	else
-		scr->isupamem = 1;
-
-	return aperture;
+	vgalinearpciid(scr, 0x1013, 0);
 }
 
 static void
@@ -171,7 +145,7 @@ clgd542xinitcursor(VGAscr* scr, int xo, int yo, int index)
 	 */
 	seq07 = vgaxi(Seqx, 0x07);
 	opage = 0;
-	p = KADDR(scr->aperture);
+	p = scr->vaddr;
 	if(!(seq07 & 0xF0)){
 		lock(&scr->devlock);
 		opage = clgd542xpageset(scr, scr->storage>>16);

+ 29 - 87
sys/src/9/pc/vgaclgd546x.c

@@ -26,93 +26,35 @@ enum {
 	CursorMMIO	= 0xE0,
 };
 
-static ulong
-clgd546xlinear(VGAscr* scr, int* size, int* align)
+static void
+clgd546xlinear(VGAscr* scr, int, int)
 {
-	ulong aperture, oaperture;
-	int oapsize, wasupamem;
-	Pcidev *p;
-
-	oaperture = scr->aperture;
-	oapsize = scr->apsize;
-	wasupamem = scr->isupamem;
-
-	aperture = 0;
-	if(p = pcimatch(nil, 0x1013, 0)){
-		switch(p->did){
-		case 0xD0:
-		case 0xD4:
-		case 0xD6:
-			aperture = p->mem[0].bar & ~0x0F;
-			*size = p->mem[0].size;
-			break;
-		default:
-			break;
-		}
-	}
-
-	if(wasupamem){
-		if(oaperture == aperture)
-			return oaperture;
-		upafree(oaperture, oapsize);
-	}
-	scr->isupamem = 0;
-
-	aperture = upamalloc(aperture, *size, *align);
-	if(aperture == 0){
-		if(wasupamem && upamalloc(oaperture, oapsize, 0)){
-			aperture = oaperture;
-			scr->isupamem = 1;
-		}
-		else
-			scr->isupamem = 0;
-	}
-	else
-		scr->isupamem = 1;
-
-	return aperture;
+	vgalinearpci(scr);
 }
+
 static void
 clgd546xenable(VGAscr* scr)
 {
 	Pcidev *p;
-	int size, align;
-	ulong aperture;
 
-	/*
-	 * Only once, can't be disabled for now.
-	 * scr->io holds the virtual address of
-	 * the MMIO registers.
-	 */
-	if(scr->io)
+	if(scr->mmio)
 		return;
-	if(p = pcimatch(nil, 0x1013, 0)){
-		switch(p->did){
-		case 0xD0:
-		case 0xD4:
-		case 0xD6:
-			break;
-		default:
-			return;
-		}
-	}
-	else
+	if((p = pcimatch(nil, 0x1013, 0)) == nil)
 		return;
-	scr->io = upamalloc(p->mem[1].bar & ~0x0F, p->mem[1].size, 0);
-	if(scr->io == 0)
+	switch(p->did){
+	case 0xD0:
+	case 0xD4:
+	case 0xD6:
+		break;
+	default:
 		return;
-	addvgaseg("clgd546xmmio", scr->io, p->mem[1].size);
-
-	scr->io = (ulong)KADDR(scr->io);
-
-	size = p->mem[0].size;
-	align = 0;
-	aperture = clgd546xlinear(scr, &size, &align);
-	if(aperture) {
-		scr->aperture = aperture;
-		scr->apsize = size;
-		addvgaseg("clgd546xscreen", aperture, size);
 	}
+
+	scr->pci = p;
+	scr->mmio = vmap(p->mem[1].bar&~0x0F, p->mem[1].size);
+	if(scr->mmio == 0)
+		return;
+	addvgaseg("clgd546xmmio", p->mem[1].bar&~0x0F, p->mem[1].size);
 }
 
 static void
@@ -120,9 +62,9 @@ clgd546xcurdisable(VGAscr* scr)
 {
 	Cursor546x *cursor546x;
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
-	cursor546x = (Cursor546x*)(scr->io+CursorMMIO);
+	cursor546x = (Cursor546x*)((uchar*)scr->mmio+CursorMMIO);
 	cursor546x->enable = 0;
 }
 
@@ -133,16 +75,16 @@ clgd546xcurload(VGAscr* scr, Cursor* curs)
 	uchar *p;
 	Cursor546x *cursor546x;
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
-	cursor546x = (Cursor546x*)(scr->io+CursorMMIO);
+	cursor546x = (Cursor546x*)((uchar*)scr->mmio+CursorMMIO);
 
 	/*
 	 * Disable the cursor then change only the bits
 	 * that need it.
 	 */
 	cursor546x->enable = 0;
-	p = (uchar*)(scr->aperture + scr->storage);
+	p = (uchar*)scr->vaddr + scr->storage;
 	for(y = 0; y < 16; y++){
 		c = curs->set[2*y];
 		m = 0;
@@ -189,9 +131,9 @@ clgd546xcurmove(VGAscr* scr, Point p)
 	int x, xo, y, yo;
 	Cursor546x *cursor546x;
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return 1;
-	cursor546x = (Cursor546x*)(scr->io+CursorMMIO);
+	cursor546x = (Cursor546x*)((uchar*)scr->mmio+CursorMMIO);
 
 	if((x = p.x+scr->offset.x) < 0){
 		xo = -x;
@@ -220,15 +162,15 @@ clgd546xcurenable(VGAscr* scr)
 	Cursor546x *cursor546x;
 
 	clgd546xenable(scr);
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
-	cursor546x = (Cursor546x*)(scr->io+CursorMMIO);
+	cursor546x = (Cursor546x*)((uchar*)scr->mmio+CursorMMIO);
 
 	/*
 	 * Cursor colours.
 	 * Can't call setcolor here as cursor is already locked.
 	 */
-	p = (uchar*)(scr->io+PaletteState);
+	p = (uchar*)scr->mmio+PaletteState;
 	*p |= 0x08;
 	vgao(PaddrW, 0x00);
 	vgao(Pdata, Pwhite);
@@ -248,7 +190,7 @@ clgd546xcurenable(VGAscr* scr)
 	 */
 	scr->storage = ((vgaxi(Seqx, 0x14) & 0x07)+1)*1024*1022;
 	cursor546x->addr = (scr->storage>>10)<<2;
-	memset((uchar*)(scr->aperture + scr->storage), 0, 2*64*16);
+	memset((uchar*)scr->vaddr + scr->storage, 0, 2*64*16);
 
 	/*
 	 * Load, locate and enable the 64x64 cursor.

+ 2 - 1
sys/src/9/pc/vgact65545.c

@@ -3,6 +3,7 @@
 #include "mem.h"
 #include "dat.h"
 #include "fns.h"
+#include "io.h"
 #include "../port/error.h"
 
 #define	Image	IMAGE
@@ -52,7 +53,7 @@ ct65545initcursor(VGAscr* scr, int xo, int yo, int index)
 	uint and, clr, set, xor;
 	int i, x, y;
 
-	mem = KADDR(scr->aperture);
+	mem = scr->vaddr;
 	mem += scr->storage + index*1024;
 
 	for(y = yo; y < 16; y++){

+ 17 - 39
sys/src/9/pc/vgacyber938x.c

@@ -38,50 +38,28 @@ cyber938xpage(VGAscr* scr, int page)
 	unlock(&scr->devlock);
 }
 
-static ulong
-cyber938xlinear(VGAscr* scr, int* size, int* align)
+static void
+cyber938xlinear(VGAscr* scr, int, int)
 {
-	ulong aperture, oaperture;
-	int oapsize, wasupamem;
-	int osize;
 	Pcidev *p;
 
-	osize = *size;
-	oaperture = scr->aperture;
-	oapsize = scr->apsize;
-	wasupamem = scr->isupamem;
-	if(wasupamem)
-		upafree(oaperture, oapsize);
-	scr->isupamem = 0;
-	scr->mmio = 0;
-
-	if(p = pcimatch(nil, 0x1023, 0)){
-		aperture = p->mem[0].bar & ~0x0F;
-		*size = p->mem[0].size;
-		/*
-		 * Heuristic to detect the MMIO space.  We're flying blind
-		 * here, with only the XFree86 source to guide us.
-		 */
-		if(p->mem[1].size == 0x20000)
-			scr->mmio = (ulong*)(p->mem[1].bar & ~0x0F);
-	}
-	else
-		aperture = 0;
+	if(scr->vaddr)
+		return;
+	
+	vgalinearpciid(scr, 0x1023, 0);
+	p = scr->pci;
 
-	aperture = upamalloc(aperture, *size, *align);
-	if(aperture == 0){
-		if(wasupamem && upamalloc(oaperture, oapsize, 0))
-			scr->isupamem = 1;
-	}
-	else
-		scr->isupamem = 1;
+	/*
+	 * Heuristic to detect the MMIO space.  We're flying blind
+	 * here, with only the XFree86 source to guide us.
+	 */
+	if(p->mem[1].size == 0x20000)
+		scr->mmio = vmap(p->mem[1].bar & ~0x0F, p->mem[1].size);
 
-	if(aperture)
-		addvgaseg("cyber938xscreen", aperture, osize);
+	if(scr->apsize)
+		addvgaseg("cyber938xscreen", scr->paddr, scr->apsize);
 	if(scr->mmio)
-		addvgaseg("cyber938xmmio", (ulong)scr->mmio, 0x20000);
-
-	return aperture;
+		addvgaseg("cyber938xmmio", p->mem[1].bar&~0x0F, 0x20000);
 }
 
 static void
@@ -99,7 +77,7 @@ cyber938xcurload(VGAscr* scr, Cursor* curs)
 	cyber938xcurdisable(scr);
 
 	opage = 0;
-	p = KADDR(scr->aperture);
+	p = scr->vaddr;
 	islinear = vgaxi(Crtx, 0x21) & 0x20;
 	if(!islinear){
 		lock(&scr->devlock);

+ 2 - 1
sys/src/9/pc/vgaet4000.c

@@ -3,6 +3,7 @@
 #include "mem.h"
 #include "dat.h"
 #include "fns.h"
+#include "io.h"
 #include "../port/error.h"
 
 #define	Image	IMAGE
@@ -139,7 +140,7 @@ et4000load(VGAscr *scr, Cursor *c)
 	et4000disable(scr);
 
 	setet4000page(scr->storage>>16);
-	mem = (uchar*)KADDR(scr->aperture) + (scr->storage & 0xFFFF);
+	mem = (uchar*)scr->vaddr + (scr->storage & 0xFFFF);
 
 	/*
 	 * Initialise the 64x64 cursor RAM array. There are 2 planes,

+ 15 - 61
sys/src/9/pc/vgahiqvideo.c

@@ -34,65 +34,21 @@ hiqvideoxo(long port, uchar index, uchar data)
 	outb(port+1, data);
 }
 
-static ulong
-hiqvideolinear(VGAscr* scr, int* size, int* align)
+static void
+hiqvideolinear(VGAscr*, int, int)
 {
-	ulong aperture, oaperture;
-	int oapsize, wasupamem;
-	Pcidev *p;
-
-	oaperture = scr->aperture;
-	oapsize = scr->apsize;
-	wasupamem = scr->isupamem;
-
-	aperture = 0;
-	if(p = pcimatch(nil, 0x102C, 0)){
-		switch(p->did){
-		case 0x00C0:		/* 69000 HiQVideo */
-		case 0x00E0:		/* 65550 HiQV32 */
-		case 0x00E4:		/* 65554 HiQV32 */
-		case 0x00E5:		/* 65555 HiQV32 */
-			aperture = p->mem[0].bar & ~0x0F;
-			*size = p->mem[0].size;
-			break;
-		default:
-			break;
-		}
-	}
-
-	if(wasupamem){
-		if(oaperture == aperture)
-			return oaperture;
-		upafree(oaperture, oapsize);
-	}
-	scr->isupamem = 0;
-
-	aperture = upamalloc(aperture, *size, *align);
-	if(aperture == 0){
-		if(wasupamem && upamalloc(oaperture, oapsize, 0)){
-			aperture = oaperture;
-			scr->isupamem = 1;
-		}
-		else
-			scr->isupamem = 0;
-	}
-	else
-		scr->isupamem = 1;
-
-	return aperture;
 }
 
 static void
 hiqvideoenable(VGAscr* scr)
 {
 	Pcidev *p;
-	int align, size, vmsize;
-	ulong aperture;
+	int vmsize;
 
 	/*
 	 * Only once, can't be disabled for now.
 	 */
-	if(scr->io)
+	if(scr->mmio)
 		return;
 	if(p = pcimatch(nil, 0x102C, 0)){
 		switch(p->did){
@@ -119,23 +75,21 @@ hiqvideoenable(VGAscr* scr)
 	else
 		return;
 
-	size = p->mem[0].size;
-	align = 0;
-	aperture = hiqvideolinear(scr, &size, &align);
-	if(aperture) {
-		scr->aperture = aperture;
-		scr->apsize = size;
-		addvgaseg("hiqvideoscreen", aperture, size);
+	scr->pci = p;
+	vgalinearpci(scr);
+	
+	if(scr->paddr) {
+		addvgaseg("hiqvideoscreen", scr->paddr, scr->apsize);
 	}
 
 	/*
 	 * Find a place for the cursor data in display memory.
 	 * Must be on a 4096-byte boundary.
-	 * scr->io holds the physical address of the cursor
+	 * scr->mmio holds the virtual address of the cursor
 	 * storage area in the framebuffer region.
 	 */
 	scr->storage = vmsize-4096;
-	scr->io = scr->aperture+scr->storage;
+	scr->mmio = (ulong*)((uchar*)scr->vaddr+scr->storage);
 }
 
 static void
@@ -155,9 +109,9 @@ hiqvideocurload(VGAscr* scr, Cursor* curs)
 	 */
 	hiqvideocurdisable(scr);
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
-	p = KADDR(scr->io);
+	p = (uchar*)scr->mmio;
 
 	for(y = 0; y < 16; y += 2){
 		*p++ = ~(curs->clr[2*y]|curs->set[2*y]);
@@ -197,7 +151,7 @@ hiqvideocurmove(VGAscr* scr, Point p)
 {
 	int x, y;
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return 1;
 
 	if((x = p.x+scr->offset.x) < 0)
@@ -219,7 +173,7 @@ hiqvideocurenable(VGAscr* scr)
 	uchar xr80;
 
 	hiqvideoenable(scr);
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
 
 	/*

+ 38 - 88
sys/src/9/pc/vgai81x.c

@@ -49,94 +49,44 @@ i81xpcimatch(void)
 	return nil;
 }
 
-static ulong
-i81xlinear(VGAscr* scr, int* size, int* align)
-{
-	Pcidev *p;
-	int oapsize, wasupamem;
-	ulong aperture, oaperture, fbuf, fbend, *rp;
-
-	oaperture = scr->aperture;
-	oapsize = scr->apsize;
-	wasupamem = scr->isupamem;
-
-	aperture = 0;
-	p = i81xpcimatch();
-	if(p != nil) {
-		aperture = p->mem[0].bar & ~0x0F;
-		*size = p->mem[0].size;
-		if(*size > Fbsize)
-			*size = Fbsize;
-	}
-
-	if(wasupamem){
-		if(oaperture == aperture)
-			return oaperture;
-		upafree(oaperture, oapsize);
-	}
-	scr->isupamem = 0;
-
-	aperture = upamalloc(aperture, *size, *align);
-	if(aperture == 0){
-		if(wasupamem && upamalloc(oaperture, oapsize, 0)){
-			aperture = oaperture;
-			scr->isupamem = 1;
-		}
-		else
-			scr->isupamem = 0;
-	}
-	else
-		scr->isupamem = 1;
-
-	/* allocate space for frame buffer, populate page table */
-	if(oapsize == 0) {
-		fbuf = PADDR(xspanalloc(*size, BY2PG, 0));
-		fbend = PGROUND(fbuf+*size);
-		rp = KADDR(scr->io+0x10000);
-		while(fbuf < fbend) {
-			*rp++ = fbuf | (1<<0);
-			fbuf += BY2PG;
-		}
-	}
-	return aperture;
-}
-
 static void
 i81xenable(VGAscr* scr)
 {
 	Pcidev *p;
-	int align, size;
+	int size;
 	Mach *mach0;
-	ulong aperture, pgtbl, *rp, cursor, *pte;
-
-	/*
-	 * Only once, can't be disabled for now.
-	 * scr->io holds the physical address of
-	 * the MMIO registers.
-	 */
-	if(scr->io)
+	ulong *pgtbl, *rp, cursor, *pte, fbuf, fbend;
+	
+	if(scr->mmio)
 		return;
 	p = i81xpcimatch();
 	if(p == nil)
 		return;
-	scr->io = upamalloc(p->mem[1].bar & ~0x0F, p->mem[1].size, 0);
-	if(scr->io == 0)
+	scr->mmio = vmap(p->mem[1].bar & ~0x0F, p->mem[1].size);
+	if(scr->mmio == 0)
 		return;
+	addvgaseg("i81xmmio", p->mem[1].bar&~0x0F, p->mem[1].size);
 
 	/* allocate page table */
-	pgtbl = PADDR(xspanalloc(64*1024, BY2PG, 0));
-	rp = KADDR(scr->io+0x2020);
-	*rp = pgtbl | 1;
-
-	addvgaseg("i81xmmio", (ulong)scr->io, p->mem[0].size);
+	pgtbl = xspanalloc(64*1024, BY2PG, 0);
+	scr->mmio[0x2020/4] = PADDR(pgtbl) | 1;
 
 	size = p->mem[0].size;
-	align = 0;
-	aperture = i81xlinear(scr, &size, &align);
-	if(aperture){
-		scr->aperture = aperture;
-		scr->apsize = size;
-		addvgaseg("i81xscreen", aperture, size);
+	if(size > 0)
+		size = Fbsize;
+	vgalinearaddr(scr, p->mem[0].bar&~0xF, size);
+	addvgaseg("i81xscreen", p->mem[0].bar&~0xF, size);
+
+	/*
+	 * allocate backing store for frame buffer
+	 * and populate device page tables.
+	 */
+	fbuf = PADDR(xspanalloc(size, BY2PG, 0));
+	fbend = PGROUND(fbuf+size);
+	rp = scr->mmio+0x10000/4;
+	while(fbuf < fbend) {
+		*rp++ = fbuf | 1;
+		fbuf += BY2PG;
 	}
 
 	/*
@@ -147,9 +97,9 @@ i81xenable(VGAscr* scr)
 	mach0 = MACHP(0);
 	pte = mmuwalk(mach0->pdb, cursor, 2, 0);
 	if(pte == nil)
-		panic("i81x cursor");
+		panic("i81x cursor mmuwalk");
 	*pte |= PTEUNCACHED;
-	scr->storage = PADDR(cursor);
+	scr->storage = cursor;
 }
 
 static void
@@ -157,9 +107,9 @@ i81xcurdisable(VGAscr* scr)
 {
 	CursorI81x *hwcurs;
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
-	hwcurs = KADDR(scr->io+hwCur);
+	hwcurs = (void*)((uchar*)scr->mmio+hwCur);
 	hwcurs->ctl = (1<<4);
 }
 
@@ -170,9 +120,9 @@ i81xcurload(VGAscr* scr, Cursor* curs)
 	uchar *p;
 	CursorI81x *hwcurs;
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
-	hwcurs = KADDR(scr->io+hwCur);
+	hwcurs = (void*)((uchar*)scr->mmio+hwCur);
 
 	/*
 	 * Disable the cursor then load the new image in
@@ -181,7 +131,7 @@ i81xcurload(VGAscr* scr, Cursor* curs)
 	 * transparent.
 	 */
 	hwcurs->ctl = (1<<4);
-	p = KADDR(scr->storage);
+	p = (uchar*)scr->storage;
 	for(y = 0; y < 16; y += 2) {
 		*p++ = ~(curs->clr[2*y]|curs->set[2*y]);
 		*p++ = ~(curs->clr[2*y+1]|curs->set[2*y+1]);
@@ -213,9 +163,9 @@ i81xcurmove(VGAscr* scr, Point p)
 	ulong pos;
 	CursorI81x *hwcurs;
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return 1;
-	hwcurs = KADDR(scr->io+hwCur);
+	hwcurs = (void*)((uchar*)scr->mmio+hwCur);
 
 	x = p.x+scr->offset.x;
 	y = p.y+scr->offset.y;
@@ -242,15 +192,15 @@ i81xcurenable(VGAscr* scr)
 	CursorI81x *hwcurs;
 
 	i81xenable(scr);
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
-	hwcurs = KADDR(scr->io+hwCur);
+	hwcurs = (void*)((uchar*)scr->mmio+hwCur);
 
 	/*
 	 * Initialise the 32x32 cursor to be transparent in 2bpp mode.
 	 */
-	hwcurs->base = scr->storage;
-	p = KADDR(scr->storage);
+	hwcurs->base = PADDR(scr->storage);
+	p = (uchar*)scr->storage;
 	for(i = 0; i < 32/2; i++) {
 		memset(p, 0xff, 8);
 		memset(p+8, 0, 8);
@@ -269,7 +219,7 @@ VGAdev vgai81xdev = {
 	i81xenable,
 	nil,
 	nil,
-	i81xlinear,
+	nil,
 };
 
 VGAcur vgai81xcur = {

+ 13 - 53
sys/src/9/pc/vgamach64xx.c

@@ -168,13 +168,11 @@ mach64xxenable(VGAscr* scr)
 {
 	Pcidev *p;
 
-	/*
-	 * Only once, can't be disabled for now.
-	 */
 	if(scr->io)
 		return;
 	if(p = mach64xxpci()){
 		scr->id = p->did;
+		scr->pci = p;
 
 		/*
 		 * The CT doesn't always have the I/O base address
@@ -189,53 +187,15 @@ mach64xxenable(VGAscr* scr)
 	}
 }
 
-static ulong
-mach64xxlinear(VGAscr* scr, int* size, int* align)
+static void
+mach64xxlinear(VGAscr* scr, int size, int)
 {
-	ulong aperture, osize, oaperture;
-	int i, oapsize, wasupamem;
-	Pcidev *p;
-
-	osize = *size;
-	oaperture = scr->aperture;
-	oapsize = scr->apsize;
-	wasupamem = scr->isupamem;
-
-	if(p = mach64xxpci()){
-		for(i=0; i<nelem(p->mem); i++){
-			if(p->mem[i].size >= *size
-			&& ((p->mem[i].bar & ~0x0F) & (*align-1)) == 0)
-				break;
-		}
-		if(i >= nelem(p->mem)){
-			print("vgamach64xx: aperture not found\n");
-			return 0;
-		}
-		aperture = p->mem[i].bar & ~0x0F;
-		*size = p->mem[i].size;
-	}
-	else
-		aperture = 0;
-
-	if(wasupamem)
-		upafree(oaperture, oapsize);
-	scr->isupamem = 0;
-
-	aperture = upamalloc(aperture, *size, *align);
-	if(aperture == 0){
-		if(wasupamem && upamalloc(oaperture, oapsize, 0))
-			scr->isupamem = 1;
-	}
-	else
-		scr->isupamem = 1;
-
-	scr->mmio = KADDR(aperture+osize-0x400);
-	if(oaperture && oaperture != aperture)
-		print("warning (BUG): redefinition of aperture does not change mach64mmio segment\n");
-	addvgaseg("mach64mmio", aperture+osize-BY2PG, BY2PG);
-	addvgaseg("mach64screen", aperture, osize);
-
-	return aperture;
+	vgalinearpci(scr);
+	if(scr->paddr == 0)
+		return;
+	scr->mmio = (ulong*)((uchar*)scr->vaddr+size-1024);
+	addvgaseg("mach64mmio", scr->paddr+size-BY2PG, BY2PG);
+	addvgaseg("mach64screen", scr->paddr, scr->apsize);
 }
 
 enum {
@@ -474,7 +434,7 @@ mach64xxcurload(VGAscr* scr, Cursor* curs)
 	r = ior32(scr, GenTestCntl);
 	iow32(scr, GenTestCntl, r & ~0x80);
 
-	p = KADDR(scr->aperture);
+	p = scr->vaddr;
 	p += scr->storage;
 
 	/*
@@ -792,7 +752,7 @@ initengine(VGAscr *scr)
 	}
 
 	/* Get the base freq from the BIOS */
-	bios  = KADDR(0xC000);
+	bios  = kaddr(0xC000);
 	table = *(ushort *)(bios + 0x48);
 	table = *(ushort *)(bios + table + 0x10);
 	switch (*(ushort *)(bios + table + 0x08)) {
@@ -1120,7 +1080,7 @@ ovl_status(VGAscr *scr, Chan *, char **field)
 		   mach64revb? "yes": "no",
 		   mach64refclock);
 	pprint("%s: storage @%.8luX, aperture @%8.ulX, ovl buf @%.8ulX\n",
-		   scr->dev->name, scr->storage, scr->aperture,
+		   scr->dev->name, scr->storage, scr->paddr,
 		   mach64overlay);
 }
 	
@@ -1215,7 +1175,7 @@ mach64xxovlwrite(VGAscr *scr, void *a, int len, vlong offs)
 
 		_offs = (ulong)(offs % ovl_fib);
 		nb     = (_offs + len > ovl_fib)? ovl_fib - _offs: len;
-		memmove((uchar *)KADDR(scr->aperture + mach64overlay + _offs), 
+		memmove((uchar *)scr->vaddr + mach64overlay + _offs, 
 				  src, nb);
 		offs += nb;
 		src  += nb;

+ 22 - 73
sys/src/9/pc/vgamga2164w.c

@@ -42,82 +42,31 @@ mgapcimatch(void)
 	return p;
 }
 
-static ulong
-mga2164wlinear(VGAscr* scr, int* size, int* align)
-{
-	ulong aperture, oaperture;
-	int oapsize, wasupamem;
-	Pcidev *p;
-
-	oaperture = scr->aperture;
-	oapsize = scr->apsize;
-	wasupamem = scr->isupamem;
-
-	if(p = mgapcimatch()){
-		aperture = p->mem[p->did==MGA2064? 1 : 0].bar & ~0x0F;
-		*size = (p->did==MGA2064? 8 :16)*1024*1024;
-	}
-	else
-		aperture = 0;
-
-	if(wasupamem) {
-		if(oaperture == aperture)
-			return oaperture;
-		upafree(oaperture, oapsize);
-	}
-	scr->isupamem = 0;
-
-	aperture = upamalloc(aperture, *size, *align);
-	if(aperture == 0){
-		if(wasupamem && upamalloc(oaperture, oapsize, 0)) {
-			aperture = oaperture;
-			scr->isupamem = 1;
-		}
-		else
-			scr->isupamem = 0;
-	}
-	else
-		scr->isupamem = 1;
-
-	return aperture;
-}
-
 static void
 mga2164wenable(VGAscr* scr)
 {
 	Pcidev *p;
-	int size, align, immio;
-	ulong aperture;
 
-	/*
-	 * Only once, can't be disabled for now.
-	 * scr->io holds the virtual address of
-	 * the MMIO registers.
-	 */
-	if(scr->io)
+	if(scr->mmio)
 		return;
 
 	p = mgapcimatch();
 	if(p == nil)
 		return;
 
-	immio = p->did==MGA2064? 0 : 1;
-	scr->io = upamalloc(p->mem[immio].bar & ~0x0F, p->mem[immio].size, 0);
-	if(scr->io == 0)
-		return;
-	addvgaseg("mga2164wmmio", scr->io, p->mem[immio].size);
-
-	scr->io = (ulong)KADDR(scr->io);
-
-	/* need to map frame buffer here too, so vga can find memory size */
-	size = (p->did==MGA2064? 8 :16)*1024*1024;
-	align = 0;
-	aperture = mga2164wlinear(scr, &size, &align);
-	if(aperture) {
-		scr->aperture = aperture;
-		scr->apsize = size;
-		addvgaseg("mga2164wscreen", aperture, size);
+	if(p->did == MGA2064){
+		scr->mmio = vmap(p->mem[0].bar&~0x0F, p->mem[0].size);
+		if(scr->mmio == nil)
+			return;
+		vgalinearaddr(scr, p->mem[1].bar&~0x0F, 8*MB);
+	}else{
+		scr->mmio = vmap(p->mem[1].bar&~0x0F, p->mem[1].size);
+		if(scr->mmio == nil)
+			return;
+		vgalinearaddr(scr, p->mem[0].bar&~0x0F, 16*MB);
 	}
+	if(scr->paddr)
+		addvgaseg("mga2164wscreen", scr->paddr, scr->apsize);
 }
 
 enum {
@@ -142,9 +91,9 @@ tvp3026disable(VGAscr* scr)
 {
 	uchar *tvp3026;
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
-	tvp3026 = KADDR(scr->io+0x3C00);
+	tvp3026 = (uchar*)scr->mmio+0x3C00;
 
 	/*
 	 * Make sure cursor is off
@@ -161,9 +110,9 @@ tvp3026load(VGAscr* scr, Cursor* curs)
 	int x, y;
 	uchar *tvp3026;
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
-	tvp3026 = KADDR(scr->io+0x3C00);
+	tvp3026 = (uchar*)scr->mmio+0x3C00;
 
 	/*
 	 * Make sure cursor is off by initialising the cursor
@@ -223,9 +172,9 @@ tvp3026move(VGAscr* scr, Point p)
 	int x, y;
 	uchar *tvp3026;
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return 1;
-	tvp3026 = KADDR(scr->io+0x3C00);
+	tvp3026 = (uchar*)scr->mmio+0x3C00;
 
 	x = p.x+scr->offset.x;
 	y = p.y+scr->offset.y;
@@ -244,9 +193,9 @@ tvp3026enable(VGAscr* scr)
 	int i;
 	uchar *tvp3026;
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
-	tvp3026 = KADDR(scr->io+0x3C00);
+	tvp3026 = (uchar*)scr->mmio+0x3C00;
 
 	tvp3026disable(scr);
 
@@ -276,7 +225,7 @@ VGAdev vgamga2164wdev = {
 	mga2164wenable,			/* enable */
 	0,				/* disable */
 	0,				/* page */
-	mga2164wlinear,			/* linear */
+	0,				/* linear */
 };
 
 VGAcur vgamga2164wcur = {

+ 41 - 93
sys/src/9/pc/vgamga4xx.c

@@ -23,9 +23,6 @@ enum {
 	MGA4xx			= 0x0525,
 	MGA200			= 0x0521,
 
-	Kilo				= 1024,
-	Meg				= 1024*1024,
-
 	FCOL			= 0x1c24,
 	FXRIGHT			= 0x1cac,	
 	FXLEFT			= 0x1ca8,
@@ -91,59 +88,17 @@ mgapcimatch(void)
 	return p;
 }
 
-static ulong
-mga4xxlinear(VGAscr* scr, int* size, int* align)
-{
-	ulong 	aperture, oaperture;
-	int 		oapsize, wasupamem;
-	Pcidev *	p;
-
-	oaperture = scr->aperture;
-	oapsize = scr->apsize;
-	wasupamem = scr->isupamem;
-
-	if(p = mgapcimatch()){
-		aperture = p->mem[0].bar & ~0x0F;
-		if(p->did == MGA4xx)
-			*size = 32*Meg;
-		else
-			*size = 8*Meg;
-	}
-	else
-		aperture = 0;
-
-	if(wasupamem) {
-		if(oaperture == aperture)
-			return oaperture;
-		upafree(oaperture, oapsize);
-	}
-	scr->isupamem = 0;
-
-	aperture = upamalloc(aperture, *size, *align);
-	if(aperture == 0){
-		if(wasupamem && upamalloc(oaperture, oapsize, 0)) {
-			aperture = oaperture;
-			scr->isupamem = 1;
-		}
-		else
-			scr->isupamem = 0;
-	}
-	else
-		scr->isupamem = 1;
-
-	return aperture;
-}
 
 static void
 mgawrite8(VGAscr* scr, int index, uchar val)
 {
-	((uchar*)scr->io)[index] = val;
+	((uchar*)scr->mmio)[index] = val;
 }
 
 static uchar
 mgaread8(VGAscr* scr, int index)
 {
-	return ((uchar*)scr->io)[index];
+	return ((uchar*)scr->mmio)[index];
 }
 
 static uchar
@@ -163,60 +118,53 @@ static void
 mga4xxenable(VGAscr* scr)
 {
 	Pcidev *	pci;
-	int 		size, align;
-	ulong 	aperture;
+	int 		size;
 	int 		i, n, k;
 	uchar *	p;
 	uchar	x[16];
 	uchar	crtcext3;
 
-	/*
-	 * Only once, can't be disabled for now.
-	 * scr->io holds the virtual address of
-	 * the MMIO registers.
-	 */
-	if(scr->io)
+	if(scr->mmio)
 		return;
 
 	pci = mgapcimatch();
 	if(pci == nil)
 		return;
 
-	scr->io = upamalloc(pci->mem[1].bar & ~0x0F, 16*1024, 0);
-	if(scr->io == 0)
+	scr->mmio = vmap(pci->mem[1].bar&~0x0F, 16*1024);
+	if(scr->mmio == nil)
 		return;
-
-	addvgaseg("mga4xxmmio", scr->io, pci->mem[1].size);
-
-	scr->io = (ulong)KADDR(scr->io);
+	
+	addvgaseg("mga4xxmmio", pci->mem[1].bar&~0x0F, pci->mem[1].size);
 
 	/* need to map frame buffer here too, so vga can find memory size */
-	size = 8*Meg;
-	align = 0;
-	aperture = mga4xxlinear(scr, &size, &align);
-	if(aperture) {
-		scr->aperture = aperture;
-		addvgaseg("mga4xxscreen", aperture, size);
+	if(pci->did == MGA4xx)
+		size = 32*MB;
+	else
+		size = 8*MB;
+	vgalinearaddr(scr, pci->mem[0].bar&~0x0F, size);
 
-		/* Find out how much memory is here, some multiple of 2 Meg */
+	if(scr->paddr){
+
+		/* Find out how much memory is here, some multiple of 2 MB */
 
 		/* First Set MGA Mode ... */
 		crtcext3 = crtcextset(scr, 3, 0x80, 0x00);
 
-		p = (uchar*)aperture;
-		n = (size / Meg) / 2;
+		p = scr->vaddr;
+		n = (size / MB) / 2;
 		for (i = 0; i < n; i++) {
-			k = (2*i+1)*Meg;
+			k = (2*i+1)*MB;
 			p[k] = 0;
 			p[k] = i+1;
-			*((uchar*)(scr->io + CACHEFLUSH)) = 0;
+			*((uchar*)scr->mmio + CACHEFLUSH) = 0;
 			x[i] = p[k];
  		}
 		for(i = 1; i < n; i++)
 			if(x[i] != i+1)
 				break;
-  		scr->apsize = 2*i*Meg;
-
+		scr->apsize = 2*i*MB;	/* sketchy */
+		addvgaseg("mga4xxscreen", scr->paddr, scr->apsize);
 		crtcextset(scr, 3, crtcext3, 0xff);
 	}
 }
@@ -240,10 +188,10 @@ dac4xxdisable(VGAscr* scr)
 {
 	uchar * 	dac4xx;
 	
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
 
-	dac4xx = KADDR(scr->io+0x3C00);
+	dac4xx = (uchar*)scr->mmio+0x3C00;
 	
 	*(dac4xx+Index) = Icctl;
 	*(dac4xx+Data) = 0x00;
@@ -256,14 +204,14 @@ dac4xxload(VGAscr* scr, Cursor* curs)
 	uchar *	p;
 	uchar * 	dac4xx;
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
 
-	dac4xx = KADDR(scr->io+0x3C00);
+	dac4xx = (uchar*)scr->mmio+0x3C00;
 	
 	dac4xxdisable(scr);
 
-	p = KADDR(scr->storage);
+	p = scr->vaddr;
 	for(y = 0; y < 64; y++){
 		*p++ = 0; *p++ = 0; *p++ = 0;
 		*p++ = 0; *p++ = 0; *p++ = 0;
@@ -296,10 +244,10 @@ dac4xxmove(VGAscr* scr, Point p)
 	int 		x, y;
 	uchar *	dac4xx;
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return 1;
 
-	dac4xx = KADDR(scr->io + 0x3C00);
+	dac4xx = (uchar*)scr->mmio + 0x3C00;
 
 	x = p.x + scr->offset.x;
 	y = p.y + scr->offset.y;
@@ -319,9 +267,9 @@ dac4xxenable(VGAscr* scr)
 	uchar *	dac4xx;
 	ulong	storage;
 	
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
-	dac4xx = KADDR(scr->io+0x3C00);
+	dac4xx = (uchar*)scr->mmio+0x3C00;
 
 	dac4xxdisable(scr);
 
@@ -332,7 +280,7 @@ dac4xxenable(VGAscr* scr)
 	*(dac4xx+Index) = Icuradrh;
 	*(dac4xx+Data) = 0xff & (storage >> 18);		
 
-	scr->storage = (ulong) KADDR((ulong)scr->aperture + (ulong)storage);
+	scr->storage = (ulong)scr->vaddr + storage;
 
 	/* Show X11-Like Cursor */
 	*(dac4xx+Index) = Icctl;
@@ -380,9 +328,9 @@ mga4xxblank(VGAscr* scr, int blank)
 	/* blank = 0 -> turn screen on */
 	/* blank = 1 -> turn screen off */
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
-	mga = KADDR(scr->io);	
+	mga = (uchar*)scr->mmio;	
 
 	if (blank == 0) {
 		seq1 = 0x00;
@@ -432,9 +380,9 @@ mga4xxfill(VGAscr* scr, Rectangle r, ulong color)
 	uchar * 		mga;
  
 	/* Constant Shaded Trapezoids / Rectangle Fills */
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return 0;
-	mga = KADDR(scr->io);
+	mga = (uchar*)scr->mmio;
 
 	mgawrite32(mga, DWGCTL, 0);
 	mgawrite32(mga, FCOL, color);
@@ -460,10 +408,10 @@ mga4xxscroll(VGAscr* scr, Rectangle r_dst, Rectangle r_src)
 	int 		ydir;
  
 	/* Two-operand Bitblts */
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return 0;
 
-	mga = KADDR(scr->io);
+	mga = (uchar*)scr->mmio;
 
 	pitch = Dx(scr->gscreen->r);
 
@@ -556,9 +504,9 @@ mga4xxdrawinit(VGAscr* scr)
 	if (p == nil)
 		return ;
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
-	mga = KADDR(scr->io);
+	mga = (uchar*)scr->mmio;
 
 	mgawrite32(mga, SRCORG, 0);
 	mgawrite32(mga, DSTORG, 0);
@@ -590,7 +538,7 @@ VGAdev vgamga4xxdev = {
 	mga4xxenable,		/* enable */
 	0,					/* disable */
 	0,					/* page */
-	mga4xxlinear,			/* linear */
+	0,					/* linear */
 	mga4xxdrawinit,
 };
 

+ 27 - 84
sys/src/9/pc/vganeomagic.c

@@ -22,72 +22,20 @@ struct CursorNM {
 	int	addr;
 };
 
-static ulong
-neomagiclinear(VGAscr* scr, int* size, int* align)
-{
-	ulong aperture, oaperture;
-	int oapsize, wasupamem;
-	Pcidev *p;
-
-	oaperture = scr->aperture;
-	oapsize = scr->apsize;
-	wasupamem = scr->isupamem;
-
-	aperture = 0;
-	if(p = pcimatch(nil, 0x10C8, 0)){
-		switch(p->did){
-		case 0x0003:		/* MagicGraph 128ZV */
-		case 0x0083:		/* MagicGraph 128ZV+ */
-		case 0x0004:		/* MagicGraph 128XD */
-		case 0x0005:		/* MagicMedia 256AV */
-		case 0x0006:		/* MagicMedia 256ZX */
-			aperture = p->mem[0].bar & ~0x0F;
-			*size = p->mem[0].size;
-			break;
-		default:
-			break;
-		}
-	}
-
-	if(wasupamem){
-		if(oaperture == aperture)
-			return oaperture;
-		upafree(oaperture, oapsize);
-	}
-	scr->isupamem = 0;
-
-	aperture = upamalloc(aperture, *size, *align);
-//print("neomagiclinear1 %lux %d\n", aperture, *size);
-	if(aperture == 0){
-		if(wasupamem && upamalloc(oaperture, oapsize, 0)){
-			aperture = oaperture;
-			scr->isupamem = 1;
-		}
-		else
-			scr->isupamem = 0;
-	}
-	else
-		scr->isupamem = 1;
-
-	return aperture;
-}
-
 static void
 neomagicenable(VGAscr* scr)
 {
 	Pcidev *p;
-	int align, curoff, size, vmsize;
-	ulong aperture;
+	int curoff, vmsize;
 	ulong ioaddr;
 	ulong iosize;
 
 	/*
-	 * Only once, can't be disabled for now.
-	 * scr->io holds the physical address of the cursor registers
+	 * scr->mmio holds the virtual address of the cursor registers
 	 * in the MMIO space. This may need to change for older chips
 	 * which have the MMIO space offset in the framebuffer region.
 	 */
-	if(scr->io)
+	if(scr->mmio)
 		return;
 	if(p = pcimatch(nil, 0x10C8, 0)){
 		switch(p->did){
@@ -127,11 +75,12 @@ neomagicenable(VGAscr* scr)
 	}
 	else
 		return;
-	scr->io = upamalloc(ioaddr, iosize, 0);
-	if(scr->io == 0)
+	scr->pci = p;
+
+	scr->mmio = vmap(ioaddr, iosize);
+	if(scr->mmio == nil)
 		return;
-	addvgaseg("neomagicmmio", scr->io, iosize);
-	scr->mmio = KADDR(scr->io);
+	addvgaseg("neomagicmmio", ioaddr, iosize);
 
 	/*
 	 * Find a place for the cursor data in display memory.
@@ -139,16 +88,10 @@ neomagicenable(VGAscr* scr)
 	 * last 2KB of the framebuffer.
 	 */
 	scr->storage = vmsize-2*1024;
-	scr->io += curoff;
-
-	size = p->mem[0].size;
-	align = 0;
-	aperture = neomagiclinear(scr, &size, &align);
-	if(aperture) {
-		scr->aperture = aperture;
-		scr->apsize = size;
-		addvgaseg("neomagicscreen", aperture, size);
-	}
+	scr->mmio = (ulong*)((uchar*)scr->mmio + curoff);
+	vgalinearpci(scr);
+	if(scr->paddr)
+		addvgaseg("neomagicscreen", scr->paddr, scr->apsize);
 }
 
 static void
@@ -156,9 +99,9 @@ neomagiccurdisable(VGAscr* scr)
 {
 	CursorNM *cursornm;
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
-	cursornm = KADDR(scr->io);
+	cursornm = (void*)scr->mmio;
 	cursornm->enable = 0;
 }
 
@@ -169,7 +112,7 @@ neomagicinitcursor(VGAscr* scr, int xo, int yo, int index)
 	uint p0, p1;
 	int x, y;
 
-	p = KADDR(scr->aperture);
+	p = (uchar*)scr->mmio;
 	p += scr->storage + index*1024;
 
 	for(y = yo; y < 16; y++){
@@ -211,9 +154,9 @@ neomagiccurload(VGAscr* scr, Cursor* curs)
 {
 	CursorNM *cursornm;
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
-	cursornm = KADDR(scr->io);
+	cursornm = (void*)scr->mmio;
 
 	cursornm->enable = 0;
 	memmove(&scr->Cursor, curs, sizeof(Cursor));
@@ -227,9 +170,9 @@ neomagiccurmove(VGAscr* scr, Point p)
 	CursorNM *cursornm;
 	int addr, index, x, xo, y, yo;
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return 1;
-	cursornm = KADDR(scr->io);
+	cursornm = (void*)scr->mmio;
 
 	index = 0;
 	if((x = p.x+scr->offset.x) < 0){
@@ -266,9 +209,9 @@ neomagiccurenable(VGAscr* scr)
 	CursorNM *cursornm;
 
 	neomagicenable(scr);
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
-	cursornm = KADDR(scr->io);
+	cursornm = (void*)scr->mmio;
 	cursornm->enable = 0;
 
 	/*
@@ -426,7 +369,7 @@ neomagichwfill(VGAscr *scr, Rectangle r, ulong sval)
 		| NEO_BC0_SRC_IS_FG
 		| NEO_BC3_SKIP_MAPPING
 		| GXcopy;
-	mmio[DstStartOff] = scr->aperture
+	mmio[DstStartOff] = scr->paddr
 		+ r.min.y*scr->gscreen->width*BY2WD
 		+ r.min.x*scr->gscreen->depth/BI2BY;
 	mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff);
@@ -452,9 +395,9 @@ neomagichwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
 			| NEO_BC3_FIFO_EN
 			| NEO_BC3_SKIP_MAPPING
 			| GXcopy;
-		mmio[SrcStartOff] = scr->aperture
+		mmio[SrcStartOff] = scr->paddr
 			+ sr.min.y*pitch + sr.min.x*pixel;
-		mmio[DstStartOff] = scr->aperture
+		mmio[DstStartOff] = scr->paddr
 			+ r.min.y*pitch + r.min.x*pixel;
 	} else {
 		/* start from lower-right */
@@ -465,9 +408,9 @@ neomagichwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
 			| NEO_BC3_FIFO_EN
 			| NEO_BC3_SKIP_MAPPING
 			| GXcopy;
-		mmio[SrcStartOff] = scr->aperture
+		mmio[SrcStartOff] = scr->paddr
 			+ (sr.max.y-1)*pitch + (sr.max.x-1)*pixel;
-		mmio[DstStartOff] = scr->aperture
+		mmio[DstStartOff] = scr->paddr
 			+ (r.max.y-1)*pitch + (r.max.x-1)*pixel;
 	}
 	mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff);
@@ -549,7 +492,7 @@ VGAdev vganeomagicdev = {
 	neomagicenable,
 	nil,
 	nil,
-	neomagiclinear,
+	nil,
 	neomagicdrawinit,
 };
 

+ 29 - 74
sys/src/9/pc/vganvidia.c

@@ -77,8 +77,6 @@ struct {
 	int		dmamax;
 } nv;
 
-
-/* Nvidia is good about backwards compatibility -- any did >= 0x20 is fine */
 static Pcidev*
 nvidiapci(void)
 {
@@ -92,83 +90,40 @@ nvidiapci(void)
 	return nil;
 }
 
-static ulong
-nvidialinear(VGAscr* scr, int* size, int* align)
+static void
+nvidialinear(VGAscr*, int, int)
 {
-	Pcidev *p;
-	int oapsize, wasupamem;
-	ulong aperture, oaperture;
-
-	oaperture = scr->aperture;
-	oapsize = scr->apsize;
-	wasupamem = scr->isupamem;
-
-	aperture = 0;
-	if(p = nvidiapci()){
-		aperture = p->mem[1].bar & ~0x0F;
-		*size = p->mem[1].size;
-	}
-
-	if(wasupamem){
-		if(oaperture == aperture)
-			return oaperture;
-		upafree(oaperture, oapsize);
-	}
-	scr->isupamem = 0;
-
-	aperture = upamalloc(aperture, *size, *align);
-	if(aperture == 0){
-		if(wasupamem && upamalloc(oaperture, oapsize, 0)){
-			aperture = oaperture;
-			scr->isupamem = 1;
-		}
-		else
-			scr->isupamem = 0;
-	}
-	else
-		scr->isupamem = 1;
-
-	return aperture;
 }
 
 static void
 nvidiaenable(VGAscr* scr)
 {
 	Pcidev *p;
-	ulong aperture, *q;
-	int align, size, tmp;
-
-	/*
-	 * Only once, can't be disabled for now.
-	 * scr->io holds the physical address of
-	 * the MMIO registers.
-	 */
-	if(scr->io)
+	ulong *q;
+	int tmp;
+
+	if(scr->mmio)
 		return;
 	p = nvidiapci();
 	if(p == nil)
 		return;
 	scr->id = p->did;
+	scr->pci = p;
 
-	scr->io = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
-	if(scr->io == 0)
+	scr->mmio = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);
+	if(scr->mmio == nil)
 		return;
-	addvgaseg("nvidiammio", scr->io, p->mem[0].size);
-
-	size = p->mem[1].size;
-	align = 0;
-	aperture = nvidialinear(scr, &size, &align);
-	if(aperture){
-		scr->aperture = aperture;
-		scr->apsize = size;
-		addvgaseg("nvidiascreen", aperture, size);
-	}
+	addvgaseg("nvidiammio", p->mem[0].bar&~0x0F, p->mem[0].size);
+
+	vgalinearpci(scr);
+	if(scr->apsize)
+		addvgaseg("nvidiascreen", scr->paddr, scr->apsize);
 
 	/* find video memory size */
 	switch (scr->id & 0x0ff0) {
 	case 0x0020:
 	case 0x00A0:
-		q = KADDR(scr->io + Pfb);
+		q = (void*)((uchar*)scr->mmio + Pfb);
 		tmp = *q;
 		if (tmp & 0x0100) {
 			scr->storage = ((tmp >> 12) & 0x0F) * 1024 + 1024 * 2;
@@ -191,7 +146,7 @@ nvidiaenable(VGAscr* scr)
 		scr->storage = (((tmp >> 4) & 127) + 1) * 1024 * 1024;
 		break;
 	default:
-		q = KADDR(scr->io + Pfb +  0x020C);
+		q = (void*)((uchar*)scr->mmio + Pfb +  0x020C);
 		tmp = (*q >> 20) & 0xFF;
 		if (tmp == 0)
 			tmp = 16;
@@ -203,7 +158,7 @@ nvidiaenable(VGAscr* scr)
 static void
 nvidiacurdisable(VGAscr* scr)
 {
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
 
 	vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) & ~0x01);
@@ -218,7 +173,7 @@ nvidiacurload(VGAscr* scr, Cursor* curs)
 	ushort	c,s;
 	ulong	tmp;
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
 
 	vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) & ~0x01);
@@ -226,10 +181,10 @@ nvidiacurload(VGAscr* scr, Cursor* curs)
 	switch (scr->id & 0x0ff0) {
 	case 0x0020:
 	case 0x00A0:
-		p = KADDR(scr->io + Pramin + 0x1E00 * 4);
+		p = (void*)((uchar*)scr->mmio + Pramin + 0x1E00 * 4);
 		break;
 	default:
-		p = KADDR(scr->aperture + scr->storage - 96*1024);
+		p = (void*)((uchar*)scr->vaddr + scr->storage - 96*1024);
 		break;
 	}
 
@@ -268,10 +223,10 @@ nvidiacurmove(VGAscr* scr, Point p)
 {
 	ulong*	cursorpos;
 
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return 1;
 
-	cursorpos = KADDR(scr->io + hwCurPos);
+	cursorpos = (void*)((uchar*)scr->mmio + hwCurPos);
 	*cursorpos = ((p.y+scr->offset.y)<<16)|((p.x+scr->offset.x) & 0xFFFF);
 
 	return 0;
@@ -281,7 +236,7 @@ static void
 nvidiacurenable(VGAscr* scr)
 {
 	nvidiaenable(scr);
-	if(scr->io == 0)
+	if(scr->mmio == 0)
 		return;
 
 	vgaxo(Crtx, 0x1F, 0x57);
@@ -299,9 +254,9 @@ writeput(VGAscr *scr, int data)
 	ulong	*fifo;
 
 	outb(0x3D0,0);
-	p=KADDR(scr->aperture);
+	p = scr->vaddr;
 	scratch = *p;
-	fifo = KADDR(scr->io + Fifo);
+	fifo = (void*)((uchar*)scr->mmio + Fifo);
 	fifo[0x10] = (data << 2);
 	USED(scratch);
 }
@@ -311,7 +266,7 @@ readget(VGAscr *scr)
 {
 	ulong	*fifo;
 
-	fifo = KADDR(scr->io + Fifo);
+	fifo = (void*)((uchar*)scr->mmio + Fifo);
 	return (fifo[0x0011] >> 2);
 }
 
@@ -375,7 +330,7 @@ waitforidle(VGAscr *scr)
 	ulong*	pgraph;
 	int x;
 
-	pgraph = KADDR(scr->io + Pgraph);
+	pgraph = (void*)((uchar*)scr->mmio + Pgraph);
 
 	x = 0;
 	while((readget(scr) != nv.dmaput) && x++ < 1000000)
@@ -388,7 +343,7 @@ waitforidle(VGAscr *scr)
 		;
 
 	if(x >= 1000000)
-		iprint("idle stat %lud scrio %.8lux scr %p pc %luX\n", *pgraph, scr->io, scr, getcallerpc(&scr));
+		iprint("idle stat %lud scrio %.8lux scr %p pc %luX\n", *pgraph, scr->mmio, scr, getcallerpc(&scr));
 }
 
 static void
@@ -399,7 +354,7 @@ nvresetgraphics(VGAscr *scr)
 
 	pitch = scr->gscreen->width*BY2WD;
 
-	nv.dmabase = KADDR(scr->aperture + scr->storage - 128*1024);
+	nv.dmabase = (void*)((uchar*)scr->vaddr + scr->storage - 128*1024);
 
 	for(i=0; i<SKIPS; i++)
 		nv.dmabase[i] = 0x00000000;

Some files were not shown because too many files changed in this diff